From 79bed8eda39e91e4112f5490b37106ee5353e78b Mon Sep 17 00:00:00 2001 From: Jaco Date: Tue, 26 Jul 2022 08:34:59 +0200 Subject: [PATCH] Prototype static init Enum/Set/Struct (#5087) * Prototype static init Enum/Set/Struct * Adjust (similar, logic extracted - further local testing) * Adjust with latest util (no prototype atm) * Introduce prototype assignment * Old Enum tests * Fix toCallsOnly spread * Adjust * Use objectSpread in derives (decorated objects only) * Adjust * Remove extra map from bag get * Additional spreads * Signer spread * Formatting * typo * Adjust spreads for session * Additional spread * Adjust spread * Formatting * CHANGELOG * Adjust * slice * CHANGELOG --- CHANGELOG.md | 7 ++- packages/api-derive/src/bagsList/get.ts | 23 ++++---- .../api-derive/src/bagsList/getExpanded.ts | 4 +- packages/api-derive/src/balances/account.ts | 9 ++- packages/api-derive/src/balances/all.ts | 15 ++--- .../src/crowdloan/ownContributions.ts | 15 +++-- .../api-derive/src/democracy/dispatchQueue.ts | 4 +- .../api-derive/src/democracy/proposals.ts | 30 +++++----- .../api-derive/src/democracy/referendums.ts | 9 +-- .../src/democracy/referendumsInfo.ts | 13 +++-- packages/api-derive/src/democracy/util.ts | 7 +-- packages/api-derive/src/elections/info.ts | 21 ++++--- packages/api-derive/src/parachains/info.ts | 30 +++++----- .../api-derive/src/parachains/overview.ts | 4 +- packages/api-derive/src/session/info.ts | 7 ++- packages/api-derive/src/session/progress.ts | 18 +++--- packages/api-derive/src/staking/account.ts | 8 +-- packages/api-derive/src/staking/overview.ts | 13 +++-- .../api-derive/src/staking/stakerRewards.ts | 11 ++-- packages/api/src/test/SingleAccountSigner.ts | 7 +-- packages/types-codec/src/base/Enum.spec.ts | 13 +++-- packages/types-codec/src/base/Enum.ts | 45 ++++++++------- packages/types-codec/src/native/Set.ts | 22 ++++--- .../types-codec/src/native/Struct.spec.ts | 1 + packages/types-codec/src/native/Struct.ts | 57 +++++++++++-------- packages/types/src/create/lazy.ts | 2 +- .../PortableRegistry/PortableRegistry.ts | 33 ++++++----- 27 files changed, 227 insertions(+), 201 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 537ee89a9e..b8bd161a05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,14 @@ ## master -- **Breaking change** Deprecated interfaces have been removed including `tx.sign(...)` (use `signAsync`), `{is, as}Error` on Result (use `{is, as}Err`) as well as storage `.range(...)` operations. -- **Breaking change** Deprecated interfaces on `api-contract` has been removed. Always ensure you pass an options options to construction and queries. +- **Breaking change** The decorated field getters on `Struct` were moved to the prototype class for performance reasons. While `struct.` access still behaves in the same way, with the same results, this does mean that the prototype getters are not visible when doing an `Object.keys(struct)` or when doing an object spread. +- **Breaking change** Deprecated interfaces have been removed including `tx.sign(...)` (use `signAsync`), `Result.{is, as}Error` (use `{is, as}Err`) as well as storage `.range(...)` operations. +- **Breaking change** Only current Substrate contracts pallets are supported. This means `api-contract` will detect the usage of `storageDepositLimit` in params, if not available the contract interfaces will not be available. +- **Breaking change** Deprecated call interfaces on `api-contract` have been removed. Always ensure you pass an options options to construction and queries. Changes: +- Decorate `Struct/Enum/Set` field getters on class prototypes - Convert `api-contract` usage of `api.rpc.*` to `api.call.*` - Drop support for contract runtimes without `storageDepositLimit` (runtime `contractsApi` only has unversioned support for latest) - Export `api.rx.call.*` for internal usage (derive, contracts) diff --git a/packages/api-derive/src/bagsList/get.ts b/packages/api-derive/src/bagsList/get.ts index 78c4a42450..2f372ab359 100644 --- a/packages/api-derive/src/bagsList/get.ts +++ b/packages/api-derive/src/bagsList/get.ts @@ -10,7 +10,7 @@ import type { Bag } from './types'; import { map, of, switchMap } from 'rxjs'; -import { BN_ZERO, bnToBn } from '@polkadot/util'; +import { BN_ZERO, bnToBn, objectSpread } from '@polkadot/util'; import { memo } from '../util'; @@ -21,20 +21,17 @@ function orderBags (ids: BN[], bags: Option[]): Bag[] { id, key: id.toString() })) - .sort((a, b) => b.id.cmp(a.id)) - .map((base, index): Bag => ({ - ...base, - bagLower: BN_ZERO, - bagUpper: base.id, - index - })); + .sort((a, b) => b.id.cmp(a.id)); const max = sorted.length - 1; - return sorted.map((entry, index) => - index === max - ? entry - // We could probably use a .add(BN_ONE) here - : { ...entry, bagLower: sorted[index + 1].bagUpper } + return sorted.map((entry, index): Bag => + objectSpread(entry, { + bagLower: index === max + ? BN_ZERO + : sorted[index + 1].id, + bagUpper: entry.id, + index + }) ); } diff --git a/packages/api-derive/src/bagsList/getExpanded.ts b/packages/api-derive/src/bagsList/getExpanded.ts index eb229e6873..2120f330f7 100644 --- a/packages/api-derive/src/bagsList/getExpanded.ts +++ b/packages/api-derive/src/bagsList/getExpanded.ts @@ -8,12 +8,14 @@ import type { Bag, BagExpanded } from './types'; import { map, switchMap } from 'rxjs'; +import { objectSpread } from '@polkadot/util'; + import { memo } from '../util'; export function expand (instanceId: string, api: DeriveApi): (bag: Bag) => Observable { return memo(instanceId, (bag: Bag): Observable => api.derive.bagsList.listNodes(bag.bag).pipe( - map((nodes) => ({ ...bag, nodes })) + map((nodes) => objectSpread({ nodes }, bag)) ) ); } diff --git a/packages/api-derive/src/balances/account.ts b/packages/api-derive/src/balances/account.ts index 11cc2a5e3b..b8a46c1c5d 100644 --- a/packages/api-derive/src/balances/account.ts +++ b/packages/api-derive/src/balances/account.ts @@ -9,7 +9,7 @@ import type { DeriveApi, DeriveBalancesAccount, DeriveBalancesAccountData } from import { combineLatest, map, of, switchMap } from 'rxjs'; -import { isFunction } from '@polkadot/util'; +import { isFunction, objectSpread } from '@polkadot/util'; import { memo } from '../util'; @@ -40,12 +40,11 @@ function getBalance (api: DeriveApi, [freeBalance, reservedBalance, frozenFee, f } function calcBalances (api: DeriveApi, [accountId, [accountNonce, [primary, ...additional]]]: [AccountId, Result]): DeriveBalancesAccount { - return { + return objectSpread({ accountId, accountNonce, - additional: additional.map((b) => getBalance(api, b)), - ...getBalance(api, primary) - }; + additional: additional.map((b) => getBalance(api, b)) + }, getBalance(api, primary)); } // old diff --git a/packages/api-derive/src/balances/all.ts b/packages/api-derive/src/balances/all.ts index 01fa9af762..c49636073f 100644 --- a/packages/api-derive/src/balances/all.ts +++ b/packages/api-derive/src/balances/all.ts @@ -9,7 +9,7 @@ import type { DeriveApi, DeriveBalancesAccount, DeriveBalancesAccountData, Deriv import { combineLatest, map, of, switchMap } from 'rxjs'; -import { BN, BN_ZERO, bnMax, bnMin, isFunction } from '@polkadot/util'; +import { BN, BN_ZERO, bnMax, bnMin, isFunction, objectSpread } from '@polkadot/util'; import { memo } from '../util'; @@ -57,13 +57,12 @@ 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); - return { - ...data, + return objectSpread({}, data, { availableBalance: api.registry.createType('Balance', allLocked ? 0 : bnMax(new BN(0), data.freeBalance.sub(lockedBalance))), lockedBalance, lockedBreakdown, vestingLocked - }; + }); } function calcVesting (bestNumber: BlockNumber, shared: DeriveBalancesAllAccountData, _vesting: PalletVestingVestingInfo[] | null): DeriveBalancesAllVesting { @@ -102,16 +101,14 @@ function calcVesting (bestNumber: BlockNumber, shared: DeriveBalancesAllAccountD function calcBalances (api: DeriveApi, [data, [vesting, allLocks, namedReserves], bestNumber]: Result): DeriveBalancesAll { const shared = calcShared(api, bestNumber, data, allLocks[0]); - return { - ...shared, - ...calcVesting(bestNumber, shared, vesting), + return objectSpread(shared, calcVesting(bestNumber, shared, vesting), { accountId: data.accountId, accountNonce: data.accountNonce, additional: allLocks - .filter((_, index) => index !== 0) + .slice(1) .map((l, index) => calcShared(api, bestNumber, data.additional[index], l)), namedReserves - }; + }); } // old diff --git a/packages/api-derive/src/crowdloan/ownContributions.ts b/packages/api-derive/src/crowdloan/ownContributions.ts index bdc61ecfd4..b28d758860 100644 --- a/packages/api-derive/src/crowdloan/ownContributions.ts +++ b/packages/api-derive/src/crowdloan/ownContributions.ts @@ -7,6 +7,8 @@ import type { DeriveApi, DeriveOwnContributions } from '../types'; import { combineLatest, EMPTY, map, of, startWith, switchMap } from 'rxjs'; +import { objectSpread } from '@polkadot/util'; + import { memo } from '../util'; import { extractContributed } from './util'; @@ -21,10 +23,8 @@ function _getValues (api: DeriveApi, childKey: string, keys: string[]): Observab ? api.registry.createType('Balance', o.unwrap()) : api.registry.createType('Balance') ) - .reduce((all: DeriveOwnContributions, b, index): DeriveOwnContributions => ({ - ...all, - [keys[index]]: b - }), {}) + .reduce((all: DeriveOwnContributions, b, index): DeriveOwnContributions => + objectSpread(all, { [keys[index]]: b }), {}) ) ); } @@ -51,10 +51,9 @@ function _contributions (api: DeriveApi, paraId: string | number | BN, childKey: _getValues(api, childKey, keys), _watchOwnChanges(api, paraId, childKey, keys) ]).pipe( - map(([all, latest]) => ({ - ...all, - ...latest - })) + map(([all, latest]) => + objectSpread({}, all, latest) + ) ); } diff --git a/packages/api-derive/src/democracy/dispatchQueue.ts b/packages/api-derive/src/democracy/dispatchQueue.ts index 79bf235093..e27d18d27d 100644 --- a/packages/api-derive/src/democracy/dispatchQueue.ts +++ b/packages/api-derive/src/democracy/dispatchQueue.ts @@ -11,7 +11,7 @@ import type { DeriveApi, DeriveDispatch, DeriveProposalImage } from '../types'; import { catchError, combineLatest, map, of, switchMap } from 'rxjs'; import { Enum } from '@polkadot/types'; -import { isFunction, stringToHex } from '@polkadot/util'; +import { isFunction, objectSpread, stringToHex } from '@polkadot/util'; import { memo } from '../util'; @@ -107,7 +107,7 @@ function queryScheduler (api: DeriveApi): Observable { ]); }), map(([infos, images]): DeriveDispatch[] => - infos.map((info, index) => ({ ...info, image: images[index] })) + infos.map((info, index) => objectSpread({ image: images[index] }, info)) ) ); } diff --git a/packages/api-derive/src/democracy/proposals.ts b/packages/api-derive/src/democracy/proposals.ts index 718d9a54f0..447c543695 100644 --- a/packages/api-derive/src/democracy/proposals.ts +++ b/packages/api-derive/src/democracy/proposals.ts @@ -9,7 +9,7 @@ import type { DeriveApi, DeriveProposal, DeriveProposalImage } from '../types'; import { combineLatest, map, of, switchMap } from 'rxjs'; -import { isFunction } from '@polkadot/util'; +import { isFunction, objectSpread } from '@polkadot/util'; import { memo } from '../util'; @@ -33,17 +33,17 @@ function parse ([proposals, images, optDepositors]: Result): DeriveProposal[] { .map(([index, imageHash, proposer], proposalIndex): DeriveProposal => { const depositors = optDepositors[proposalIndex].unwrap(); - return { - ...( - isNewDepositors(depositors) - ? { balance: depositors[1], seconds: depositors[0] } - : { balance: depositors[0], seconds: depositors[1] } - ), - image: images[proposalIndex], - imageHash, - index, - proposer - }; + return objectSpread( + { + image: images[proposalIndex], + imageHash, + index, + proposer + }, + isNewDepositors(depositors) + ? { balance: depositors[1], seconds: depositors[0] } + : { balance: depositors[0], seconds: depositors[1] } + ); }); } @@ -56,9 +56,11 @@ export function proposals (instanceId: string, api: DeriveApi): () => Observable ? combineLatest([ of(proposals), api.derive.democracy.preimages( - proposals.map(([, hash]) => hash)), + proposals.map(([, hash]) => hash) + ), api.query.democracy.depositOf.multi( - proposals.map(([index]) => index)) + proposals.map(([index]) => index) + ) ]) : of([[], [], []]) ), diff --git a/packages/api-derive/src/democracy/referendums.ts b/packages/api-derive/src/democracy/referendums.ts index 544124afe6..bd1ef45140 100644 --- a/packages/api-derive/src/democracy/referendums.ts +++ b/packages/api-derive/src/democracy/referendums.ts @@ -6,6 +6,8 @@ import type { DeriveApi, DeriveReferendumExt } from '../types'; import { combineLatest, map, of, switchMap } from 'rxjs'; +import { objectSpread } from '@polkadot/util'; + import { memo } from '../util'; export function referendums (instanceId: string, api: DeriveApi): () => Observable { @@ -20,10 +22,9 @@ export function referendums (instanceId: string, api: DeriveApi): () => Observab : of([[], []]) ), map(([referendums, votes]) => - referendums.map((referendum, index): DeriveReferendumExt => ({ - ...referendum, - ...votes[index] - })) + referendums.map((referendum, index): DeriveReferendumExt => + objectSpread({}, referendum, votes[index]) + ) ) ) ); diff --git a/packages/api-derive/src/democracy/referendumsInfo.ts b/packages/api-derive/src/democracy/referendumsInfo.ts index 703e674f62..89b3452833 100644 --- a/packages/api-derive/src/democracy/referendumsInfo.ts +++ b/packages/api-derive/src/democracy/referendumsInfo.ts @@ -10,7 +10,7 @@ import type { DeriveApi, DeriveBalancesAccount, DeriveReferendum, DeriveReferend import { combineLatest, map, of, switchMap } from 'rxjs'; -import { isFunction } from '@polkadot/util'; +import { isFunction, objectSpread } from '@polkadot/util'; import { memo } from '../util'; import { calcVotes, getStatus } from './util'; @@ -57,11 +57,12 @@ function extractVotes (mapped: [AccountId, PalletDemocracyVoteVoting][], referen // FIXME We are ignoring split votes votes.reduce((result: DeriveReferendumVote[], [, vote]): DeriveReferendumVote[] => { if (vote.isStandard) { - result.push({ - accountId, - isDelegating: false, - ...vote.asStandard - }); + result.push( + objectSpread({ + accountId, + isDelegating: false + }, vote.asStandard) + ); } return result; diff --git a/packages/api-derive/src/democracy/util.ts b/packages/api-derive/src/democracy/util.ts index 7a9a6d4205..399a540221 100644 --- a/packages/api-derive/src/democracy/util.ts +++ b/packages/api-derive/src/democracy/util.ts @@ -6,7 +6,7 @@ import type { PalletDemocracyReferendumInfo, PalletDemocracyReferendumStatus, Pa import type { Option } from '@polkadot/types-codec'; import type { DeriveReferendum, DeriveReferendumVote, DeriveReferendumVotes, DeriveReferendumVoteState } from '../types'; -import { BN, bnSqrt } from '@polkadot/util'; +import { BN, bnSqrt, objectSpread } from '@polkadot/util'; interface ApproxState { votedAye: BN; @@ -119,11 +119,10 @@ export function calcVotes (sqrtElectorate: BN, referendum: DeriveReferendum, vot ? calcVotesCurrent(referendum.status.tally, votes) : calcVotesPrev(votes); - return { - ...state, + return objectSpread({}, state, { isPassing: calcPassing(referendum.status.threshold, sqrtElectorate, state), votes - }; + }); } export function getStatus (info: Option): PalletDemocracyReferendumStatus | ReferendumInfoTo239 | null { diff --git a/packages/api-derive/src/elections/info.ts b/packages/api-derive/src/elections/info.ts index fd320ddc08..8e47ea6e00 100644 --- a/packages/api-derive/src/elections/info.ts +++ b/packages/api-derive/src/elections/info.ts @@ -11,6 +11,8 @@ import type { DeriveElectionsInfo } from './types'; import { combineLatest, map, of } from 'rxjs'; +import { objectSpread } from '@polkadot/util'; + import { memo } from '../util'; // SeatHolder is current tuple is 2.x-era Substrate @@ -107,15 +109,16 @@ export function info (instanceId: string, api: DeriveApi): () => Observable ({ - ...getConstants(api, elections), - candidateCount: api.registry.createType('u32', candidates.length), - candidates: candidates.map(getCandidate), - members: members.length - ? members.map(getAccountTuple).sort(sortAccounts) - : councilMembers.map((a): [AccountId32, Balance] => [a, api.registry.createType('Balance')]), - runnersUp: runnersUp.map(getAccountTuple).sort(sortAccounts) - })) + map(([councilMembers, candidates, members, runnersUp]): DeriveElectionsInfo => + objectSpread({}, getConstants(api, elections), { + candidateCount: api.registry.createType('u32', candidates.length), + candidates: candidates.map(getCandidate), + members: members.length + ? members.map(getAccountTuple).sort(sortAccounts) + : councilMembers.map((a): [AccountId32, Balance] => [a, api.registry.createType('Balance')]), + runnersUp: runnersUp.map(getAccountTuple).sort(sortAccounts) + }) + ) ); }); } diff --git a/packages/api-derive/src/parachains/info.ts b/packages/api-derive/src/parachains/info.ts index 231c90e708..8ec80c64ab 100644 --- a/packages/api-derive/src/parachains/info.ts +++ b/packages/api-derive/src/parachains/info.ts @@ -8,6 +8,8 @@ import type { Active, DidUpdate, Heads, ParaInfoResult, PendingSwap, RelayDispat import { map, of } from 'rxjs'; +import { objectSpread } from '@polkadot/util'; + import { memo } from '../util'; import { didUpdateToBool } from './util'; @@ -28,20 +30,18 @@ function parseActive (id: ParaId, active: Active): DeriveParachainActive | null if (found && found[1].isSome) { const [collatorId, retriable] = found[1].unwrap(); - return { - collatorId, - ...( - retriable.isWithRetries - ? { - isRetriable: true, - retries: retriable.asWithRetries.toNumber() - } - : { - isRetriable: false, - retries: 0 - } - ) - }; + return objectSpread( + { collatorId }, + retriable.isWithRetries + ? { + isRetriable: true, + retries: retriable.asWithRetries.toNumber() + } + : { + isRetriable: false, + retries: 0 + } + ); } return null; @@ -65,7 +65,7 @@ function parse (id: ParaId, [active, retryQueue, selectedThreads, didUpdate, inf didUpdate: didUpdateToBool(didUpdate, id), heads, id, - info: { id, ...info.unwrap() } as DeriveParachainInfo, + info: objectSpread({ id }, info.unwrap()), pendingSwapId: pendingSwap.unwrapOr(null), relayDispatchQueue, retryCollators: parseCollators(id, retryQueue), diff --git a/packages/api-derive/src/parachains/overview.ts b/packages/api-derive/src/parachains/overview.ts index fa78c29b14..941efc9345 100644 --- a/packages/api-derive/src/parachains/overview.ts +++ b/packages/api-derive/src/parachains/overview.ts @@ -8,6 +8,8 @@ import type { DidUpdate, ParaInfoResult, PendingSwap, RelayDispatchQueueSize } f import { combineLatest, map, of, switchMap } from 'rxjs'; +import { objectSpread } from '@polkadot/util'; + import { memo } from '../util'; import { didUpdateToBool } from './util'; @@ -23,7 +25,7 @@ function parse ([ids, didUpdate, infos, pendingSwaps, relayDispatchQueueSizes]: return ids.map((id, index): DeriveParachain => ({ didUpdate: didUpdateToBool(didUpdate, id), id, - info: { id, ...infos[index].unwrapOr(null) } as DeriveParachainInfo, + info: objectSpread({ id }, infos[index].unwrapOr(null)), pendingSwapId: pendingSwaps[index].unwrapOr(null), relayDispatchQueueSize: relayDispatchQueueSizes[index][0].toNumber() })); diff --git a/packages/api-derive/src/session/info.ts b/packages/api-derive/src/session/info.ts index 1a618aeaac..106e5f1079 100644 --- a/packages/api-derive/src/session/info.ts +++ b/packages/api-derive/src/session/info.ts @@ -6,6 +6,8 @@ import type { DeriveApi, DeriveSessionInfo } from '../types'; import { map } from 'rxjs'; +import { objectSpread } from '@polkadot/util'; + import { memo } from '../util'; /** @@ -18,13 +20,12 @@ export function info (instanceId: string, api: DeriveApi): () => Observable { return api.derive.session.info().pipe( - map((info): DeriveSessionProgress => ({ - ...info, - eraProgress: api.registry.createType('BlockNumber'), - sessionProgress: api.registry.createType('BlockNumber') - })) + map((info): DeriveSessionProgress => + objectSpread({ + eraProgress: api.registry.createType('BlockNumber'), + sessionProgress: api.registry.createType('BlockNumber') + }, info) + ) ); } diff --git a/packages/api-derive/src/staking/account.ts b/packages/api-derive/src/staking/account.ts index d7bd513aba..e1319a5359 100644 --- a/packages/api-derive/src/staking/account.ts +++ b/packages/api-derive/src/staking/account.ts @@ -9,7 +9,7 @@ import type { StakingQueryFlags } from './types'; import { combineLatest, map, switchMap } from 'rxjs'; -import { BN, BN_ZERO } from '@polkadot/util'; +import { BN, BN_ZERO, objectSpread } from '@polkadot/util'; import { firstMemo, memo } from '../util'; @@ -54,12 +54,10 @@ function redeemableSum (api: DeriveApi, stakingLedger: PalletStakingStakingLedge } function parseResult (api: DeriveApi, sessionInfo: DeriveSessionInfo, keys: DeriveStakingKeys, query: DeriveStakingQuery): DeriveStakingAccount { - return { - ...keys, - ...query, + return objectSpread({}, keys, query, { redeemable: redeemableSum(api, query.stakingLedger, sessionInfo), unlocking: calculateUnlocking(api, query.stakingLedger, sessionInfo) - }; + }); } /** diff --git a/packages/api-derive/src/staking/overview.ts b/packages/api-derive/src/staking/overview.ts index b7e60d673a..1a16e337c7 100644 --- a/packages/api-derive/src/staking/overview.ts +++ b/packages/api-derive/src/staking/overview.ts @@ -6,6 +6,8 @@ import type { DeriveApi, DeriveStakingOverview } from '../types'; import { combineLatest, map } from 'rxjs'; +import { objectSpread } from '@polkadot/util'; + import { memo } from '../util'; /** @@ -17,10 +19,11 @@ export function overview (instanceId: string, api: DeriveApi): () => Observable< api.derive.session.indexes(), api.derive.staking.validators() ]).pipe( - map(([indexes, { nextElected, validators }]): DeriveStakingOverview => ({ - ...indexes, - nextElected, - validators - })) + map(([indexes, { nextElected, validators }]): DeriveStakingOverview => + objectSpread({}, indexes, { + nextElected, + validators + }) + ) )); } diff --git a/packages/api-derive/src/staking/stakerRewards.ts b/packages/api-derive/src/staking/stakerRewards.ts index bf47adb312..c3ffc58c39 100644 --- a/packages/api-derive/src/staking/stakerRewards.ts +++ b/packages/api-derive/src/staking/stakerRewards.ts @@ -10,7 +10,7 @@ import type { DeriveStakingQuery } from './types'; import { combineLatest, map, of, switchMap } from 'rxjs'; -import { BN_BILLION, BN_ZERO } from '@polkadot/util'; +import { BN_BILLION, BN_ZERO, objectSpread } from '@polkadot/util'; import { firstMemo, memo } from '../util'; @@ -125,10 +125,11 @@ function filterRewards (eras: EraIndex[], valInfo: [string, DeriveStakingQuery][ return true; }) .filter(({ validators }) => Object.keys(validators).length !== 0) - .map((reward) => ({ - ...reward, - nominators: reward.nominating.filter((n) => reward.validators[n.validatorId]) - })); + .map((reward) => + objectSpread({}, reward, { + nominators: reward.nominating.filter((n) => reward.validators[n.validatorId]) + }) + ); } export function _stakerRewardsEras (instanceId: string, api: DeriveApi): (eras: EraIndex[], withActive?: boolean) => Observable { diff --git a/packages/api/src/test/SingleAccountSigner.ts b/packages/api/src/test/SingleAccountSigner.ts index ab2d5ad842..1b29b78576 100644 --- a/packages/api/src/test/SingleAccountSigner.ts +++ b/packages/api/src/test/SingleAccountSigner.ts @@ -5,7 +5,7 @@ import type { Signer, SignerResult } from '@polkadot/api/types'; import type { KeyringPair } from '@polkadot/keyring/types'; import type { Registry, SignerPayloadJSON, SignerPayloadRaw } from '@polkadot/types/types'; -import { hexToU8a, u8aToHex } from '@polkadot/util'; +import { hexToU8a, objectSpread, u8aToHex } from '@polkadot/util'; let id = 0; @@ -31,10 +31,7 @@ export class SingleAccountSigner implements Signer { setTimeout((): void => { const signed = this.#registry.createType('ExtrinsicPayload', payload, { version: payload.version }).sign(this.#keyringPair); - resolve({ - id: ++id, - ...signed - }); + resolve(objectSpread({ id: ++id }, signed)); }, this.#signDelay); }); } diff --git a/packages/types-codec/src/base/Enum.spec.ts b/packages/types-codec/src/base/Enum.spec.ts index 3aadc8e1d3..1272311bc9 100644 --- a/packages/types-codec/src/base/Enum.spec.ts +++ b/packages/types-codec/src/base/Enum.spec.ts @@ -117,13 +117,16 @@ describe('Enum', (): void => { it('has correct isXyz/asXyz (Enum.with)', (): void => { const test = new (Enum.with({ First: Text, Second: U32, Third: U32 }))(registry, { Second: 42 }) as any as { isFirst: boolean; isSecond: boolean; asSecond: U32; isThird: boolean; asThird: never }; - const asKeys = Object.keys(test).filter((k) => k.startsWith('as')); - const isKeys = Object.keys(test).filter((k) => k.startsWith('is')); - expect(asKeys).toEqual(['asFirst', 'asSecond', 'asThird']); - expect(isKeys).toEqual(['isFirst', 'isSecond', 'isThird']); + // const asKeys = Object.keys(test).filter((k) => k.startsWith('as')); + // const isKeys = Object.keys(test).filter((k) => k.startsWith('is')); + + // expect([isKeys, asKeys]).toEqual([ + // ['isFirst', 'isSecond', 'isThird'], + // ['asFirst', 'asSecond', 'asThird'] + // ]); + expect([test.isFirst, test.isSecond, test.isThird]).toEqual([false, true, false]); - expect(test.asSecond.toNumber()).toEqual(42); expect((): never => test.asThird).toThrow(/Cannot convert 'Second' via asThird/); }); diff --git a/packages/types-codec/src/base/Enum.ts b/packages/types-codec/src/base/Enum.ts index 3be3f544fd..cdb75ce4dc 100644 --- a/packages/types-codec/src/base/Enum.ts +++ b/packages/types-codec/src/base/Enum.ts @@ -223,19 +223,6 @@ export class Enum implements IEnum { } public static with (Types: Record | Record | string[]): EnumCodecClass { - const keys = Array.isArray(Types) - ? Types - : Object.keys(Types); - const asKeys = new Array(keys.length); - const isKeys = new Array(keys.length); - - for (let i = 0; i < keys.length; i++) { - const name = stringPascalCase(keys[i]); - - asKeys[i] = `as${name}`; - isKeys[i] = `is${name}`; - } - let definition: Definition | undefined; // eslint-disable-next-line no-return-assign @@ -243,18 +230,36 @@ export class Enum implements IEnum { definition = d; return class extends Enum { - constructor (registry: Registry, value?: unknown, index?: number) { - super(registry, Types, value, index, { definition, setDefinition }); + static { + const keys = Array.isArray(Types) + ? Types + : Object.keys(Types); + const asKeys = new Array(keys.length); + const isKeys = new Array(keys.length); - objectProperties(this, isKeys, (_, i) => this.type === keys[i]); - objectProperties(this, asKeys, (k, i): Codec => { - if (!this[isKeys[i] as keyof this]) { - throw new Error(`Cannot convert '${this.type}' via ${k}`); + for (let i = 0; i < keys.length; i++) { + const name = stringPascalCase(keys[i]); + + asKeys[i] = `as${name}`; + isKeys[i] = `is${name}`; + } + + objectProperties(this.prototype, isKeys, (_: string, i: number, self: Enum) => + self.type === keys[i] + ); + + objectProperties(this.prototype, asKeys, (k: string, i: number, self: Enum): Codec => { + if (self.type !== keys[i]) { + throw new Error(`Cannot convert '${self.type}' via ${k}`); } - return this.value; + return self.value; }); } + + constructor (registry: Registry, value?: unknown, index?: number) { + super(registry, Types, value, index, { definition, setDefinition }); + } }; } diff --git a/packages/types-codec/src/native/Set.ts b/packages/types-codec/src/native/Set.ts index 197caa86fe..18d1f8ab7b 100644 --- a/packages/types-codec/src/native/Set.ts +++ b/packages/types-codec/src/native/Set.ts @@ -109,18 +109,22 @@ export class CodecSet extends Set implements ISet { } public static with (values: SetValues, bitLength?: number): CodecClass { - const keys = Object.keys(values); - const isKeys = new Array(keys.length); - - for (let i = 0; i < keys.length; i++) { - isKeys[i] = `is${stringPascalCase(keys[i])}`; - } - return class extends CodecSet { + static { + const keys = Object.keys(values); + const isKeys = new Array(keys.length); + + for (let i = 0; i < keys.length; i++) { + isKeys[i] = `is${stringPascalCase(keys[i])}`; + } + + objectProperties(this.prototype, isKeys, (_: string, i: number, self: CodecSet) => + self.strings.includes(keys[i]) + ); + } + constructor (registry: Registry, value?: string[] | Set | Uint8Array | BN | number | string) { super(registry, values, value, bitLength); - - objectProperties(this, isKeys, (_, i) => this.strings.includes(keys[i])); } }; } diff --git a/packages/types-codec/src/native/Struct.spec.ts b/packages/types-codec/src/native/Struct.spec.ts index 92a1a57b18..eb78fda711 100644 --- a/packages/types-codec/src/native/Struct.spec.ts +++ b/packages/types-codec/src/native/Struct.spec.ts @@ -33,6 +33,7 @@ describe('Struct', (): void => { testDecode('hex', '0x1c62617a7a696e6745000000'); testDecode('object', { foo: 'bazzing', bar: 69 }); testDecode('Uint8Array', Uint8Array.from([28, 98, 97, 122, 122, 105, 110, 103, 69, 0, 0, 0])); + testDecode('Struct.with', new (Struct.with({ foo: 'Text', bar: 'U32' }))(registry, { foo: 'bazzing', bar: 69 })); it('decodes null/undefined/empty correctly (& equivalent)', (): void => { const Clazz = Struct.with({ diff --git a/packages/types-codec/src/native/Struct.ts b/packages/types-codec/src/native/Struct.ts index 3eca4c1b2a..ee57ef9b23 100644 --- a/packages/types-codec/src/native/Struct.ts +++ b/packages/types-codec/src/native/Struct.ts @@ -130,8 +130,6 @@ export class Struct< } public static with (Types: S, jsonMap?: Map): CodecClass> { - const keys = Object.keys(Types); - let definition: Definition | undefined; // eslint-disable-next-line no-return-assign @@ -139,10 +137,16 @@ export class Struct< definition = d; return class extends Struct { + static { + const keys = Object.keys(Types); + + objectProperties(this.prototype, keys, (k: string, _: number, self: Struct) => + self.get(k) + ); + } + constructor (registry: Registry, value?: unknown) { super(registry, Types, value as HexString, jsonMap, { definition, setDefinition }); - - objectProperties(this, keys, (k) => this.get(k)); } }; } @@ -154,10 +158,6 @@ export class Struct< return this.#Types[1]; } - public getT (key: string): T { - return this.get(key) as unknown as T; - } - /** * @description Checks if the value is an empty value */ @@ -171,20 +171,6 @@ export class Struct< return true; } - /** - * @description Returns the Type description of the structure - */ - public get Type (): E { - const result: Record = {}; - const [Types, keys] = this.#Types; - - for (let i = 0; i < keys.length; i++) { - result[keys[i]] = new Types[i](this.registry).toRawType(); - } - - return result as E; - } - /** * @description The length of the value when encoded as a Uint8Array */ @@ -205,6 +191,20 @@ export class Struct< return this.registry.hash(this.toU8a()); } + /** + * @description Returns the Type description of the structure + */ + public get Type (): E { + const result: Record = {}; + const [Types, keys] = this.#Types; + + for (let i = 0; i < keys.length; i++) { + result[keys[i]] = new Types[i](this.registry).toRawType(); + } + + return result as E; + } + /** * @description Compares the value of the input to see if there is a match */ @@ -214,10 +214,10 @@ export class Struct< /** * @description Returns a specific names entry in the structure - * @param name The name of the entry to retrieve + * @param key The name of the entry to retrieve */ - public override get (name: keyof S): Codec | undefined { - return super.get(name); + public override get (key: keyof S): Codec | undefined { + return super.get(key); } /** @@ -227,6 +227,13 @@ export class Struct< return this.toArray()[index]; } + /** + * @description Returns the a types value by name + */ + public getT (key: string): T { + return super.get(key) as unknown as T; + } + /** * @description Returns a breakdown of the hex encoding for this Codec */ diff --git a/packages/types/src/create/lazy.ts b/packages/types/src/create/lazy.ts index 45ee70fd8d..483ff34f52 100644 --- a/packages/types/src/create/lazy.ts +++ b/packages/types/src/create/lazy.ts @@ -15,7 +15,7 @@ export function lazyVariants (lookup: PortableRegistry, { type }: TypeHolder const variants = lookup.getSiType(type).def.asVariant.variants; for (let i = 0; i < variants.length; i++) { - lazyMethod(result, variants[i], creator, getName); + lazyMethod(result, variants[i], creator, getName, i); } return result; diff --git a/packages/types/src/metadata/PortableRegistry/PortableRegistry.ts b/packages/types/src/metadata/PortableRegistry/PortableRegistry.ts index 4cc3cfa45b..76cfcd5d17 100644 --- a/packages/types/src/metadata/PortableRegistry/PortableRegistry.ts +++ b/packages/types/src/metadata/PortableRegistry/PortableRegistry.ts @@ -34,7 +34,7 @@ interface TypeInfo { // Just a placeholder for a type.unrwapOr() const TYPE_UNWRAP = { toNumber: () => -1 }; -// Alias the primitive enum with out known values +// Alias the primitive enum with our known values const PRIMITIVE_ALIAS: Record = { Char: 'u32', // Rust char is 4-bytes Str: 'Text' @@ -655,7 +655,10 @@ export class PortableRegistry extends Struct implements ILookup { throw new Error(`PortableRegistry: ${lookupIndex}${namespace ? ` (${namespace})` : ''}: Error extracting ${stringify(type)}: ${(error as Error).message}`); } - return objectSpread({ docs: sanitizeDocs(type.docs), namespace }, typeDef); + return objectSpread({ + docs: sanitizeDocs(type.docs), + namespace + }, typeDef); } #extractArray (_: number, { len, type }: SiTypeDefArray): TypeDef { @@ -852,13 +855,10 @@ export class PortableRegistry extends Struct implements ILookup { } #extractHistoric (_: number, type: Type): TypeDef { - return objectSpread( - { - displayName: type.toString(), - isFromSi: true - }, - getTypeDef(type) - ); + return objectSpread({ + displayName: type.toString(), + isFromSi: true + }, getTypeDef(type)); } #extractPrimitive (_: number, type: SiType): TypeDef { @@ -937,7 +937,9 @@ export class PortableRegistry extends Struct implements ILookup { return withTypeString(this.registry, { info: TypeDefInfo.Result, sub: params.map(({ type }, index) => - objectSpread({ name: ['Ok', 'Error'][index] }, this.#createSiDef(type.unwrap())) + objectSpread({ + name: ['Ok', 'Error'][index] + }, this.#createSiDef(type.unwrap())) ) }); } else if (variants.length === 0) { @@ -971,13 +973,10 @@ export class PortableRegistry extends Struct implements ILookup { } sub.push( - objectSpread( - this.#extractFields(-1, fields), - { - index, - name: name.toString() - } - ) + objectSpread(this.#extractFields(-1, fields), { + index, + name: name.toString() + }) ); });