From 1f751e07fc20351706de3fd60ba74c5296d06493 Mon Sep 17 00:00:00 2001 From: Tarik Gul <47201679+TarikGul@users.noreply.github.com> Date: Thu, 5 Sep 2024 06:06:35 -0700 Subject: [PATCH] Keep assetID hex as Option for toPayload (#5968) * Keep assetID hex as Option for toPayload * Resolve last issues with hex and u8a conversion for assetId * Inline comment * Fix types * Fix test * adjust merit of test --- packages/api/src/submittable/createClass.ts | 2 +- .../types/src/extrinsic/ExtrinsicPayload.ts | 20 +++++++++++++- .../types/src/extrinsic/SignerPayload.spec.ts | 26 +++++++++++-------- packages/types/src/extrinsic/SignerPayload.ts | 2 +- packages/types/src/types/extrinsic.ts | 2 +- 5 files changed, 37 insertions(+), 15 deletions(-) diff --git a/packages/api/src/submittable/createClass.ts b/packages/api/src/submittable/createClass.ts index a6d05f845981..1c8b1088ad4d 100644 --- a/packages/api/src/submittable/createClass.ts +++ b/packages/api/src/submittable/createClass.ts @@ -348,7 +348,7 @@ export function createClass ({ api, apiType, blockHas const ext = this.registry.createTypeUnsafe('Extrinsic', [result.signedTransaction]); const newSignerPayload = this.registry.createTypeUnsafe('SignerPayload', [objectSpread({}, { address, - assetId: ext.assetId && ext.assetId.isSome ? ext.assetId.unwrap().toHex() : null, + assetId: ext.assetId && ext.assetId.isSome ? ext.assetId.toHex() : null, blockHash: payload.blockHash, blockNumber: header ? header.number : 0, era: ext.era.toHex(), diff --git a/packages/types/src/extrinsic/ExtrinsicPayload.ts b/packages/types/src/extrinsic/ExtrinsicPayload.ts index d23252cfbc99..c5b38fbe25ea 100644 --- a/packages/types/src/extrinsic/ExtrinsicPayload.ts +++ b/packages/types/src/extrinsic/ExtrinsicPayload.ts @@ -11,7 +11,7 @@ import type { ExtrinsicPayloadValue, ICompact, IKeyringPair, INumber, IOption } import type { GenericExtrinsicEra } from './ExtrinsicEra.js'; import { AbstractBase } from '@polkadot/types-codec'; -import { u8aToHex } from '@polkadot/util'; +import { hexToU8a, isHex, u8aToHex } from '@polkadot/util'; import { DEFAULT_VERSION } from './constants.js'; @@ -36,6 +36,24 @@ function decodeExtrinsicPayload (registry: Registry, value?: GenericExtrinsicPay return value.unwrap(); } + /** + * HACK: In order to change the assetId from `number | object` to HexString (While maintaining the true type ie Option), + * to allow for easier generalization of the SignerPayloadJSON interface the below check is necessary. The ExtrinsicPayloadV4 class does not like + * a value passed in as an Option, and can't decode it properly. Therefore, we ensure to convert the following below, and then pass the option as a unwrapped + * JSON value. + * + * ref: https://github.com/polkadot-js/api/pull/5968 + * ref: https://github.com/polkadot-js/api/pull/5967 + */ + if (value && (value as ExtrinsicPayloadValue).assetId && isHex((value as ExtrinsicPayloadValue).assetId)) { + const adjustedPayload = { + ...(value as ExtrinsicPayloadValue), + assetId: registry.createType('TAssetConversion', hexToU8a((value as ExtrinsicPayloadValue).assetId)).toJSON() + }; + + return registry.createTypeUnsafe(VERSIONS[version] || VERSIONS[0], [adjustedPayload, { version }]); + } + return registry.createTypeUnsafe(VERSIONS[version] || VERSIONS[0], [value, { version }]); } diff --git a/packages/types/src/extrinsic/SignerPayload.spec.ts b/packages/types/src/extrinsic/SignerPayload.spec.ts index 17ad0d63f250..2920c6438d67 100644 --- a/packages/types/src/extrinsic/SignerPayload.spec.ts +++ b/packages/types/src/extrinsic/SignerPayload.spec.ts @@ -4,6 +4,7 @@ /// import rpcMetadata from '@polkadot/types-support/metadata/static-substrate'; +import { u8aToHex } from '@polkadot/util'; import { TypeRegistry } from '../create/index.js'; import { Metadata } from '../metadata/index.js'; @@ -35,6 +36,11 @@ describe('SignerPayload', (): void => { withSignedTransaction: false }; + const TEST_WITH_ASSETID_HEX = { + ...TEST, + assetId: '0x010002043205ed01' + }; + it('creates a valid JSON output', (): void => { expect( new SignerPayload(registry, { @@ -57,7 +63,7 @@ describe('SignerPayload', (): void => { ).toEqual({ address: '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE', // eslint-disable-next-line sort-keys - assetId: '0x0002043205ed01', + assetId: '0x010002043205ed01', blockHash: '0xde8f69eeb5e065e18c6950ff708d7e551f68dc9bf59a07c52367c0280f805ec7', blockNumber: '0x00231d30', era: '0x0703', @@ -88,12 +94,12 @@ describe('SignerPayload', (): void => { expect( test.toPayload().assetId // eslint-disable-next-line sort-keys - ).toEqual('0x0002043205ed01'); + ).toEqual('0x010002043205ed01'); expect( new SignerPayload(registry, { assetId: 0 }).toPayload().assetId // eslint-disable-next-line sort-keys - ).toEqual('0x0000'); + ).toEqual('0x010000'); }); it('re-constructs from JSON', (): void => { @@ -102,7 +108,7 @@ describe('SignerPayload', (): void => { ...TEST, runtimeVersion: { specVersion: 0x06, transactionVersion: 0x07 } }).toPayload() - ).toEqual(TEST); + ).toEqual(TEST_WITH_ASSETID_HEX); }); it('re-constructs from itself', (): void => { @@ -114,14 +120,12 @@ describe('SignerPayload', (): void => { runtimeVersion: { specVersion: 0x06, transactionVersion: 0x07 } }) ).toPayload() - ).toEqual(TEST); + ).toEqual(TEST_WITH_ASSETID_HEX); }); it('can be used as a feed to ExtrinsicPayload', (): void => { const signer = new SignerPayload(registry, { - ...TEST, - // eslint-disable-next-line sort-keys - assetId: { parents: 0, interior: { x2: [{ palletInstance: 50 }, { generalIndex: 123 }] } } + ...TEST }).toPayload(); const payload = registry.createType('ExtrinsicPayload', signer, { version: signer.version }); @@ -130,11 +134,11 @@ 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); - expect(payload.assetId.isSome && payload.assetId - ?.eq(registry.createType('MultiLocation', { + expect(u8aToHex(payload.assetId?.toU8a())) + .toEqual(u8aToHex(registry.createType('Option', { // eslint-disable-next-line sort-keys parents: 0, interior: { X2: [{ palletInstance: 50 }, { generalIndex: 123 }] } - }))).toBe(true); + }).toU8a())); }); const TEST_WITHOUT_CHECK = { diff --git a/packages/types/src/extrinsic/SignerPayload.ts b/packages/types/src/extrinsic/SignerPayload.ts index 6071bac41e7a..b0ccee89207b 100644 --- a/packages/types/src/extrinsic/SignerPayload.ts +++ b/packages/types/src/extrinsic/SignerPayload.ts @@ -159,7 +159,7 @@ export class GenericSignerPayload extends Struct implements ISignerPayload, Sign // the known defaults as managed explicitly and has different // formatting in cases, e.g. we mostly expose a hex format here address: this.address.toString(), - assetId: this.assetId && this.assetId.isSome ? this.assetId.unwrap().toHex() : null, + assetId: this.assetId && this.assetId.isSome ? this.assetId.toHex() : null, blockHash: this.blockHash.toHex(), blockNumber: this.blockNumber.toHex(), era: this.era.toHex(), diff --git a/packages/types/src/types/extrinsic.ts b/packages/types/src/types/extrinsic.ts index 6fea5886999b..6a0fe33cdd46 100644 --- a/packages/types/src/types/extrinsic.ts +++ b/packages/types/src/types/extrinsic.ts @@ -220,7 +220,7 @@ export interface ExtrinsicPayloadValue { specVersion: AnyNumber; tip: AnyNumber; transactionVersion: AnyNumber; - assetId?: AnyNumber | object; + assetId?: HexString; mode?: AnyNumber; metadataHash?: AnyU8a; }