Skip to content

Commit

Permalink
Keep assetID hex as Option for toPayload (#5968)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
TarikGul authored Sep 5, 2024
1 parent b872fc1 commit 1f751e0
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 15 deletions.
2 changes: 1 addition & 1 deletion packages/api/src/submittable/createClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ export function createClass <ApiType extends ApiTypes> ({ api, apiType, blockHas
const ext = this.registry.createTypeUnsafe<Extrinsic>('Extrinsic', [result.signedTransaction]);
const newSignerPayload = this.registry.createTypeUnsafe<SignerPayload>('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(),
Expand Down
20 changes: 19 additions & 1 deletion packages/types/src/extrinsic/ExtrinsicPayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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<TAssetConversion>),
* 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 }]);
}

Expand Down
26 changes: 15 additions & 11 deletions packages/types/src/extrinsic/SignerPayload.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/// <reference types="@polkadot/dev-test/globals.d.ts" />

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';
Expand Down Expand Up @@ -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, {
Expand All @@ -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',
Expand Down Expand Up @@ -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 => {
Expand All @@ -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 => {
Expand All @@ -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 });

Expand All @@ -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<MultiLocation>', {
// eslint-disable-next-line sort-keys
parents: 0, interior: { X2: [{ palletInstance: 50 }, { generalIndex: 123 }] }
}))).toBe(true);
}).toU8a()));
});

const TEST_WITHOUT_CHECK = {
Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/extrinsic/SignerPayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/types/extrinsic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ export interface ExtrinsicPayloadValue {
specVersion: AnyNumber;
tip: AnyNumber;
transactionVersion: AnyNumber;
assetId?: AnyNumber | object;
assetId?: HexString;
mode?: AnyNumber;
metadataHash?: AnyU8a;
}
Expand Down

0 comments on commit 1f751e0

Please sign in to comment.