diff --git a/CHANGELOG.md b/CHANGELOG.md index 68c67514d77c..e00cc09614e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Changes: - Add runtime `ParachainHost` version 5 - Consistently use `import.meta.url` inside tests - Group `Uint/Int` tests for maintainability +- Serialize any additional payload fields via `toJSON()` - Update to latest Polkadot, Kusama & Substrate metadata diff --git a/packages/types/src/extrinsic/SignerPayload.spec.ts b/packages/types/src/extrinsic/SignerPayload.spec.ts index 0f64694ff4b8..55d681b19816 100644 --- a/packages/types/src/extrinsic/SignerPayload.spec.ts +++ b/packages/types/src/extrinsic/SignerPayload.spec.ts @@ -60,6 +60,29 @@ describe('SignerPayload', (): void => { }); }); + it('handles Option correctly', (): void => { + const test = new SignerPayload(registry, { assetId: 123 }); + + expect( + [...test.keys()].includes('assetId') + ).toEqual(true); + + expect( + // @ts-expect-error We don't have getters for this field + test.toPayload().assetId + ).toEqual(123); + + expect( + // @ts-expect-error We don't have getters for this field + new SignerPayload(registry, { assetId: 0 }).toPayload().assetId + ).toEqual(0); + + expect( + // @ts-expect-error We don't have getters for this field + new SignerPayload(registry, TEST).toPayload().assetId + ).toBeUndefined(); + }); + it('re-constructs from JSON', (): void => { expect( new SignerPayload(registry, { @@ -82,7 +105,7 @@ describe('SignerPayload', (): void => { }); it('can be used as a feed to ExtrinsicPayload', (): void => { - const signer = new SignerPayload(registry, TEST).toPayload(); + const signer = new SignerPayload(registry, { ...TEST, assetId: 123 }).toPayload(); const payload = registry.createType('ExtrinsicPayload', signer, { version: signer.version }); expect(payload.era.toHex()).toEqual(TEST.era); @@ -90,5 +113,7 @@ describe('SignerPayload', (): void => { expect(payload.blockHash.toHex()).toEqual(TEST.blockHash); expect(payload.nonce.eq(TEST.nonce)).toBe(true); expect(payload.tip.eq(TEST.tip)).toBe(true); + // @ts-expect-error assetId is of unknown type, so we don't know about "isSome" + expect(payload.inner?.get('assetId')?.isSome && payload.inner?.get('assetId')?.eq(123)).toBe(true); }); }); diff --git a/packages/types/src/extrinsic/SignerPayload.ts b/packages/types/src/extrinsic/SignerPayload.ts index d81ac31d522f..f2ec372034ab 100644 --- a/packages/types/src/extrinsic/SignerPayload.ts +++ b/packages/types/src/extrinsic/SignerPayload.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import type { Text, Vec } from '@polkadot/types-codec'; -import type { Registry } from '@polkadot/types-codec/types'; +import type { AnyJson, Registry } from '@polkadot/types-codec/types'; import type { HexString } from '@polkadot/util/types'; import type { Address, BlockHash, Call, ExtrinsicEra, Hash } from '../interfaces/index.js'; import type { Codec, ICompact, INumber, IRuntimeVersion, ISignerPayload, SignerPayloadJSON, SignerPayloadRaw } from '../types/index.js'; @@ -112,18 +112,22 @@ export class GenericSignerPayload extends Struct implements ISignerPayload, Sign * @description Creates an representation of the structure as an ISignerPayload JSON */ public toPayload (): SignerPayloadJSON { - const result: Record = {}; + const result: Record = {}; const keys = Object.keys(this.#extraTypes); // add any explicit overrides we may have for (let i = 0, count = keys.length; i < count; i++) { const key = keys[i]; const value = this.getT(key); - const isOption = value instanceof Option; // Don't include Option.isNone - if (!isOption || value.isSome) { - result[key] = value.toHex(); + if (!(value instanceof Option) || value.isSome) { + // NOTE In the spread below we convert (mostly) to Hex to align + // with the typings. In the case of "unknown" fields, we use the + // primitive toJSON conversion (which is serializable). Technically + // we can include isNone in here as well ("null" is allowed), however + // for empty fields we just skip it completely (historical compat) + result[key] = value.toJSON(); } } diff --git a/packages/types/src/types/extrinsic.ts b/packages/types/src/types/extrinsic.ts index 27a77dc17ecd..c934f174364f 100644 --- a/packages/types/src/types/extrinsic.ts +++ b/packages/types/src/types/extrinsic.ts @@ -38,22 +38,22 @@ export interface SignerPayloadJSON { /** * @description The checkpoint hash of the block, in hex */ - blockHash: string; + blockHash: HexString; /** * @description The checkpoint block number, in hex */ - blockNumber: string; + blockNumber: HexString; /** * @description The era for this transaction, in hex */ - era: string; + era: HexString; /** * @description The genesis hash of the chain, in hex */ - genesisHash: string; + genesisHash: HexString; /** * @description The encoded method (with arguments) in hex @@ -63,22 +63,22 @@ export interface SignerPayloadJSON { /** * @description The nonce for this transaction, in hex */ - nonce: string; + nonce: HexString; /** * @description The current spec version for the runtime */ - specVersion: string; + specVersion: HexString; /** * @description The tip for this transaction, in hex */ - tip: string; + tip: HexString; /** * @description The current transaction version for the runtime */ - transactionVersion: string; + transactionVersion: HexString; /** * @description The applicable signed extensions for this runtime