From 8b962f27a6ef105a944063d16a13fad39bd40024 Mon Sep 17 00:00:00 2001 From: tarikgul Date: Sun, 18 Aug 2024 11:12:28 -0400 Subject: [PATCH 1/4] Rework api.derive.balance.account to work with the new frame account data --- packages/api-derive/src/balances/account.ts | 72 +++++++++++++++------ packages/api-derive/src/balances/types.ts | 5 ++ 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/packages/api-derive/src/balances/account.ts b/packages/api-derive/src/balances/account.ts index 087cfc87c557..7bfc3a7a5d72 100644 --- a/packages/api-derive/src/balances/account.ts +++ b/packages/api-derive/src/balances/account.ts @@ -4,6 +4,7 @@ import type { Observable } from 'rxjs'; import type { QueryableStorageEntry } from '@polkadot/api-base/types'; import type { AccountData, AccountId, AccountIndex, AccountInfo, Address, Balance, Index } from '@polkadot/types/interfaces'; +import type { FrameSystemAccountInfo, PalletBalancesAccountData } from '@polkadot/types/lookup'; import type { ITuple } from '@polkadot/types/types'; import type { DeriveApi, DeriveBalancesAccount, DeriveBalancesAccountData } from '../types.js'; @@ -15,7 +16,9 @@ import { memo } from '../util/index.js'; type BalanceResult = [Balance, Balance, Balance, Balance]; -type Result = [Index, BalanceResult[]]; +type Result = [Index, BalanceResult[], AccountType]; + +interface AccountType { isFrameAccountData: boolean } type DeriveCustomAccount = DeriveApi['derive'] & Record getBalance(api, b)) - }, getBalance(api, primary)); + additional: additional.map((b) => getBalance(api, b, accType)) + }, getBalance(api, primary, accType)); } // old @@ -54,7 +72,8 @@ function queryBalancesFree (api: DeriveApi, accountId: AccountId): Observable [ accountNonce, - [[freeBalance, reservedBalance, zeroBalance(api), zeroBalance(api)]] + [[freeBalance, reservedBalance, zeroBalance(api), zeroBalance(api)]], + { isFrameAccountData: false } ]) ); } @@ -62,7 +81,8 @@ function queryBalancesFree (api: DeriveApi, accountId: AccountId): Observable { const fill = (nonce: Index): Result => [ nonce, - [[zeroBalance(api), zeroBalance(api), zeroBalance(api), zeroBalance(api)]] + [[zeroBalance(api), zeroBalance(api), zeroBalance(api), zeroBalance(api)]], + { isFrameAccountData: false } ]; return isFunction(api.query.system.account) @@ -83,7 +103,8 @@ function queryBalancesAccount (api: DeriveApi, accountId: AccountId, modules: st const extract = (nonce: Index, data: AccountData[]): Result => [ nonce, - data.map(({ feeFrozen, free, miscFrozen, reserved }): BalanceResult => [free, reserved, feeFrozen, miscFrozen]) + data.map(({ feeFrozen, free, miscFrozen, reserved }): BalanceResult => [free, reserved, feeFrozen, miscFrozen]), + { isFrameAccountData: false } ]; // NOTE this is for the first case where we do have instances specified @@ -106,7 +127,7 @@ function queryBalancesAccount (api: DeriveApi, accountId: AccountId, modules: st function querySystemAccount (api: DeriveApi, accountId: AccountId): Observable { // AccountInfo is current, support old, eg. Edgeware - return api.query.system.account>(accountId).pipe( + return api.query.system.account>(accountId).pipe( map((infoOrTuple): Result => { const data = (infoOrTuple as AccountInfo).nonce ? (infoOrTuple as AccountInfo).data @@ -117,16 +138,30 @@ function querySystemAccount (api: DeriveApi, accountId: AccountId): Observable Date: Sun, 18 Aug 2024 15:57:21 -0400 Subject: [PATCH 2/4] Ensure api.derive.balances.all correctly returns transferable --- packages/api-derive/src/balances/account.ts | 9 +++--- packages/api-derive/src/balances/all.ts | 8 +++++ packages/api-derive/src/balances/types.ts | 33 +++++++++++++++++---- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/packages/api-derive/src/balances/account.ts b/packages/api-derive/src/balances/account.ts index 7bfc3a7a5d72..b938c82a841c 100644 --- a/packages/api-derive/src/balances/account.ts +++ b/packages/api-derive/src/balances/account.ts @@ -33,13 +33,13 @@ function getBalance (api: DeriveApi, [freeBalance, reservedBalance, frozenFeeOrF if (accType.isFrameAccountData) { return { - freeBalance, - frozenFee: api.registry.createType('Balance', 0), - frozenMisc: api.registry.createType('Balance', 0), - newFrameData: { + frameSystemAccountInfo: { flags: frozenMiscOrFlags, frozen: frozenFeeOrFrozen }, + freeBalance, + frozenFee: api.registry.createType('Balance', 0), + frozenMisc: api.registry.createType('Balance', 0), reservedBalance, votingBalance }; @@ -49,7 +49,6 @@ function getBalance (api: DeriveApi, [freeBalance, reservedBalance, frozenFeeOrF freeBalance, frozenFee: frozenFeeOrFrozen, frozenMisc: frozenMiscOrFlags, - newFrameData: {}, reservedBalance, votingBalance }; diff --git a/packages/api-derive/src/balances/all.ts b/packages/api-derive/src/balances/all.ts index 60aaf49cb378..fa69a5cc9885 100644 --- a/packages/api-derive/src/balances/all.ts +++ b/packages/api-derive/src/balances/all.ts @@ -54,11 +54,19 @@ function calcLocked (api: DeriveApi, bestNumber: BlockNumber, locks: (PalletBala function calcShared (api: DeriveApi, bestNumber: BlockNumber, data: DeriveBalancesAccountData, locks: (PalletBalancesBalanceLock | BalanceLockTo212)[]): DeriveBalancesAllAccountData { const { allLocked, lockedBalance, lockedBreakdown, vestingLocked } = calcLocked(api, bestNumber, locks); + let transferable = null; + + if (data.frameSystemAccountInfo?.frozen) { + const frozenReserveDiff = data.frameSystemAccountInfo.frozen.sub(data.reservedBalance); + + transferable = api.registry.createType('Balance', allLocked ? 0 : data?.freeBalance.sub(bnMax(frozenReserveDiff, api.consts.balances.existentialDeposit))); + } return objectSpread({}, data, { availableBalance: api.registry.createType('Balance', allLocked ? 0 : bnMax(new BN(0), data?.freeBalance ? data.freeBalance.sub(lockedBalance) : new BN(0))), lockedBalance, lockedBreakdown, + transferable, vestingLocked }); } diff --git a/packages/api-derive/src/balances/types.ts b/packages/api-derive/src/balances/types.ts index 651d7a29ce97..aa28324d27b0 100644 --- a/packages/api-derive/src/balances/types.ts +++ b/packages/api-derive/src/balances/types.ts @@ -6,15 +6,15 @@ import type { PalletBalancesBalanceLock, PalletBalancesReserveData } from '@polk import type { BN } from '@polkadot/util'; export interface DeriveBalancesAccountData { + frameSystemAccountInfo?: { + frozen: Balance; + flags: Balance; + } freeBalance: Balance; frozenFee: Balance; frozenMisc: Balance; reservedBalance: Balance; votingBalance: Balance; - newFrameData: { - frozen?: Balance; - flags?: Balance; - } } export interface DeriveBalancesAccount extends DeriveBalancesAccountData { @@ -24,11 +24,34 @@ export interface DeriveBalancesAccount extends DeriveBalancesAccountData { } export interface DeriveBalancesAllAccountData extends DeriveBalancesAccountData { + /** + * Calculated available balance. This uses the formula: max(0, free - locked) + * This is only correct when the return type of `api.query.system.account` is `AccountInfo` which was replaced by `FrameSystemAccountInfo`. + * See `transferable` for the correct balance calculation. + * + * ref: https://github.com/paritytech/substrate/pull/12951 + */ availableBalance: Balance; + /** + * The amount of balance locked away. + */ lockedBalance: Balance; + /** + * The breakdown of locked balances. + */ lockedBreakdown: (PalletBalancesBalanceLock | BalanceLockTo212)[]; + /** + * Calculated transferable balance. This uses the formula: free - max(frozen - reserve, ed) + * This is only correct when the return type of `api.query.system.account` is `FrameSystemAccountInfo`. + * Which is the most up to date calulcation for transferrable balances. + * + * ref: https://github.com/paritytech/polkadot-sdk/issues/1833 + */ + transferable: Balance | null; + /** + * Amount locked in vesting. + */ vestingLocked: Balance; - transferable: Balance; } export interface DeriveBalancesVesting { From 0ece89f925813eb6bc3a1f0cbd1954437520e27b Mon Sep 17 00:00:00 2001 From: tarikgul Date: Sun, 18 Aug 2024 16:17:30 -0400 Subject: [PATCH 3/4] Remove null from transferable --- packages/api-derive/src/balances/all.ts | 2 +- packages/api-derive/src/balances/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/api-derive/src/balances/all.ts b/packages/api-derive/src/balances/all.ts index fa69a5cc9885..4d5fdeceaf41 100644 --- a/packages/api-derive/src/balances/all.ts +++ b/packages/api-derive/src/balances/all.ts @@ -54,7 +54,7 @@ function calcLocked (api: DeriveApi, bestNumber: BlockNumber, locks: (PalletBala function calcShared (api: DeriveApi, bestNumber: BlockNumber, data: DeriveBalancesAccountData, locks: (PalletBalancesBalanceLock | BalanceLockTo212)[]): DeriveBalancesAllAccountData { const { allLocked, lockedBalance, lockedBreakdown, vestingLocked } = calcLocked(api, bestNumber, locks); - let transferable = null; + let transferable = new BN(0); if (data.frameSystemAccountInfo?.frozen) { const frozenReserveDiff = data.frameSystemAccountInfo.frozen.sub(data.reservedBalance); diff --git a/packages/api-derive/src/balances/types.ts b/packages/api-derive/src/balances/types.ts index aa28324d27b0..041c973e9bec 100644 --- a/packages/api-derive/src/balances/types.ts +++ b/packages/api-derive/src/balances/types.ts @@ -47,7 +47,7 @@ export interface DeriveBalancesAllAccountData extends DeriveBalancesAccountData * * ref: https://github.com/paritytech/polkadot-sdk/issues/1833 */ - transferable: Balance | null; + transferable: Balance; /** * Amount locked in vesting. */ From d2f7116373b600899b3ee91c8e41e3a4e4f5bee3 Mon Sep 17 00:00:00 2001 From: tarikgul Date: Sun, 18 Aug 2024 16:18:39 -0400 Subject: [PATCH 4/4] set back to null --- packages/api-derive/src/balances/all.ts | 2 +- packages/api-derive/src/balances/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/api-derive/src/balances/all.ts b/packages/api-derive/src/balances/all.ts index 4d5fdeceaf41..fa69a5cc9885 100644 --- a/packages/api-derive/src/balances/all.ts +++ b/packages/api-derive/src/balances/all.ts @@ -54,7 +54,7 @@ function calcLocked (api: DeriveApi, bestNumber: BlockNumber, locks: (PalletBala function calcShared (api: DeriveApi, bestNumber: BlockNumber, data: DeriveBalancesAccountData, locks: (PalletBalancesBalanceLock | BalanceLockTo212)[]): DeriveBalancesAllAccountData { const { allLocked, lockedBalance, lockedBreakdown, vestingLocked } = calcLocked(api, bestNumber, locks); - let transferable = new BN(0); + let transferable = null; if (data.frameSystemAccountInfo?.frozen) { const frozenReserveDiff = data.frameSystemAccountInfo.frozen.sub(data.reservedBalance); diff --git a/packages/api-derive/src/balances/types.ts b/packages/api-derive/src/balances/types.ts index 041c973e9bec..aa28324d27b0 100644 --- a/packages/api-derive/src/balances/types.ts +++ b/packages/api-derive/src/balances/types.ts @@ -47,7 +47,7 @@ export interface DeriveBalancesAllAccountData extends DeriveBalancesAccountData * * ref: https://github.com/paritytech/polkadot-sdk/issues/1833 */ - transferable: Balance; + transferable: Balance | null; /** * Amount locked in vesting. */