From f2b6685c4a17d8ef981d6a5b0429b986743b021f Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Mon, 14 Oct 2024 18:14:51 +0200 Subject: [PATCH 1/2] Add more accurate implementation of transferable balance --- src/helpers/substrate.ts | 13 +++++++++++++ src/shared/useAccountBalance.ts | 11 ++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/helpers/substrate.ts b/src/helpers/substrate.ts index 17a87f07..0525d295 100644 --- a/src/helpers/substrate.ts +++ b/src/helpers/substrate.ts @@ -1,5 +1,18 @@ +import Big from 'big.js'; import { EventRecord } from '@polkadot/types/interfaces'; import { ApiPromise } from '@polkadot/api'; +import { nativeToDecimal } from '../shared/parseNumbers/metric'; + +// Defined [here](https://github.com/pendulum-chain/pendulum/blob/63bd13abbe089308f9702925697dba22d7792eba/runtime/common/src/lib.rs#L55) +const EXISTENTIAL_DEPOSIT = nativeToDecimal(1_000_000_000); + +// Calculate the transferable balance. It's calculated as `transferable = free - max(frozen - reserved, ED)`, +// see [here](https://wiki.polkadot.network/docs/learn-guides-accounts#query-account-data-in-polkadot-js). +export function calculateTransferableBalance(free: Big, frozen: Big, reserved: Big) { + // Emulate Math.max + const max = frozen.minus(reserved).gt(EXISTENTIAL_DEPOSIT) ? frozen.minus(reserved) : EXISTENTIAL_DEPOSIT; + return free.minus(max); +} export function containsError(events: EventRecord[], api: ApiPromise): boolean { const errorEvents = events diff --git a/src/shared/useAccountBalance.ts b/src/shared/useAccountBalance.ts index 002f3548..299a5e7d 100644 --- a/src/shared/useAccountBalance.ts +++ b/src/shared/useAccountBalance.ts @@ -5,6 +5,7 @@ import { emptyCacheKey, QueryOptions } from './helpers'; import { nativeToDecimal, prettyNumbers } from './parseNumbers/metric'; import { useSharedState } from './Provider'; import { cacheKeys } from '../constants/cache'; +import { calculateTransferableBalance } from '../helpers/substrate'; export interface UseAccountBalanceResponse { query: UseQueryResult; @@ -50,11 +51,11 @@ export const useAccountBalance = ( const { free: freeRaw, frozen: frozenRaw, reserved: reservedRaw } = data.data; - const free = nativeToDecimal(freeRaw || 0, decimals).toNumber(); - const frozen = nativeToDecimal(frozenRaw || 0, decimals).toNumber(); - const reserved = nativeToDecimal(reservedRaw || 0, decimals).toNumber(); - const total = prettyNumbers(free); - const transferable = prettyNumbers(free - frozen - reserved); + const free = nativeToDecimal(freeRaw || 0, decimals); + const frozen = nativeToDecimal(frozenRaw || 0, decimals); + const reserved = nativeToDecimal(reservedRaw || 0, decimals); + const total = prettyNumbers(free.toNumber()); + const transferable = prettyNumbers(calculateTransferableBalance(free, frozen, reserved).toNumber()); return { total, transferable }; }, [data, decimals]); From b84d267d286c362de7a1a1cdf9f413a67b3a9edb Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Mon, 14 Oct 2024 18:15:05 +0200 Subject: [PATCH 2/2] Use transferable balance for wallet button --- src/components/Wallet/modals/DisconnectModal/index.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/Wallet/modals/DisconnectModal/index.tsx b/src/components/Wallet/modals/DisconnectModal/index.tsx index 2d5dedd8..927e0840 100644 --- a/src/components/Wallet/modals/DisconnectModal/index.tsx +++ b/src/components/Wallet/modals/DisconnectModal/index.tsx @@ -77,10 +77,11 @@ const WalletDropdownMenu = ({ export const DisconnectModal = () => { const { walletAccount, removeWalletAccount } = useGlobalState(); - const { query, balances } = useAccountBalance(); const { ss58Format, tokenSymbol } = useNodeInfoState().state; const { wallet, address } = walletAccount || {}; - const { total: balance } = balances; + + const { query, balances } = useAccountBalance(); + const { transferable: transferableBalance } = balances; if (!address) return <>; @@ -89,7 +90,7 @@ export const DisconnectModal = () => { @@ -97,7 +98,7 @@ export const DisconnectModal = () => { walletAccount={walletAccount} ss58Format={ss58Format} address={address} - balance={balance} + balance={transferableBalance} tokenSymbol={tokenSymbol} removeWalletAccount={removeWalletAccount} />