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:
Jaco Greeff
2019-02-19 13:47:36 +01:00
committed by GitHub
parent 4f17047c77
commit f807a93e87
40 changed files with 259 additions and 96 deletions
+1 -1
View File
@@ -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": [
+8 -1
View File
@@ -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;
}
}
+2 -2
View File
@@ -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
+7
View File
@@ -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
*/
+7
View File
@@ -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);
});
+7
View File
@@ -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
*/
+7
View File
@@ -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
*/
+7
View File
@@ -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
*/
+15
View File
@@ -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
*/
+7
View File
@@ -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
*/
+10
View File
@@ -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;
}
+1 -1
View File
@@ -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';
+7
View File
@@ -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
*/
+7
View File
@@ -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
*/
+7
View File
@@ -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
*/
+7
View File
@@ -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
*/
+4 -1
View File
@@ -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;
+9 -1
View File
@@ -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)
*/
+8 -1
View File
@@ -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> };