Handle storage with optional modifiers (#717)
* Handle storage with optional modifiers * Storage docs indicate Option * Cleanup Option logic * Convert Optional derive to use Option * Bump version, update changelog * Update CHANGELOG description * Enum.spec.js -> Enum.spec.ts * Add isEmpty to primitive types
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/types",
|
||||
"version": "0.44.1",
|
||||
"version": "0.45.0",
|
||||
"description": "Implementation of the Parity codec",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
|
||||
@@ -124,7 +124,14 @@ export class ModuleMetadata extends Struct {
|
||||
|
||||
export class StorageFunctionModifier extends Enum {
|
||||
constructor (value?: any) {
|
||||
super(['None', 'Default', 'Required'], value);
|
||||
super(['Optional', 'Default', 'Required'], value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description `true` if the storage entry is optional
|
||||
*/
|
||||
get isOptional (): boolean {
|
||||
return this.toNumber() === 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@ function storageV0 (mod: MetadataModuleV1): StorageMetadata | null {
|
||||
|
||||
return new StorageMetadata({
|
||||
prefix: mod.prefix,
|
||||
functions: mod.storage.unwrap().map(({ docs, fallback, name, type }) =>
|
||||
functions: mod.storage.unwrap().map(({ docs, fallback, modifier, name, type }) =>
|
||||
new StorageFunctionMetadata({
|
||||
name,
|
||||
modifier: 0, // unused, don't specify
|
||||
modifier: modifier.toNumber(),
|
||||
type,
|
||||
default: fallback,
|
||||
documentation: docs
|
||||
|
||||
@@ -65,6 +65,13 @@ export default abstract class AbstractInt extends BN implements Codec {
|
||||
return this._bitLength / 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is a zero value (align elsewhere)
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return this.isZero();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the number of bits in the value
|
||||
*/
|
||||
|
||||
@@ -73,6 +73,13 @@ export default class Compact extends Base<UInt | Moment> implements Codec {
|
||||
return this.toU8a().length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return this.raw.isEmpty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the number of bits in the value
|
||||
*/
|
||||
|
||||
@@ -4,15 +4,16 @@
|
||||
|
||||
import Enum from './Enum';
|
||||
|
||||
const testDecode = (type, input, expected) =>
|
||||
const testDecode = (type: string, input: any, expected: any) =>
|
||||
it(`can decode from ${type}`, () => {
|
||||
const e = new Enum(['foo', 'bar'], input);
|
||||
expect(e.toString()).toBe(expected);
|
||||
});
|
||||
|
||||
const testEncode = (to, expected) =>
|
||||
const testEncode = (to: 'toJSON' | 'toNumber' | 'toString' | 'toU8a', expected: any) =>
|
||||
it(`can encode ${to}`, () => {
|
||||
const e = new Enum(['foo', 'bar'], 1);
|
||||
|
||||
expect(e[to]()).toEqual(expected);
|
||||
});
|
||||
|
||||
@@ -65,6 +65,13 @@ export default class Enum extends Base<number> implements Codec {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value (always false)
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Compares the value of the input to see if there is a match
|
||||
*/
|
||||
|
||||
@@ -122,6 +122,13 @@ export default class EnumType<T> extends Base<Codec> implements Codec {
|
||||
return this._index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return this.isEmpty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the Enum points to a [[Null]] type
|
||||
*/
|
||||
|
||||
@@ -53,6 +53,13 @@ export default class Option<T extends Codec> extends Base<T> implements Codec {
|
||||
return 1 + this.raw.encodedLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the Option has no value
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return this.isNone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the Option has no value
|
||||
*/
|
||||
|
||||
@@ -139,6 +139,21 @@ export default class Struct<
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
const items = this.toArray();
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (!items[i].isEmpty) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the Type description to sthe structure
|
||||
*/
|
||||
|
||||
@@ -62,6 +62,13 @@ export default class Tuple extends Array<Codec> implements Codec {
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return this.length === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The types definition of the tuple
|
||||
*/
|
||||
|
||||
@@ -53,6 +53,16 @@ export default class Vector<
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return this.length === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The type for the items
|
||||
*/
|
||||
get Type (): string {
|
||||
return this._Type.name;
|
||||
}
|
||||
|
||||
@@ -22,5 +22,5 @@ export { default as U8a } from './U8a';
|
||||
export { default as UInt } from './UInt';
|
||||
|
||||
// Type management helper functions
|
||||
export { default as createType, getTypeClass, getTypeDef, TypeDef, TypeDefInfo } from './createType';
|
||||
export { default as createType, createClass, getTypeClass, getTypeDef, TypeDef, TypeDefInfo } from './createType';
|
||||
export { default as typeRegistry } from './typeRegistry';
|
||||
|
||||
@@ -36,6 +36,13 @@ export default class Bool extends Boolean implements Codec {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value (always false)
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Compares the value of the input to see if there is a match
|
||||
*/
|
||||
|
||||
@@ -52,6 +52,13 @@ export default class Moment extends Date implements Codec {
|
||||
return BITLENGTH / 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return this.getTime() === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Compares the value of the input to see if there is a match
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,13 @@ export default class Null implements Codec {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value (always true)
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Compares the value of the input to see if there is a match
|
||||
*/
|
||||
|
||||
@@ -46,6 +46,13 @@ export default class Text extends String implements Codec {
|
||||
return this.toU8a().length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return this.length === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The length of the value
|
||||
*/
|
||||
|
||||
@@ -145,7 +145,10 @@ function addStorage (metadata: MetadataV0) {
|
||||
const methodName = stringLowerFirst(func.name.toString());
|
||||
const arg = func.type.isMap ? ('`' + func.type.asMap.key.toString() + '`') : '';
|
||||
const doc = func.documentation.reduce((md, doc) => `${md} ${doc}`, '');
|
||||
const renderSignature = `${md}\n▸ **${methodName}**(${arg}): ` + '`' + func.type + '`';
|
||||
const type = func.modifier.isOptional
|
||||
? `Option<${func.type}>`
|
||||
: func.type;
|
||||
const renderSignature = `${md}\n▸ **${methodName}**(${arg}): ` + '`' + type + '`';
|
||||
const renderSummary = `${doc ? `\n- **summary**: ${doc}\n` : '\n'}`;
|
||||
|
||||
return renderSignature + renderSummary;
|
||||
|
||||
@@ -6,6 +6,7 @@ import BN from 'bn.js';
|
||||
import { decodeAddress } from '@polkadot/keyring';
|
||||
import { hexToU8a, isBn, isHex, isNumber, isU8a, u8aConcat, u8aToHex, u8aToU8a, u8aToBn } from '@polkadot/util';
|
||||
|
||||
import { Codec } from '../types';
|
||||
import Base from '../codec/Base';
|
||||
import AccountId from './AccountId';
|
||||
import AccountIndex from './AccountIndex';
|
||||
@@ -22,7 +23,7 @@ export const ACCOUNT_ID_PREFIX = new Uint8Array([0xff]);
|
||||
* we extend from Base with an AccountId/AccountIndex wrapper. Basically the Address
|
||||
* is encoded as `[ <prefix-byte>, ...publicKey/...bytes ]` as per spec
|
||||
*/
|
||||
export default class Address extends Base<AccountId | AccountIndex> {
|
||||
export default class Address extends Base<AccountId | AccountIndex> implements Codec {
|
||||
constructor (value: AnyAddress = new Uint8Array()) {
|
||||
super(
|
||||
Address.decodeAddress(value)
|
||||
@@ -75,6 +76,13 @@ export default class Address extends Base<AccountId | AccountIndex> {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return this.raw.isEmpty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The length of the raw value, either AccountIndex or AccountId
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,13 @@ export default class ChainProperties extends Map<string, any> implements Codec {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return [...this.keys()].length === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The token decimals, if defined (de-facto standard only)
|
||||
*/
|
||||
|
||||
@@ -33,6 +33,11 @@ export interface Codec {
|
||||
*/
|
||||
encodedLength: number;
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value
|
||||
*/
|
||||
isEmpty: boolean;
|
||||
|
||||
/**
|
||||
* @description Compares the value of the input to see if there is a match
|
||||
*/
|
||||
@@ -62,7 +67,9 @@ export interface Codec {
|
||||
|
||||
export type CodecTo = 'toHex' | 'toJSON' | 'toString' | 'toU8a';
|
||||
|
||||
export type Constructor<T = Codec> = { new(value?: any): T };
|
||||
export interface Constructor<T = Codec> {
|
||||
new(...value: Array<any>): T;
|
||||
}
|
||||
|
||||
export type ConstructorDef<T = Codec> = { [index: string]: Constructor<T> };
|
||||
|
||||
|
||||
Reference in New Issue
Block a user