From 69f68509efea4818f7399740a5f7d146ad5080eb Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Fri, 7 Dec 2018 12:30:09 +0100 Subject: [PATCH] Expand with all currently known RPC methods --- docs/SUMMARY.md | 1 + packages/rpc-core/test/e2e/basics.test.js | 13 ++++ packages/type-jsonrpc/src/chain.ts | 30 ++++++++- packages/type-jsonrpc/src/state.ts | 51 +++------------- packages/type-jsonrpc/src/system.ts | 7 +++ packages/types/README.md | 2 +- packages/types/src/ChainProperties.ts | 74 +++++++++++++++++++++++ packages/types/src/index.ts | 1 + 8 files changed, 131 insertions(+), 48 deletions(-) create mode 100644 packages/types/src/ChainProperties.ts diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 8e8b49a5a8..575653128e 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -38,6 +38,7 @@ - [hidden](types/classes/_blocknumber_.blocknumber.md) - [hidden](types/classes/_bool_.bool.md) - [hidden](types/classes/_bytes_.bytes.md) +- [hidden](types/classes/_chainproperties_.chainproperties.md) - [hidden](types/classes/_codec_base_.base.md) - [hidden](types/classes/_codec_compact_.compact.md) - [hidden](types/classes/_codec_enum_.enum.md) diff --git a/packages/rpc-core/test/e2e/basics.test.js b/packages/rpc-core/test/e2e/basics.test.js index 0dd0318eee..55ecc8e9be 100644 --- a/packages/rpc-core/test/e2e/basics.test.js +++ b/packages/rpc-core/test/e2e/basics.test.js @@ -26,4 +26,17 @@ describe.skip('e2e basics', () => { throw error; }); }); + + it('retrieves the system properties', () => { + return api.system + .properties() + .then((properties) => { + console.error('properties', properties); + }) + .catch((error) => { + console.error(error); + + throw error; + }); + }); }); diff --git a/packages/type-jsonrpc/src/chain.ts b/packages/type-jsonrpc/src/chain.ts index 879094d625..77cee78504 100644 --- a/packages/type-jsonrpc/src/chain.ts +++ b/packages/type-jsonrpc/src/chain.ts @@ -33,8 +33,8 @@ const getBlockHash: RpcMethodOpt = { type: 'Hash' }; -const getHead: RpcMethodOpt = { - description: 'Retrieves the best headerHash', +const getFinalisedHead: RpcMethodOpt = { + description: 'Get hash of the last finalised block in the canon chain', params: [], type: 'Hash' }; @@ -58,6 +58,28 @@ const subscribeNewHead: RpcMethodOpt = { type: 'Header' }; +const subscribeFinalisedHeads: RpcMethodOpt = { + description: 'Retrieves the best finalised header via subscription', + params: [], + pubsub: [ + 'finalisedHead', + 'subscribeFinalisedHeads', + 'unsubscribeFinalisedHeads' + ], + type: 'Header' +}; + +const subscribeRuntimeVersion: RpcMethodOpt = { + description: 'Retrieves the runtime version via subscription', + params: [], + pubsub: [ + 'runtimeVersion', + 'subscribeRuntimeVersion', + 'unsubscribeRuntimeVersion' + ], + type: 'RuntimeVersion' +}; + const section = 'chain'; /** @@ -71,9 +93,11 @@ export default { methods: { getBlock: createMethod(section, 'getBlock', getBlock), getBlockHash: createMethod(section, 'getBlockHash', getBlockHash), - getHead: createMethod(section, 'getHead', getHead), + getFinalisedHead: createMethod(section, 'getFinalisedHead', getFinalisedHead), getHeader: createMethod(section, 'getHeader', getHeader), getRuntimeVersion: createMethod(section, 'getRuntimeVersion', getRuntimeVersion), + subscribeFinalisedHeads: createMethod(section, 'subscribeFinalisedHeads', subscribeFinalisedHeads), + subscribeRuntimeVersion: createMethod(section, 'subscribeRuntimeVersion', subscribeRuntimeVersion), subscribeNewHead: createMethod(section, 'subscribeNewHead', subscribeNewHead) } } as RpcSection; diff --git a/packages/type-jsonrpc/src/state.ts b/packages/type-jsonrpc/src/state.ts index 20b975b29d..2e1e1c88fc 100644 --- a/packages/type-jsonrpc/src/state.ts +++ b/packages/type-jsonrpc/src/state.ts @@ -11,19 +11,10 @@ import createParam from './create/param'; const call: RpcMethodOpt = { description: 'Perform a call to a builtin on the chain', - params: [ - createParam('method', 'Text'), - createParam('data', 'Bytes') - ], - type: 'Bytes' -}; - -const callAt: RpcMethodOpt = { - description: 'Perform a call to a builtin on the chain (At block)', params: [ createParam('method', 'Text'), createParam('data', 'Bytes'), - createParam('block', 'Hash') + createParam('block', 'Hash', { isOptional: true }) ], type: 'Bytes' }; @@ -31,33 +22,17 @@ const callAt: RpcMethodOpt = { const getStorage: RpcMethodOpt = { description: 'Retrieves the storage for a key', params: [ - createParam('key', 'StorageKey') + createParam('key', 'StorageKey'), + createParam('block', 'Hash', { isOptional: true }) ], type: 'StorageData' }; -const getStorageAt: RpcMethodOpt = { - description: 'Retrieves the storage for a key at a specific block', - params: [ - createParam('key', 'Bytes'), - createParam('block', 'Hash') - ], - type: 'Bytes' -}; - const getStorageHash: RpcMethodOpt = { description: 'Retrieves the storage hash', params: [ - createParam('key', 'Bytes') - ], - type: 'Hash' -}; - -const getStorageHashAt: RpcMethodOpt = { - description: 'Retrieves the storage hash at a specific block', - params: [ - createParam('key', 'Bytes'), - createParam('block', 'Hash') + createParam('key', 'StorageKey'), + createParam('block', 'Hash', { isOptional: true }) ], type: 'Hash' }; @@ -65,16 +40,8 @@ const getStorageHashAt: RpcMethodOpt = { const getStorageSize: RpcMethodOpt = { description: 'Retrieves the storage size', params: [ - createParam('key', 'Bytes') - ], - type: 'u64' -}; - -const getStorageSizeAt: RpcMethodOpt = { - description: 'Retrieves the storage size at a specific block', - params: [ - createParam('key', 'Bytes'), - createParam('block', 'Hash') + createParam('key', 'StorageKey'), + createParam('block', 'Hash', { isOptional: true }) ], type: 'u64' }; @@ -125,14 +92,10 @@ export default { section, methods: { call: createMethod(section, 'call', call), - callAt: createMethod(section, 'callAt', callAt), getMetadata: createMethod(section, 'getMetadata', getMetadata), getStorage: createMethod(section, 'getStorage', getStorage), - getStorageAt: createMethod(section, 'getStorageAt', getStorageAt), getStorageHash: createMethod(section, 'getStorageHash', getStorageHash), - getStorageHashAt: createMethod(section, 'getStorageHashAt', getStorageHashAt), getStorageSize: createMethod(section, 'getStorageSize', getStorageSize), - getStorageSizeAt: createMethod(section, 'getStorageSizeAt', getStorageSizeAt), queryStorage: createMethod(section, 'queryStorage', queryStorage), subscribeStorage: createMethod(section, 'subscribeStorage', subscribeStorage) } diff --git a/packages/type-jsonrpc/src/system.ts b/packages/type-jsonrpc/src/system.ts index 78363072be..d511f3433d 100644 --- a/packages/type-jsonrpc/src/system.ts +++ b/packages/type-jsonrpc/src/system.ts @@ -26,6 +26,12 @@ const chain: RpcMethodOpt = { type: 'Text' }; +const properties: RpcMethodOpt = { + description: 'Get a custom set of properties as a JSON object, defined in the chain spec', + params: [], + type: 'ChainProperties' +}; + const section = 'system'; /** @@ -39,6 +45,7 @@ export default { methods: { chain: createMethod(section, 'chain', chain), name: createMethod(section, 'name', name), + properties: createMethod(section, 'properties', properties), version: createMethod(section, 'version', version) } } as RpcSection; diff --git a/packages/types/README.md b/packages/types/README.md index 9706e09f76..8e407a3d70 100644 --- a/packages/types/README.md +++ b/packages/types/README.md @@ -4,7 +4,7 @@ Implementation of the types and their (de-)serialisation via [parity-codec](http ## Substrate types -These types implement specific types that are found as part of the Substrate base: [[AccountId]], [[AccountIndex]], [[Address]], [[AuthorityId]], [[Balance]], [[Block]], [[BlockNumber]], [[Bool]], [[Bytes]], [[Data]], [[Digest]], [[Event]], [[EventRecord]], [[Extrinsic]], [[Extrinsics]], [[ExtrinsicEra]], [[ExtrinsicSignature]], [[ExtrinsicStatus]], [[Gas]], [[H256]], [[H512]], [[Hash]], [[Header]], [[Justification]], [[KeyValue]], [[Metadata]], [[Method]], [[MisbehaviorReport]], [[Moment]], [[NewAccountOutcome]], [[Nonce]], [[Null]], [[Origin]], [[ParachainId]], [[PendingExtrinsics]], [[Perbill]], [[Permill]], [[PropIndex]], [[Proposal]], [[ProposalIndex]], [[ReferendumIndex]], [[RuntimeVersion]], [[SessionKey]], [[Signature]], [[SignaturePayload]], [[SignedBlock]], [[StorageChangeSet]], [[StorageData]], [[StorageKey]], [[StoredPendingChange]], [[Text]], [[Type]], [[U8]], [[U16]], [[U32]], [[U64]], [[U128]], [[U256]], [[ValidatorPrefs]], [[VoteIndex]], [[VoteThreshold]] +These types implement specific types that are found as part of the Substrate base: [[AccountId]], [[AccountIndex]], [[Address]], [[AuthorityId]], [[Balance]], [[Block]], [[BlockNumber]], [[Bool]], [[Bytes]], [[ChainProperties]] [[Data]], [[Digest]], [[Event]], [[EventRecord]], [[Extrinsic]], [[Extrinsics]], [[ExtrinsicEra]], [[ExtrinsicSignature]], [[ExtrinsicStatus]], [[Gas]], [[H256]], [[H512]], [[Hash]], [[Header]], [[Justification]], [[KeyValue]], [[Metadata]], [[Method]], [[MisbehaviorReport]], [[Moment]], [[NewAccountOutcome]], [[Nonce]], [[Null]], [[Origin]], [[ParachainId]], [[PendingExtrinsics]], [[Perbill]], [[Permill]], [[PropIndex]], [[Proposal]], [[ProposalIndex]], [[ReferendumIndex]], [[RuntimeVersion]], [[SessionKey]], [[Signature]], [[SignaturePayload]], [[SignedBlock]], [[StorageChangeSet]], [[StorageData]], [[StorageKey]], [[StoredPendingChange]], [[Text]], [[Type]], [[U8]], [[U16]], [[U32]], [[U64]], [[U128]], [[U256]], [[ValidatorPrefs]], [[VoteIndex]], [[VoteThreshold]] ## Codec types diff --git a/packages/types/src/ChainProperties.ts b/packages/types/src/ChainProperties.ts new file mode 100644 index 0000000000..2ee1eef149 --- /dev/null +++ b/packages/types/src/ChainProperties.ts @@ -0,0 +1,74 @@ +// Copyright 2017-2018 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { Codec } from './types'; + +// TODO Expose known properties as they become known, currently we have `tokenSymbol` (e.g. BBQ) + +/** + * @name ChainProperties + * @description + * Wraps the properties retrieved from the chain via the `system.properties` RPC call. It extends + * the standard JS Map with known values exposed as a getter. While it implements a Codec, it is + * limited ain that it can only be used with input objects, i.e. no hex decoding. + * @noInheritDoc + */ +export default class ChainProperties extends Map implements Codec { + constructor (value: { [index: string]: any } = {}) { + super(ChainProperties.decodeChainProperties(value)); + } + + private static decodeChainProperties (value: { [index: string]: any }): Array<[string, any]> { + return Object.keys(value).map((key) => ([ + key, value[key] + ] as [string, any])); + } + + /** + * @description Always 0, never encodes as a Uint8Array + */ + get encodedLength (): number { + return 0; + } + + /** + * @description Returns a specific names entry in the structure + * @param name The name of the entry to retrieve + */ + get (name: string): any | undefined { + return super.get(name); + } + + /** + * @description Unimplemented, will throw + */ + toHex (): string { + throw new Error('Unimplemented'); + } + + /** + * @description Converts the Object to JSON, typically used for RPC transfers + */ + toJSON (): any { + return [...this.keys()].reduce((json, key) => { + json[key] = this.get(key); + + return json; + }, {} as any); + } + + /** + * @description Returns the string representation of the value + */ + toString () { + return JSON.stringify(this.toJSON()); + } + + /** + * @description Unimplemented, will throw + */ + toU8a (isBare?: boolean): Uint8Array { + throw new Error('Unimplemented'); + } +} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 73fbfee790..cc2696d0fb 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -25,6 +25,7 @@ export { default as BlockNumber } from './BlockNumber'; // NOTE We are exporting Bool as bool to match with Rust export { default as bool } from './Bool'; export { default as Bytes } from './Bytes'; +export { default as ChainProperties } from './ChainProperties'; export { default as Data } from './Data'; export { default as Digest } from './Digest'; export { default as Event } from './Event';