Add Codec toPrimitive (#5080)
This commit is contained in:
@@ -140,6 +140,19 @@ export abstract class AbstractArray<T extends Codec> extends Array<T> implements
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): AnyJson {
|
||||
const result = new Array<AnyJson>(this.length);
|
||||
|
||||
for (let i = 0; i < this.length; i++) {
|
||||
result[i] = this[i] && this[i].toPrimitive();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -83,6 +83,13 @@ export abstract class AbstractBase<T extends Codec> implements Codec {
|
||||
return this.#raw.toJSON();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): AnyJson {
|
||||
return this.#raw.toPrimitive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the string representation of the value
|
||||
*/
|
||||
|
||||
@@ -207,6 +207,15 @@ export abstract class AbstractInt extends BN implements INumber {
|
||||
: this.toNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the value in a primitive form, either number when <= 52 bits, or string otherwise
|
||||
*/
|
||||
public toPrimitive (): number | string {
|
||||
return super.bitLength() > MAX_NUMBER_BITS
|
||||
? this.toString()
|
||||
: this.toNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -171,6 +171,13 @@ export class Compact<T extends INumber> implements ICompact<T> {
|
||||
return this.#raw.toNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): string | number {
|
||||
return this.#raw.toPrimitive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -72,6 +72,10 @@ export class DoNotConstruct implements Codec {
|
||||
throw this.#neverError;
|
||||
}
|
||||
|
||||
toPrimitive (): AnyJson {
|
||||
throw this.#neverError;
|
||||
}
|
||||
|
||||
toRawType (): string {
|
||||
throw this.#neverError;
|
||||
}
|
||||
|
||||
@@ -414,6 +414,15 @@ export class Enum implements IEnum {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): AnyJson {
|
||||
return this.#isBasic
|
||||
? this.type
|
||||
: { [stringCamelCase(this.type)]: this.#raw.toPrimitive() };
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns a raw struct representation of the enum types
|
||||
*/
|
||||
|
||||
@@ -69,6 +69,13 @@ export class Null implements Codec {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): null {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -206,6 +206,15 @@ export class Option<T extends Codec> implements IOption<T> {
|
||||
: this.#raw.toJSON();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): AnyJson {
|
||||
return this.isNone
|
||||
? null
|
||||
: this.#raw.toPrimitive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -193,6 +193,19 @@ export class BTreeSet<V extends Codec = Codec> extends Set<V> implements ISet<V>
|
||||
return `BTreeSet<${this.registry.getClassName(this.#ValClass) || new this.#ValClass(this.registry).toRawType()}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): AnyJson {
|
||||
const json: AnyJson = [];
|
||||
|
||||
for (const v of this.values()) {
|
||||
json.push(v.toPrimitive());
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the string representation of the value
|
||||
*/
|
||||
|
||||
@@ -206,6 +206,23 @@ export class CodecMap<K extends Codec = Codec, V extends Codec = Codec> extends
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): AnyJson {
|
||||
const json: Record<string, AnyJson> = {};
|
||||
|
||||
for (const [k, v] of this.entries()) {
|
||||
json[
|
||||
k instanceof Raw && k.isAscii
|
||||
? k.toUtf8()
|
||||
: k.toString()
|
||||
] = v.toPrimitive();
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -92,6 +92,15 @@ export class WrapperKeepOpaque<T extends Codec> extends Bytes {
|
||||
: super.toHuman();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public override toPrimitive (): any {
|
||||
return this.#decoded
|
||||
? this.#decoded.toPrimitive()
|
||||
: super.toPrimitive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -105,6 +105,13 @@ export class bool extends Boolean implements Codec {
|
||||
return this.valueOf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): boolean {
|
||||
return this.toJSON();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -136,6 +136,13 @@ export class CodecDate extends Date implements INumber {
|
||||
return Math.ceil(this.getTime() / 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): number {
|
||||
return this.toNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -112,6 +112,13 @@ export class Float extends Number implements IFloat {
|
||||
return this.valueOf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): number {
|
||||
return this.toNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -109,6 +109,19 @@ export class Json extends Map<string, any> implements Codec {
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): Record<string, AnyJson> {
|
||||
return [...this.entries()].reduce<Record<string, AnyJson>>((json, [key, value]): Record<string, AnyJson> => {
|
||||
json[key] = isFunction((value as Codec).toHuman)
|
||||
? (value as Codec).toPrimitive()
|
||||
: value as AnyJson;
|
||||
|
||||
return json;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -36,6 +36,7 @@ describe('Raw', (): void => {
|
||||
|
||||
testEncode('toJSON', '0x0102030405');
|
||||
testEncode('toHex', '0x0102030405');
|
||||
testEncode('toPrimitive', '0x0102030405');
|
||||
testEncode('toString', '0x0102030405');
|
||||
testEncode('toU8a', Uint8Array.from([1, 2, 3, 4, 5]));
|
||||
|
||||
@@ -79,6 +80,11 @@ describe('Raw', (): void => {
|
||||
expect(new Raw(registry, '0x2021222324').isAscii).toBe(true);
|
||||
});
|
||||
|
||||
it('has valid toPrimitive', (): void => {
|
||||
expect(new Raw(registry, 'testing').toPrimitive()).toEqual('testing');
|
||||
expect(new Raw(registry, '0xe4bda0e5a5bd').toPrimitive()).toEqual('0xe4bda0e5a5bd');
|
||||
});
|
||||
|
||||
it('has valid toUtf8', (): void => {
|
||||
expect(new Raw(registry, 'Приветствую, ми').toUtf8()).toEqual('Приветствую, ми');
|
||||
expect(new Raw(registry, '0xe4bda0e5a5bd').toUtf8()).toEqual('你好');
|
||||
|
||||
@@ -111,6 +111,20 @@ export class Raw extends Uint8Array implements IU8a {
|
||||
* @description Converts the Object to to a human-friendly JSON, with additional fields, expansion and formatting of information
|
||||
*/
|
||||
public toHuman (): AnyJson {
|
||||
return this.toPrimitive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the Object to JSON, typically used for RPC transfers
|
||||
*/
|
||||
public toJSON (): string {
|
||||
return this.toHex();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): AnyJson {
|
||||
if (this.isAscii) {
|
||||
const text = this.toUtf8();
|
||||
|
||||
@@ -123,13 +137,6 @@ export class Raw extends Uint8Array implements IU8a {
|
||||
return this.toJSON();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the Object to JSON, typically used for RPC transfers
|
||||
*/
|
||||
public toJSON (): string {
|
||||
return this.toHex();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -229,6 +229,13 @@ export class CodecSet extends Set<string> implements ISet<string> {
|
||||
return this.valueEncoded.toNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): string[] {
|
||||
return this.toJSON();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -293,6 +293,23 @@ export class Struct<
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): Record<string, AnyJson> {
|
||||
const json: Record<string, AnyJson> = {};
|
||||
|
||||
for (const [k, v] of this.entries()) {
|
||||
const jsonKey = this.#jsonMap.get(k) || k;
|
||||
|
||||
// We actually log inside the U8a decoding and use JSON.stringify(...), which
|
||||
// means that the Vec may be partially populated (same applies to toHuman, same check)
|
||||
json[jsonKey as string] = v && v.toPrimitive();
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -147,6 +147,13 @@ export class Text extends String implements IText {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public toPrimitive (): string {
|
||||
return this.toJSON();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
@@ -77,6 +77,11 @@ export interface Codec {
|
||||
*/
|
||||
toJSON (): AnyJson;
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
toPrimitive (): AnyJson;
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
@@ -105,6 +110,6 @@ export interface CodecClass<T = Codec> {
|
||||
new(registry: Registry, ...args: any[]): T;
|
||||
}
|
||||
|
||||
export type CodecTo = 'toHex' | 'toJSON' | 'toString' | 'toU8a';
|
||||
export type CodecTo = 'toHex' | 'toJSON' | 'toPrimitive' | 'toString' | 'toU8a';
|
||||
|
||||
export type ArgsDef = Record<string, CodecClass | string>;
|
||||
|
||||
@@ -31,6 +31,7 @@ export interface INumber extends Codec {
|
||||
toBigInt (): bigint;
|
||||
toBn (): BN;
|
||||
toNumber (): number;
|
||||
toPrimitive (): string | number;
|
||||
}
|
||||
|
||||
export interface IFloat extends Codec {
|
||||
|
||||
@@ -53,6 +53,13 @@ export class GenericEthereumAccountId extends U8aFixed {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public override toPrimitive (): string {
|
||||
return this.toJSON();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the string representation of the value
|
||||
*/
|
||||
|
||||
@@ -43,6 +43,7 @@ describe('Extrinsic', (): void => {
|
||||
expect(extrinsic.callIndex).toEqual(new Uint8Array([6, 0]));
|
||||
expect(extrinsic.args[0].toHex()).toEqual('0x00495e1e506f266418af07fa0c5c108dd436f2faa59fe7d9e54403779f5bbd7718');
|
||||
expect(extrinsic.args[1].toHuman()).toEqual('104,560,923,320,000'); // ('104.5609 Unit');
|
||||
expect(extrinsic.toPrimitive()).toEqual({ method: { args: { dest: { id: '5DiuK2zR4asj2CEh77SKtUgTswTLkD8eiAKrByg5G3wL5w9b' }, value: 104560923320000 }, callIndex: '0x0600' }, signature: { era: { mortalEra: [1024, 186] }, nonce: 68, signature: { ed25519: '0xd99ffe3e610ad234e1414bda5831395a6df9098bf80b01561ce89a5065ae89d5c10e1619c6c99131b0bea4fb73ef04d07c07770e2ae9df5c325c331769ccb300' }, signer: { id: '5Hn8KKEp8qruCGWaN9MEsjTs4FXB4wv9xn7g1RWkNeKKNXCr' }, tip: 30000000000 } });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -62,6 +62,13 @@ export class GenericAccountId extends U8aFixed {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public override toPrimitive (): string {
|
||||
return this.toJSON();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the string representation of the value
|
||||
*/
|
||||
|
||||
@@ -104,6 +104,13 @@ export class GenericAccountIndex extends u32 {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public override toPrimitive (): string {
|
||||
return this.toJSON();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the string representation of the value
|
||||
*/
|
||||
|
||||
@@ -104,6 +104,13 @@ export class GenericCallIndex extends U8aFixed {
|
||||
constructor (registry: Registry, value?: AnyU8a) {
|
||||
super(registry, value, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public override toPrimitive (): string {
|
||||
return this.toHex();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@ import { GenericVote } from '.';
|
||||
describe('GenericVote', (): void => {
|
||||
const registry = new TypeRegistry();
|
||||
|
||||
describe.only('construction', (): void => {
|
||||
describe('construction', (): void => {
|
||||
it('constructs via boolean true', (): void => {
|
||||
expect(new GenericVote(registry, true).toU8a()).toEqual(new Uint8Array([128]));
|
||||
expect(new GenericVote(registry, true).isAye).toBe(true);
|
||||
@@ -58,7 +58,7 @@ describe('GenericVote', (): void => {
|
||||
expect(new GenericVote(registry, new Uint8Array([1])).isNay).toBe(true);
|
||||
});
|
||||
|
||||
it.only('constructs via Uint8Array (aye)', (): void => {
|
||||
it('constructs via Uint8Array (aye)', (): void => {
|
||||
const test = new GenericVote(registry, new Uint8Array([0b10000010]));
|
||||
|
||||
expect(test.isNay).toBe(false);
|
||||
@@ -68,12 +68,20 @@ describe('GenericVote', (): void => {
|
||||
|
||||
describe('Vote with conviction', (): void => {
|
||||
it('constructs Vote with raw boolean', (): void => {
|
||||
const vote = new GenericVote(registry, {
|
||||
aye: true,
|
||||
conviction: 'Locked1x'
|
||||
});
|
||||
|
||||
expect(
|
||||
new GenericVote(registry, {
|
||||
aye: true,
|
||||
conviction: 'Locked1x'
|
||||
}).toU8a()
|
||||
vote.toU8a()
|
||||
).toEqual(new Uint8Array([0b10000001]));
|
||||
expect(
|
||||
vote.toPrimitive()
|
||||
).toEqual({
|
||||
aye: true,
|
||||
conviction: 'Locked1x'
|
||||
});
|
||||
});
|
||||
|
||||
it('constructs with Vote aye is false, conviction is None', (): void => {
|
||||
|
||||
@@ -115,6 +115,16 @@ export class GenericVote extends U8aFixed {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Converts the value in a best-fit primitive form
|
||||
*/
|
||||
public override toPrimitive (): any {
|
||||
return {
|
||||
aye: this.isAye,
|
||||
conviction: this.conviction.toPrimitive()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user