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