From c84bdcb39cf4dd78d11e88f7497c824cfcf766fd Mon Sep 17 00:00:00 2001 From: Ryan Lee Date: Tue, 27 Feb 2024 17:12:48 -0500 Subject: [PATCH 1/7] feat(lc-dapp): account balance --- examples/light-client-dapp/package.json | 7 +- .../src/components/Transfer.tsx | 82 ++++++- pnpm-lock.yaml | 205 +++++++++++++++--- 3 files changed, 248 insertions(+), 46 deletions(-) diff --git a/examples/light-client-dapp/package.json b/examples/light-client-dapp/package.json index 6d651d064..8442a15ce 100644 --- a/examples/light-client-dapp/package.json +++ b/examples/light-client-dapp/package.json @@ -11,10 +11,15 @@ }, "dependencies": { "@picocss/pico": "^2.0.3", + "@polkadot-api/client": "0.0.1-86c37582599a5aaa7c2dde1d765f8af5ef6def2a.1.0", + "@polkadot-api/metadata-builders": "0.0.1-86c37582599a5aaa7c2dde1d765f8af5ef6def2a.1.0", + "@polkadot-api/substrate-client": "0.0.1-86c37582599a5aaa7c2dde1d765f8af5ef6def2a.1.0", "@polkadot-api/utils": "0.0.1-86c37582599a5aaa7c2dde1d765f8af5ef6def2a.1.0", "@polkadot-labs/hdkd-helpers": "^0.0.5", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-select": "^5.8.0", + "rxjs": "^7.8.1" }, "devDependencies": { "@substrate/unstable-wallet-provider": "workspace:^", diff --git a/examples/light-client-dapp/src/components/Transfer.tsx b/examples/light-client-dapp/src/components/Transfer.tsx index 2d9e2efc8..b31220bbe 100644 --- a/examples/light-client-dapp/src/components/Transfer.tsx +++ b/examples/light-client-dapp/src/components/Transfer.tsx @@ -2,11 +2,53 @@ import { FormEvent, useCallback, useEffect, useState } from "react" import { ss58Decode } from "@polkadot-labs/hdkd-helpers" import { UnstableWallet } from "@substrate/unstable-wallet-provider" import { toHex } from "@polkadot-api/utils" +import { filter, firstValueFrom } from "rxjs" +import { getObservableClient } from "@polkadot-api/client" +import { ConnectProvider, createClient } from "@polkadot-api/substrate-client" +import { getDynamicBuilder } from "@polkadot-api/metadata-builders" +import Select from "react-select" + +type SystemAccountStorage = { + consumers: number + data: { + flags: bigint + free: bigint + frozen: bigint + reserved: bigint + } + nonce: number + providers: number + sufficients: number +} type Props = { provider: UnstableWallet.Provider } +const getBalance = (provider: ConnectProvider) => async (address: string) => { + const client = getObservableClient(createClient(provider)) + + const { metadata$, unfollow, storage$ } = client.chainHead$() + + const metadata = await firstValueFrom(metadata$.pipe(filter(Boolean))) + const dynamicBuilder = getDynamicBuilder(metadata) + const storageAccount = dynamicBuilder.buildStorage("System", "Account") + + const balanceQuery$ = storage$(null, "value", () => + storageAccount.enc(address), + ) + + const storageResult = storageAccount.dec( + await firstValueFrom(balanceQuery$.pipe(filter(Boolean))), + ) as SystemAccountStorage + const balance = storageResult.data.free + + unfollow() + client.destroy() + + return balance +} + // FIXME: use dynamic chainId // Westend chainId const chainId = @@ -14,6 +56,12 @@ const chainId = export const Transfer = ({ provider }: Props) => { const [accounts, setAccounts] = useState([]) + const [selectedAccount, setSelectedAccount] = useState<{ + value: string + label: string + } | null>(null) + const [balance, setBalance] = useState(0n) + useEffect(() => { provider.getAccounts(chainId).then((accounts) => { setAccounts(accounts) @@ -40,9 +88,23 @@ export const Transfer = ({ provider }: Props) => { [provider, accounts], ) + const accountOptions = accounts.map((account) => ({ + value: account.address, + label: account.address, + })) + + useEffect(() => { + if (!selectedAccount) { + return + } + + getBalance(provider.getChains()[chainId].connect)( + selectedAccount.value, + ).then(setBalance) + }, [provider, selectedAccount]) + // TODO: handle form fields and submission with react // TODO: fetch accounts from extension - // TODO: fetch selected account balance // TODO: validate destination address // TODO: use PAPI to encode the transaction calldata // TODO: transfer should trigger an extension popup that signs the transaction @@ -52,17 +114,13 @@ export const Transfer = ({ provider }: Props) => {
Transfer funds
- - Balance: 123456789 +