Skip to content

Commit

Permalink
Seraliaze "unknown" payload fields via toJSON (#5716)
Browse files Browse the repository at this point in the history
* Seraliaze "unknown" payload fields via toJSON

* Additional tests

* Adjust

* CHANGELOG
  • Loading branch information
jacogr authored Aug 29, 2023
1 parent 9f0a324 commit bc62b46
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
27 changes: 26 additions & 1 deletion packages/types/src/extrinsic/SignerPayload.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,29 @@ describe('SignerPayload', (): void => {
});
});

it('handles Option<AssetId> 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, {
Expand All @@ -82,13 +105,15 @@ 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);
expect(payload.method.toHex()).toEqual(TEST.method);
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);
});
});
14 changes: 9 additions & 5 deletions packages/types/src/extrinsic/SignerPayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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<string, string> = {};
const result: Record<string, AnyJson> = {};
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();
}
}

Expand Down
16 changes: 8 additions & 8 deletions packages/types/src/types/extrinsic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit bc62b46

Please sign in to comment.