1
0

Login is now possible

This commit is contained in:
Jon Michael Aanes 2024-06-10 00:23:28 +02:00
parent cc442b3a2e
commit a812a42bde
Signed by: Jmaa
SSH Key Fingerprint: SHA256:Ab0GfHGCblESJx7JRE4fj4bFy/KRpeLhi41y4pF3sNA
4 changed files with 37 additions and 170 deletions

View File

@ -2,6 +2,9 @@
* Copyright (C) 2024 Jon Michael Aanes * Copyright (C) 2024 Jon Michael Aanes
*/ */
import {
setupWalletWidget,
} from "../token/WalletIntegration";
import BN from "bn.js"; import BN from "bn.js";
import { LittleEndianByteInput } from "@secata-public/bitmanipulation-ts"; import { LittleEndianByteInput } from "@secata-public/bitmanipulation-ts";
import { BlockchainAddress, StateBytes } from "@partisiablockchain/abi-client"; import { BlockchainAddress, StateBytes } from "@partisiablockchain/abi-client";
@ -217,6 +220,10 @@ async function get_token_state(tokenAddress: BlockchainAddress): Promise<TokenSt
} }
function setup() { function setup() {
// Setup wallet widget
setupWalletWidget();
// Setup routes
for (let router of ROUTERS) { for (let router of ROUTERS) {
console.log(router); console.log(router);
get_contract_state(router, deserializeRouterState).then((state) => { get_contract_state(router, deserializeRouterState).then((state) => {

View File

@ -21,7 +21,6 @@ import { ContractAbi, BlockchainAddress } from "@partisiablockchain/abi-client";
import { ShardedClient } from "../client/ShardedClient"; import { ShardedClient } from "../client/ShardedClient";
import { TokenContract } from "../shared/TokenContract"; import { TokenContract } from "../shared/TokenContract";
import { TransactionApi } from "../client/TransactionApi"; import { TransactionApi } from "../client/TransactionApi";
import { updateContractState } from "./WalletIntegration";
import { NETWORK } from "../constant"; import { NETWORK } from "../constant";
export const CLIENT = new ShardedClient(NETWORK.node_base_url, NETWORK.network_shards); export const CLIENT = new ShardedClient(NETWORK.node_base_url, NETWORK.network_shards);
@ -33,7 +32,6 @@ type TokenContractCreator = (
let lastBalanceKey: string | undefined; let lastBalanceKey: string | undefined;
let contractAddress: BlockchainAddress | undefined; let contractAddress: BlockchainAddress | undefined;
let currentAccount: ConnectedWallet | undefined;
let contractAbi: ContractAbi | undefined; let contractAbi: ContractAbi | undefined;
let tokenApi: TokenContract | undefined; let tokenApi: TokenContract | undefined;
@ -47,19 +45,6 @@ export function setTokenContractType(creator: TokenContractCreator) {
tokenContractCreator = creator; tokenContractCreator = creator;
} }
export const setAccount = (account: ConnectedWallet | undefined) => {
currentAccount = account;
setTokenApi();
};
export const resetAccount = () => {
currentAccount = undefined;
};
export const isConnected = () => {
return currentAccount != null;
};
export const setContractAbi = (abi: ContractAbi) => { export const setContractAbi = (abi: ContractAbi) => {
contractAbi = abi; contractAbi = abi;
setTokenApi(); setTokenApi();
@ -71,9 +56,6 @@ export const getContractAbi = () => {
const setTokenApi = () => { const setTokenApi = () => {
let transactionApi = undefined; let transactionApi = undefined;
if (currentAccount != undefined) {
transactionApi = new TransactionApi(CLIENT, currentAccount, updateContractState);
}
tokenApi = tokenContractCreator(CLIENT, transactionApi); tokenApi = tokenContractCreator(CLIENT, transactionApi);
}; };

View File

@ -20,19 +20,10 @@ import {
setTokenContractType, setTokenContractType,
getTokenApi, getTokenApi,
getContractAddress, getContractAddress,
isConnected,
setContractAddress, setContractAddress,
} from "./AppState"; } from "./AppState";
import { import {
connectMetaMaskWalletClick, setupWalletWidget,
connectMpcWalletClick,
connectLedgerWalletClick,
connectPrivateKeyWalletClick,
validateLedgerConnectionClick,
disconnectWalletClick,
fetchAndDisplayMoreBalances,
updateContractState,
updateInteractionVisibility,
} from "./WalletIntegration"; } from "./WalletIntegration";
import { TokenV1Contract } from "./contract/TokenV1Contract"; import { TokenV1Contract } from "./contract/TokenV1Contract";
import { TokenV2Contract } from "./contract/TokenV2Contract"; import { TokenV2Contract } from "./contract/TokenV2Contract";
@ -43,28 +34,8 @@ import { TransactionFailedError } from "../client/TransactionApi";
import { PutTransactionWasSuccessful } from "../client/TransactionData"; import { PutTransactionWasSuccessful } from "../client/TransactionData";
import { NETWORK } from "../constant"; import { NETWORK } from "../constant";
// Setup event listener to connect to the MPC wallet browser extension // Setup wallet widget
const connectWallet = <Element>document.querySelector("#wallet-connect-btn"); setupWalletWidget();
connectWallet.addEventListener("click", connectMpcWalletClick);
// Setup event listener to connect to the MetaMask snap
const metaMaskConnect = <Element>document.querySelector("#metamask-connect-btn");
metaMaskConnect.addEventListener("click", connectMetaMaskWalletClick);
// Setup event listener to connect to the ledger snap
const ledgerConnect = <Element>document.querySelector("#ledger-connect-btn");
ledgerConnect.addEventListener("click", connectLedgerWalletClick);
const ledgerConnectValidate = <Element>document.querySelector("#connection-link-ledger-validate");
ledgerConnectValidate.addEventListener("click", validateLedgerConnectionClick);
// Setup event listener to login using private key
const pkConnect = <Element>document.querySelector("#private-key-connect-btn");
pkConnect.addEventListener("click", connectPrivateKeyWalletClick);
// Setup event listener to drop the connection again
const disconnectWallet = <Element>document.querySelector("#wallet-disconnect-btn");
disconnectWallet.addEventListener("click", disconnectWalletClick);
// Setup event listener that sends a transfer transaction to the contract. // Setup event listener that sends a transfer transaction to the contract.
// This requires that a wallet has been connected. // This requires that a wallet has been connected.
@ -75,15 +46,9 @@ transferBtn.addEventListener("click", transferAction);
const addressBtn = <Element>document.querySelector("#address-btn"); const addressBtn = <Element>document.querySelector("#address-btn");
addressBtn.addEventListener("click", contractAddressClick); addressBtn.addEventListener("click", contractAddressClick);
const updateStateBtn = <Element>document.querySelector("#update-state-btn");
updateStateBtn.addEventListener("click", updateContractState);
const getBalanceBtn = <Element>document.querySelector("#get-balance-btn"); const getBalanceBtn = <Element>document.querySelector("#get-balance-btn");
getBalanceBtn.addEventListener("click", getBalance); getBalanceBtn.addEventListener("click", getBalance);
const loadMoreBtn = <Element>document.querySelector("#balances-load-more-btn");
loadMoreBtn.addEventListener("click", fetchAndDisplayMoreBalances);
function setModeText(modeText: string) { function setModeText(modeText: string) {
let items = document.querySelectorAll("title"); let items = document.querySelectorAll("title");
items.forEach((item) => { items.forEach((item) => {
@ -125,8 +90,6 @@ function setContractAddressUI(address: BlockchainAddress) {
currentAddress.href = `${NETWORK.browser_base_url}/contracts/${address.asString()}`; currentAddress.href = `${NETWORK.browser_base_url}/contracts/${address.asString()}`;
inputAddress.value = address.asString(); inputAddress.value = address.asString();
setContractAddress(address); setContractAddress(address);
updateInteractionVisibility();
updateContractState();
} }
/** Function for the contract address form. /** Function for the contract address form.
@ -159,23 +122,13 @@ function setTransactionLink(transaction: PutTransactionWasSuccessful) {
function transferAction() { function transferAction() {
const api = getTokenApi(); const api = getTokenApi();
const contractAddress = getContractAddress(); const contractAddress = getContractAddress();
if (isConnected() && api !== undefined && contractAddress !== undefined) { if (false && api !== undefined && contractAddress !== undefined) {
const to = <HTMLInputElement>document.querySelector("#address-to"); const to = <HTMLInputElement>document.querySelector("#address-to");
const amount = <HTMLInputElement>document.querySelector("#amount"); const amount = <HTMLInputElement>document.querySelector("#amount");
const memo = <HTMLInputElement>document.querySelector("#memo"); const memo = <HTMLInputElement>document.querySelector("#memo");
transactionErrorMessage.innerHTML = '<div class="loader"></div>'; transactionErrorMessage.innerHTML = '<div class="loader"></div>';
transactionLinkElement.innerText = ""; transactionLinkElement.innerText = "";
api
.transfer(contractAddress, BlockchainAddress.fromString(to.value), new BN(amount.value, 10), memo.value)
.then(setTransactionLink)
.catch((error) => {
console.error(error);
if (error instanceof TransactionFailedError) {
setTransactionLink(error.putTransaction);
}
transactionErrorMessage.innerText = error;
});
} }
} }

View File

@ -16,15 +16,6 @@
* *
*/ */
import {
resetAccount,
setAccount,
getContractAddress,
isConnected,
getContractLastBalanceKey,
setContractLastBalanceKey,
getTokenApi,
} from "./AppState";
import { ConnectedWallet } from "../shared/ConnectedWallet"; import { ConnectedWallet } from "../shared/ConnectedWallet";
import { connectMetaMask } from "../shared/MetaMaskIntegration"; import { connectMetaMask } from "../shared/MetaMaskIntegration";
import { connectMpcWallet } from "../shared/MpcWalletIntegration"; import { connectMpcWallet } from "../shared/MpcWalletIntegration";
@ -32,6 +23,8 @@ import { connectLedger, validateLedgerConnection } from "../shared/LedgerIntegra
import { connectPrivateKey } from "../shared/PrivateKeyIntegration"; import { connectPrivateKey } from "../shared/PrivateKeyIntegration";
import { CryptoUtils } from "../client/CryptoUtils"; import { CryptoUtils } from "../client/CryptoUtils";
let CURRENT_ACCOUNT: ConnectedWallet | undefined;
/** /**
* Function for connecting to the MPC wallet and setting the connected wallet in the app state. * Function for connecting to the MPC wallet and setting the connected wallet in the app state.
*/ */
@ -78,11 +71,11 @@ export const connectPrivateKeyWalletClick = () => {
*/ */
const handleWalletConnect = (connect: Promise<ConnectedWallet>) => { const handleWalletConnect = (connect: Promise<ConnectedWallet>) => {
// Clean up state // Clean up state
resetAccount(); CURRENT_ACCOUNT = undefined;
setConnectionStatus("Connecting..."); setConnectionStatus("Connecting...");
connect connect
.then((userAccount) => { .then((userAccount) => {
setAccount(userAccount); CURRENT_ACCOUNT = userAccount;
// Fix UI // Fix UI
setConnectionStatus("Logged in: ", userAccount.address); setConnectionStatus("Logged in: ", userAccount.address);
@ -91,7 +84,6 @@ const handleWalletConnect = (connect: Promise<ConnectedWallet>) => {
setVisibility("#ledger-connect", false); setVisibility("#ledger-connect", false);
setVisibility("#private-key-connect", false); setVisibility("#private-key-connect", false);
setVisibility("#wallet-disconnect", true); setVisibility("#wallet-disconnect", true);
updateInteractionVisibility();
}) })
.catch((error) => { .catch((error) => {
console.error(error); console.error(error);
@ -107,7 +99,7 @@ const handleWalletConnect = (connect: Promise<ConnectedWallet>) => {
* Reset state to disconnect current user. * Reset state to disconnect current user.
*/ */
export const disconnectWalletClick = () => { export const disconnectWalletClick = () => {
resetAccount(); CURRENT_ACCOUNT = undefined;
setConnectionStatus("Disconnected account"); setConnectionStatus("Disconnected account");
setVisibility("#wallet-connect", true); setVisibility("#wallet-connect", true);
setVisibility("#metamask-connect", true); setVisibility("#metamask-connect", true);
@ -115,58 +107,6 @@ export const disconnectWalletClick = () => {
setVisibility("#private-key-connect", true); setVisibility("#private-key-connect", true);
setVisibility("#wallet-disconnect", false); setVisibility("#wallet-disconnect", false);
setVisibility("#connection-link-ledger-validate", false); setVisibility("#connection-link-ledger-validate", false);
updateInteractionVisibility();
};
const ALL_BALANCES_LIST = <HTMLElement>document.querySelector("#all-balances");
/**
* Write some of the state to the UI.
*/
export const updateContractState = () => {
const address = getContractAddress();
if (address === undefined) {
throw new Error("No address provided");
}
const tokenApi = getTokenApi();
if (tokenApi === undefined) {
throw new Error("Token API not setup");
}
const refreshLoader = <HTMLInputElement>document.querySelector("#refresh-loader");
refreshLoader.classList.remove("hidden");
if (tokenApi.basicState != undefined) {
tokenApi.basicState(address).then((state) => {
const stateHeader = <HTMLInputElement>document.querySelector("#state-header");
const updateStateButton = <HTMLInputElement>document.querySelector("#update-state");
stateHeader.classList.remove("hidden");
updateStateButton.classList.remove("hidden");
const name = <HTMLElement>document.querySelector("#name");
name.innerHTML = `${state.name}`;
const decimals = <HTMLElement>document.querySelector("#decimals");
decimals.innerHTML = `${state.decimals}`;
const symbol = <HTMLElement>document.querySelector("#symbol");
symbol.innerHTML = `${state.symbol}`;
const owner = <HTMLElement>document.querySelector("#owner");
owner.innerHTML = `${state.owner.asString()}`;
const totalSupply = <HTMLElement>document.querySelector("#total-supply");
totalSupply.innerHTML = `${state.totalSupply}`;
const contractState = <HTMLElement>document.querySelector("#contract-state");
contractState.classList.remove("hidden");
refreshLoader.classList.add("hidden");
});
}
setContractLastBalanceKey(undefined);
ALL_BALANCES_LIST.innerHTML = "";
fetchAndDisplayMoreBalances();
}; };
function setConnectionStatus(status: string, address: string | undefined = undefined) { function setConnectionStatus(status: string, address: string | undefined = undefined) {
@ -190,42 +130,27 @@ const setVisibility = (selector: string, visible: boolean) => {
} }
}; };
export const updateInteractionVisibility = () => { export function setupWalletWidget() {
const contractInteraction = <HTMLElement>document.querySelector("#contract-interaction"); // Setup event listener to connect to the MPC wallet browser extension
if (isConnected() && getContractAddress() !== undefined) { const connectWallet = <Element>document.querySelector("#wallet-connect-btn");
contractInteraction.classList.remove("hidden"); connectWallet.addEventListener("click", connectMpcWalletClick);
} else {
contractInteraction.classList.add("hidden");
}
};
export const fetchAndDisplayMoreBalances = () => { // Setup event listener to connect to the MetaMask snap
const address = getContractAddress(); const metaMaskConnect = <Element>document.querySelector("#metamask-connect-btn");
if (address == undefined) { metaMaskConnect.addEventListener("click", connectMetaMaskWalletClick);
throw new Error("Address not set");
}
const tokenApi = getTokenApi();
if (tokenApi === undefined) {
throw new Error("Token API not setup");
}
if (tokenApi.tokenBalances == undefined) {
return; // Contract doesn't support tokenBalances
}
const lastKey = getContractLastBalanceKey(); // Setup event listener to connect to the ledger snap
tokenApi.tokenBalances(address, lastKey).then((balancesResult) => { const ledgerConnect = <Element>document.querySelector("#ledger-connect-btn");
balancesResult.balances.forEach((amount, tokenOwner) => { ledgerConnect.addEventListener("click", connectLedgerWalletClick);
const balance = document.createElement("li");
balance.innerHTML = `<span class="address">${tokenOwner.asString()}</span>: ${amount}`;
ALL_BALANCES_LIST.appendChild(balance);
});
setContractLastBalanceKey(balancesResult.next_cursor);
const loadMoreBtn = <Element>document.querySelector("#balances-load-more-btn"); const ledgerConnectValidate = <Element>document.querySelector("#connection-link-ledger-validate");
if (balancesResult.next_cursor === undefined) { ledgerConnectValidate.addEventListener("click", validateLedgerConnectionClick);
loadMoreBtn.classList.add("hidden");
} else { // Setup event listener to login using private key
loadMoreBtn.classList.remove("hidden"); const pkConnect = <Element>document.querySelector("#private-key-connect-btn");
} pkConnect.addEventListener("click", connectPrivateKeyWalletClick);
});
}; // Setup event listener to drop the connection again
const disconnectWallet = <Element>document.querySelector("#wallet-disconnect-btn");
disconnectWallet.addEventListener("click", disconnectWalletClick);
}