From fb5ce83f748678802d5cfbd66b7ae42bd878f0ce Mon Sep 17 00:00:00 2001 From: Jaco Date: Sat, 9 Apr 2022 15:05:36 +0200 Subject: [PATCH] Add support for apiAt.tx(...) (#4696) * Add support for apiAt.tx(...) * CHANGELOG --- CHANGELOG.md | 1 + packages/api/src/base/Decorate.ts | 36 +++++++++---------- packages/api/src/submittable/createClass.ts | 11 +++--- .../api/src/submittable/createSubmittable.ts | 7 ++-- packages/api/src/types/index.ts | 6 ++-- 5 files changed, 31 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27a6fb99e9..5d04ca556b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Contributed: Changes: +- Add support for `apiAt.tx(...)` to construct at a specific point - Add basic `api.derive.bagsList.*` support - Return sorted names for `api.registry.lookup.names` - Optimize JSONRPC requests/response handling diff --git a/packages/api/src/base/Decorate.ts b/packages/api/src/base/Decorate.ts index d67d46c2b1..7f806ec3b8 100644 --- a/packages/api/src/base/Decorate.ts +++ b/packages/api/src/base/Decorate.ts @@ -199,18 +199,23 @@ export abstract class Decorate extends Events { return this._rpcCore.provider.hasSubscriptions || !!this._rpcCore.state.queryStorageAt; } + protected _emptyDecorated (registry: Registry, blockHash?: Uint8Array): ApiDecoration { + return { + consts: {}, + errors: {}, + events: {}, + query: {}, + registry, + rx: { + query: {} + }, + tx: createSubmittable(this._type, this._rx, this._decorateMethod, registry, blockHash) + } as ApiDecoration; + } + protected _createDecorated (registry: VersionedRegistry, fromEmpty: boolean, decoratedApi: ApiDecoration | null, blockHash?: Uint8Array): FullDecoration { if (!decoratedApi) { - decoratedApi = { - consts: {}, - errors: {}, - events: {}, - query: {}, - registry: registry.registry, - rx: { - query: {} - } - } as ApiDecoration; + decoratedApi = this._emptyDecorated(registry.registry, blockHash); } if (fromEmpty || !registry.decoratedMeta) { @@ -243,16 +248,7 @@ export abstract class Decorate extends Events { protected _injectMetadata (registry: VersionedRegistry, fromEmpty = false): void { // clear the decoration, we are redoing it here if (fromEmpty || !registry.decoratedApi) { - registry.decoratedApi = { - consts: {}, - errors: {}, - events: {}, - query: {}, - registry: registry.registry, - rx: { - query: {} - } - } as ApiDecoration; + registry.decoratedApi = this._emptyDecorated(registry.registry); } const { decoratedApi, decoratedMeta } = this._createDecorated(registry, fromEmpty, registry.decoratedApi); diff --git a/packages/api/src/submittable/createClass.ts b/packages/api/src/submittable/createClass.ts index b1d94b2a37..5fb7b1d151 100644 --- a/packages/api/src/submittable/createClass.ts +++ b/packages/api/src/submittable/createClass.ts @@ -21,6 +21,7 @@ import { SubmittableResult } from './Result'; interface SubmittableOptions { api: ApiInterfaceRx; apiType: ApiTypes; + blockHash?: Uint8Array; decorateMethod: ApiBase['_decorateMethod']; } @@ -80,7 +81,7 @@ function optionsOrNonce (partialOptions: Partial = {}): Partial ({ api, apiType, decorateMethod }: SubmittableOptions): Constructor> { +export function createClass ({ api, apiType, blockHash, decorateMethod }: SubmittableOptions): Constructor> { // an instance of the base extrinsic for us to extend const ExtrinsicBase = api.registry.createClass('Extrinsic'); @@ -97,10 +98,10 @@ export function createClass ({ api, apiType, decorate // dry run an extrinsic public dryRun (account: AddressOrPair, optionsOrHash?: Partial | Uint8Array | string): SubmittableDryRunResult { - if (isString(optionsOrHash) || isU8a(optionsOrHash)) { + if (blockHash || isString(optionsOrHash) || isU8a(optionsOrHash)) { // eslint-disable-next-line @typescript-eslint/no-unsafe-return return decorateMethod( - () => api.rpc.system.dryRun(this.toHex(), optionsOrHash) + () => api.rpc.system.dryRun(this.toHex(), blockHash || optionsOrHash as string) ); } @@ -115,10 +116,10 @@ export function createClass ({ api, apiType, decorate // calculate the payment info for this transaction (if signed and submitted) public paymentInfo (account: AddressOrPair, optionsOrHash?: Partial | Uint8Array | string): SubmittablePaymentResult { - if (isString(optionsOrHash) || isU8a(optionsOrHash)) { + if (blockHash || isString(optionsOrHash) || isU8a(optionsOrHash)) { // eslint-disable-next-line @typescript-eslint/no-unsafe-return return decorateMethod( - (): Observable => api.rpc.payment.queryInfo(this.toHex(), optionsOrHash) + (): Observable => api.rpc.payment.queryInfo(this.toHex(), blockHash || optionsOrHash as string) ); } diff --git a/packages/api/src/submittable/createSubmittable.ts b/packages/api/src/submittable/createSubmittable.ts index f24d993995..2130be7cd5 100644 --- a/packages/api/src/submittable/createSubmittable.ts +++ b/packages/api/src/submittable/createSubmittable.ts @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import type { Call, Extrinsic } from '@polkadot/types/interfaces'; +import type { Registry } from '@polkadot/types-codec/types'; import type { ApiInterfaceRx, ApiTypes } from '../types'; import type { SubmittableExtrinsic } from './types'; @@ -10,9 +11,9 @@ import { createClass } from './createClass'; type Creator = (extrinsic: Call | Uint8Array | string) => SubmittableExtrinsic; -export function createSubmittable (apiType: ApiTypes, api: ApiInterfaceRx, decorateMethod: ApiBase['_decorateMethod']): Creator { - const Submittable = createClass({ api, apiType, decorateMethod }); +export function createSubmittable (apiType: ApiTypes, api: ApiInterfaceRx, decorateMethod: ApiBase['_decorateMethod'], registry?: Registry, blockHash?: Uint8Array): Creator { + const Submittable = createClass({ api, apiType, blockHash, decorateMethod }); return (extrinsic: Call | Extrinsic | Uint8Array | string): SubmittableExtrinsic => - new Submittable(api.registry, extrinsic); + new Submittable(registry || api.registry, extrinsic); } diff --git a/packages/api/src/types/index.ts b/packages/api/src/types/index.ts index db653fb9b9..98947bfc57 100644 --- a/packages/api/src/types/index.ts +++ b/packages/api/src/types/index.ts @@ -9,11 +9,12 @@ import type { DecoratedEvents } from '@polkadot/api-base/types/events'; import type { QueryableStorage } from '@polkadot/api-base/types/storage'; import type { ProviderInterface, ProviderInterfaceEmitted } from '@polkadot/rpc-provider/types'; import type { ExtDef } from '@polkadot/types/extrinsic/signedExtensions/types'; -import type { Hash } from '@polkadot/types/interfaces'; +import type { Call, Extrinsic, Hash } from '@polkadot/types/interfaces'; import type { CallFunction, DefinitionRpc, DefinitionRpcSub, RegisteredTypes, Registry, RegistryError, SignatureOptions, Signer } from '@polkadot/types/types'; import type { BN } from '@polkadot/util'; import type { HexString } from '@polkadot/util/types'; import type { ApiBase } from '../base'; +import type { SubmittableExtrinsic } from '../types/submittable'; import type { AllDerives } from '../util/decorate'; export * from '@polkadot/api-base/types'; @@ -96,7 +97,8 @@ export interface ApiDecoration { registry: Registry; rx: { query: QueryableStorage<'rxjs'>; - } + }; + tx: (extrinsic: Call | Extrinsic | Uint8Array | string) => SubmittableExtrinsic; findCall (callIndex: Uint8Array | string): CallFunction; findError (errorIndex: Uint8Array | string): RegistryError;