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} /> 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]);