Make v4 payload driven by extension fields (#4017)
* Make v4 payload driven by extension fields * Add getters for additional fields * Move keys * Re-adjust * abstract * SignerPayload fields * CHANGELOG
This commit is contained in:
@@ -11,6 +11,7 @@ Changelog:
|
|||||||
|
|
||||||
Changes:
|
Changes:
|
||||||
|
|
||||||
|
- Dynamically inject getters for Extrinsic payloads
|
||||||
- Optimize caching for previously constructed type classes per registry
|
- Optimize caching for previously constructed type classes per registry
|
||||||
- Convert metadata, rpc and api to use lazy decoration
|
- Convert metadata, rpc and api to use lazy decoration
|
||||||
- Split u8a decoding paths for Vec (different from general path)
|
- Split u8a decoding paths for Vec (different from general path)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import type { ExtrinsicValueV4 } from './v4/Extrinsic';
|
|||||||
import { assert, compactAddLength, compactFromU8a, isHex, isU8a, objectSpread, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
|
import { assert, compactAddLength, compactFromU8a, isHex, isU8a, objectSpread, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
|
||||||
|
|
||||||
import { Base } from '../codec/Base';
|
import { Base } from '../codec/Base';
|
||||||
|
import { defineProperty } from '../codec/utils';
|
||||||
import { BIT_SIGNED, BIT_UNSIGNED, DEFAULT_VERSION, UNMASK_VERSION } from './constants';
|
import { BIT_SIGNED, BIT_UNSIGNED, DEFAULT_VERSION, UNMASK_VERSION } from './constants';
|
||||||
|
|
||||||
interface CreateOptions {
|
interface CreateOptions {
|
||||||
@@ -36,6 +37,20 @@ const VERSIONS = [
|
|||||||
export { EXTRINSIC_VERSION as LATEST_EXTRINSIC_VERSION } from './v4/Extrinsic';
|
export { EXTRINSIC_VERSION as LATEST_EXTRINSIC_VERSION } from './v4/Extrinsic';
|
||||||
|
|
||||||
abstract class ExtrinsicBase<A extends AnyTuple> extends Base<ExtrinsicVx | ExtrinsicUnknown> {
|
abstract class ExtrinsicBase<A extends AnyTuple> extends Base<ExtrinsicVx | ExtrinsicUnknown> {
|
||||||
|
constructor (registry: Registry, value: ExtrinsicV4 | ExtrinsicUnknown, initialU8aLength?: number) {
|
||||||
|
super(registry, value, initialU8aLength);
|
||||||
|
|
||||||
|
const signKeys = Object.keys(registry.getSignedExtensionTypes());
|
||||||
|
|
||||||
|
// This is on the abstract class, ensuring that hasOwnProperty operates
|
||||||
|
// correctly, i.e. it needs to be on the base class exposing it
|
||||||
|
for (let i = 0; i < signKeys.length; i++) {
|
||||||
|
const key = signKeys[i];
|
||||||
|
|
||||||
|
defineProperty(this, key, () => (this._raw as ExtrinsicVx).signature[key as 'signer']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description The arguments passed to for the call, exposes args so it is compatible with [[Call]]
|
* @description The arguments passed to for the call, exposes args so it is compatible with [[Call]]
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { objectSpread, u8aToHex } from '@polkadot/util';
|
|||||||
import { Compact } from '../codec/Compact';
|
import { Compact } from '../codec/Compact';
|
||||||
import { Option } from '../codec/Option';
|
import { Option } from '../codec/Option';
|
||||||
import { Struct } from '../codec/Struct';
|
import { Struct } from '../codec/Struct';
|
||||||
|
import { defineProperty } from '../codec/utils';
|
||||||
import { Vec } from '../codec/Vec';
|
import { Vec } from '../codec/Vec';
|
||||||
import { Text } from '../primitive/Text';
|
import { Text } from '../primitive/Text';
|
||||||
import { u8 } from '../primitive/U8';
|
import { u8 } from '../primitive/U8';
|
||||||
@@ -62,6 +63,8 @@ export class GenericSignerPayload extends Struct implements ISignerPayload, Sign
|
|||||||
if (!knownTypes[key]) {
|
if (!knownTypes[key]) {
|
||||||
this._extraTypes[key] = type;
|
this._extraTypes[key] = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defineProperty(this, key, () => this.get(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
|
|
||||||
import type { HexString } from '@polkadot/util/types';
|
import type { HexString } from '@polkadot/util/types';
|
||||||
import type { EcdsaSignature, Ed25519Signature, ExtrinsicEra, ExtrinsicSignature, Sr25519Signature } from '../../interfaces/extrinsics';
|
import type { EcdsaSignature, Ed25519Signature, ExtrinsicEra, ExtrinsicSignature, Sr25519Signature } from '../../interfaces/extrinsics';
|
||||||
import type { Address, AssetId, Balance, Call, Index } from '../../interfaces/runtime';
|
import type { Address, Balance, Call, Index } from '../../interfaces/runtime';
|
||||||
import type { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, Registry, SignatureOptions } from '../../types';
|
import type { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, Registry, SignatureOptions } from '../../types';
|
||||||
import type { ExtrinsicSignatureOptions } from '../types';
|
import type { ExtrinsicSignatureOptions } from '../types';
|
||||||
|
|
||||||
import { assert, isU8a, objectSpread, stringify, u8aConcat, u8aToHex } from '@polkadot/util';
|
import { assert, isU8a, isUndefined, objectSpread, stringify, u8aConcat, u8aToHex } from '@polkadot/util';
|
||||||
|
|
||||||
import { Compact } from '../../codec/Compact';
|
import { Compact } from '../../codec/Compact';
|
||||||
import { Enum } from '../../codec/Enum';
|
import { Enum } from '../../codec/Enum';
|
||||||
import { Option } from '../../codec/Option';
|
|
||||||
import { Struct } from '../../codec/Struct';
|
import { Struct } from '../../codec/Struct';
|
||||||
|
import { defineProperty } from '../../codec/utils';
|
||||||
import { EMPTY_U8A, IMMORTAL_ERA } from '../constants';
|
import { EMPTY_U8A, IMMORTAL_ERA } from '../constants';
|
||||||
import { GenericExtrinsicPayloadV4 } from './ExtrinsicPayload';
|
import { GenericExtrinsicPayloadV4 } from './ExtrinsicPayload';
|
||||||
|
|
||||||
@@ -30,14 +30,17 @@ function toAddress (registry: Registry, address: Address | Uint8Array | string):
|
|||||||
*/
|
*/
|
||||||
export class GenericExtrinsicSignatureV4 extends Struct implements IExtrinsicSignature {
|
export class GenericExtrinsicSignatureV4 extends Struct implements IExtrinsicSignature {
|
||||||
#fakePrefix: Uint8Array;
|
#fakePrefix: Uint8Array;
|
||||||
|
#signKeys: string[];
|
||||||
|
|
||||||
constructor (registry: Registry, value?: GenericExtrinsicSignatureV4 | Uint8Array, { isSigned }: ExtrinsicSignatureOptions = {}) {
|
constructor (registry: Registry, value?: GenericExtrinsicSignatureV4 | Uint8Array, { isSigned }: ExtrinsicSignatureOptions = {}) {
|
||||||
|
const signTypes = registry.getSignedExtensionTypes();
|
||||||
|
|
||||||
super(
|
super(
|
||||||
registry,
|
registry,
|
||||||
objectSpread(
|
objectSpread(
|
||||||
// eslint-disable-next-line sort-keys
|
// eslint-disable-next-line sort-keys
|
||||||
{ signer: 'Address', signature: 'ExtrinsicSignature' },
|
{ signer: 'Address', signature: 'ExtrinsicSignature' },
|
||||||
registry.getSignedExtensionTypes()
|
signTypes
|
||||||
),
|
),
|
||||||
GenericExtrinsicSignatureV4.decodeExtrinsicSignature(value, isSigned)
|
GenericExtrinsicSignatureV4.decodeExtrinsicSignature(value, isSigned)
|
||||||
);
|
);
|
||||||
@@ -45,6 +48,13 @@ export class GenericExtrinsicSignatureV4 extends Struct implements IExtrinsicSig
|
|||||||
this.#fakePrefix = registry.createType('ExtrinsicSignature') instanceof Enum
|
this.#fakePrefix = registry.createType('ExtrinsicSignature') instanceof Enum
|
||||||
? FAKE_SOME
|
? FAKE_SOME
|
||||||
: FAKE_NONE;
|
: FAKE_NONE;
|
||||||
|
this.#signKeys = Object.keys(signTypes);
|
||||||
|
|
||||||
|
for (let i = 0; i < this.#signKeys.length; i++) {
|
||||||
|
const key = this.#signKeys[i];
|
||||||
|
|
||||||
|
defineProperty(this, key, () => this.get(key));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
@@ -119,21 +129,20 @@ export class GenericExtrinsicSignatureV4 extends Struct implements IExtrinsicSig
|
|||||||
return this.get('tip') as Compact<Balance>;
|
return this.get('tip') as Compact<Balance>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected _injectSignature (signer: Address, signature: ExtrinsicSignature, payload: GenericExtrinsicPayloadV4): IExtrinsicSignature {
|
||||||
* @description
|
// use the fields exposed to guide the getters
|
||||||
* The (optional) asset id for this signature for chains that support transaction fees in assets
|
for (let i = 0; i < this.#signKeys.length; i++) {
|
||||||
*/
|
const k = this.#signKeys[i];
|
||||||
public get assetId (): Option<AssetId> {
|
const v = payload.get(k);
|
||||||
return this.get('assetId') as Option<AssetId>;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected _injectSignature (signer: Address, signature: ExtrinsicSignature, { assetId, era, nonce, tip }: GenericExtrinsicPayloadV4): IExtrinsicSignature {
|
if (!isUndefined(v)) {
|
||||||
this.set('era', era);
|
this.set(k, v);
|
||||||
this.set('nonce', nonce);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// additional fields (exposed in struct itself)
|
||||||
this.set('signer', signer);
|
this.set('signer', signer);
|
||||||
this.set('signature', signature);
|
this.set('signature', signature);
|
||||||
this.set('tip', tip);
|
|
||||||
this.set('assetId', assetId);
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -152,18 +161,15 @@ export class GenericExtrinsicSignatureV4 extends Struct implements IExtrinsicSig
|
|||||||
/**
|
/**
|
||||||
* @description Creates a payload from the supplied options
|
* @description Creates a payload from the supplied options
|
||||||
*/
|
*/
|
||||||
public createPayload (method: Call, { assetId, blockHash, era, genesisHash, nonce, runtimeVersion: { specVersion, transactionVersion }, tip }: SignatureOptions): GenericExtrinsicPayloadV4 {
|
public createPayload (method: Call, options: SignatureOptions): GenericExtrinsicPayloadV4 {
|
||||||
return new GenericExtrinsicPayloadV4(this.registry, {
|
const { era, runtimeVersion: { specVersion, transactionVersion } } = options;
|
||||||
assetId,
|
|
||||||
blockHash,
|
return new GenericExtrinsicPayloadV4(this.registry, objectSpread<ExtrinsicPayloadValue>({}, options, {
|
||||||
era: era || IMMORTAL_ERA,
|
era: era || IMMORTAL_ERA,
|
||||||
genesisHash,
|
|
||||||
method: method.toHex(),
|
method: method.toHex(),
|
||||||
nonce,
|
|
||||||
specVersion,
|
specVersion,
|
||||||
tip: tip || 0,
|
transactionVersion
|
||||||
transactionVersion: transactionVersion || 0
|
}));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user