From 82dbc93f7922186efc75570eafd8e039efdcc953 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Fri, 5 Oct 2018 12:29:06 +0200 Subject: [PATCH] Mortal -> Extrinsic, expand for decoding start (#212) * Mortal -> Extrinsic, expand for decoding start * Method, Section -> Rpc{Method, Section} * Only expose callIndex * CallIndex -> MethodIndex in spec --- packages/api-observable/src/Base.ts | 4 +- packages/api-observable/src/Calls.ts | 4 +- packages/api/src/index.ts | 14 +-- packages/type-extrinsics/src/types.d.ts | 4 +- .../src/utils/createUnchecked.ts | 10 +- packages/type-jsonrpc/src/author.ts | 8 +- packages/type-jsonrpc/src/chain.ts | 18 +-- packages/type-jsonrpc/src/create/method.ts | 4 +- packages/type-jsonrpc/src/create/param.ts | 6 +- packages/type-jsonrpc/src/state.ts | 26 ++-- packages/type-jsonrpc/src/system.ts | 10 +- packages/type-jsonrpc/src/types.d.ts | 14 +-- packages/types/src/Address.ts | 2 +- packages/types/src/Block.spec.js | 72 ----------- packages/types/src/Extrinsic.ts | 95 ++++++++++++-- .../{TransactionEra.ts => ExtrinsicEra.ts} | 2 +- packages/types/src/ExtrinsicSignature.ts | 118 ++++++++++++++++++ packages/types/src/{Call.ts => Method.ts} | 25 ++-- ...{CallIndex.spec.js => MethodIndex.spec.js} | 8 +- .../src/{CallIndex.ts => MethodIndex.ts} | 2 +- packages/types/src/SignaturePayload.ts | 20 +-- packages/types/src/SignedBlock.rpc.json | 2 +- packages/types/src/SignedBlock.spec.js | 4 +- packages/types/src/TransactionSignature.ts | 50 -------- .../types/src/UncheckedMortalExtrinsic.ts | 102 --------------- packages/types/src/codec/Struct.ts | 7 +- packages/types/src/codec/createType.ts | 5 +- packages/types/src/index.ts | 9 +- 28 files changed, 312 insertions(+), 333 deletions(-) delete mode 100644 packages/types/src/Block.spec.js rename packages/types/src/{TransactionEra.ts => ExtrinsicEra.ts} (89%) create mode 100644 packages/types/src/ExtrinsicSignature.ts rename packages/types/src/{Call.ts => Method.ts} (66%) rename packages/types/src/{CallIndex.spec.js => MethodIndex.spec.js} (74%) rename packages/types/src/{CallIndex.ts => MethodIndex.ts} (90%) delete mode 100644 packages/types/src/TransactionSignature.ts delete mode 100644 packages/types/src/UncheckedMortalExtrinsic.ts diff --git a/packages/api-observable/src/Base.ts b/packages/api-observable/src/Base.ts index 533a417b34..a7b8e1b130 100644 --- a/packages/api-observable/src/Base.ts +++ b/packages/api-observable/src/Base.ts @@ -3,7 +3,7 @@ // of the ISC license. See the LICENSE file for details. import { RxApiInterface, RxApiInterface$Method, RxApiInterface$Section } from '@polkadot/api-rx/types'; -import { Method } from '@polkadot/jsonrpc/types'; +import { RpcMethod } from '@polkadot/jsonrpc/types'; import { EMPTY, Observable, combineLatest, from } from 'rxjs'; import { defaultIfEmpty, map } from 'rxjs/operators'; @@ -83,7 +83,7 @@ export default class ApiBase { return this._api.isConnected(); } - rawCall = ({ method, section }: Method, ...params: Array): Observable => { + rawCall = ({ method, section }: RpcMethod, ...params: Array): Observable => { const apiSection = this._api[section as keyof RxApiInterface] as RxApiInterface$Section; assert(apiSection, `Unable to find 'api.${section}'`); diff --git a/packages/api-observable/src/Calls.ts b/packages/api-observable/src/Calls.ts index a7209d855e..1eb4be7937 100644 --- a/packages/api-observable/src/Calls.ts +++ b/packages/api-observable/src/Calls.ts @@ -4,7 +4,7 @@ import { Observable } from 'rxjs'; import { defaultIfEmpty, map } from 'rxjs/operators'; -import { BlockNumber, Hash, Header, SignedBlock, UncheckedMortalExtrinsic } from '@polkadot/types/index'; +import { BlockNumber, Hash, Header, SignedBlock, Extrinsic } from '@polkadot/types/index'; import ApiQueries from './Queries'; @@ -44,7 +44,7 @@ export default class ApiCalls extends ApiQueries { return this._api.system.version(); } - submitExtrinsic = (extrinsic: UncheckedMortalExtrinsic): Observable => { + submitExtrinsic = (extrinsic: Extrinsic): Observable => { return this._api.author.submitExtrinsic(extrinsic); } } diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index f1e314ee62..d3758b0691 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -3,7 +3,7 @@ // of the ISC license. See the LICENSE file for details. import { ProviderInterface, ProviderInterface$Callback } from '@polkadot/api-provider/types'; -import { Section, Method } from '@polkadot/jsonrpc/types'; +import { RpcSection, RpcMethod } from '@polkadot/jsonrpc/types'; import { ApiInterface, ApiInterface$Section, ApiInterface$Section$Method } from './types'; import { Base, Vector, createType } from '@polkadot/types/codec'; @@ -62,7 +62,7 @@ export default class Api implements ApiInterface { * Api.signature({ name: 'test_method', params: [ { name: 'dest', type: 'Address' } ], type: 'Address' }); // => test_method (dest: Address): Address * */ - static signature ({ method, params, type }: Method): string { + static signature ({ method, params, type }: RpcMethod): string { const inputs = params.map(({ name, type }) => `${name}: ${type}` ).join(', '); @@ -70,7 +70,7 @@ export default class Api implements ApiInterface { return `${method} (${inputs}): ${type}`; } - private createInterface ({ methods, section }: Section): ApiInterface$Section { + private createInterface ({ methods, section }: RpcSection): ApiInterface$Section { return Object .keys(methods) .reduce((exposed, method) => { @@ -85,7 +85,7 @@ export default class Api implements ApiInterface { }, {} as ApiInterface$Section); } - private createMethodSend (rpcName: string, method: Method): ApiInterface$Section$Method { + private createMethodSend (rpcName: string, method: RpcMethod): ApiInterface$Section$Method { const call = async (...values: Array): Promise => { // TODO Warn on deprecated methods try { @@ -106,7 +106,7 @@ export default class Api implements ApiInterface { return call as ApiInterface$Section$Method; } - private createMethodSubscribe (rpcName: string, method: Method): ApiInterface$Section$Method { + private createMethodSubscribe (rpcName: string, method: RpcMethod): ApiInterface$Section$Method { const unsubscribe = (subscriptionId: any): Promise => this._provider.unsubscribe(rpcName, method.subscribe[1], subscriptionId); const _call = async (...values: Array): Promise => { @@ -138,7 +138,7 @@ export default class Api implements ApiInterface { return call; } - private formatInputs (method: Method, inputs: Array): Array { + private formatInputs (method: RpcMethod, inputs: Array): Array { assert(method.params.length === inputs.length, `Expected ${method.params.length} parameters, ${inputs.length} found instead`); return method.params.map(({ type }, index) => @@ -146,7 +146,7 @@ export default class Api implements ApiInterface { ); } - private formatOutput (method: Method, params: Array, result?: any): Base { + private formatOutput (method: RpcMethod, params: Array, result?: any): Base { const base = createType(method.type as string).fromJSON(result); if (method.type === 'StorageData') { diff --git a/packages/type-extrinsics/src/types.d.ts b/packages/type-extrinsics/src/types.d.ts index f21323ef63..1b60f48f11 100644 --- a/packages/type-extrinsics/src/types.d.ts +++ b/packages/type-extrinsics/src/types.d.ts @@ -2,11 +2,11 @@ // This software may be modified and distributed under the terms // of the ISC license. See the LICENSE file for details. -import { UncheckedMortalExtrinsic } from '@polkadot/types/index'; +import { Extrinsic } from '@polkadot/types/index'; import { FunctionMetadata } from '@polkadot/types/Metadata'; export interface ExtrinsicFunction { - (...args: any[]): UncheckedMortalExtrinsic, + (...args: any[]): Extrinsic, callIndex: Uint8Array, meta: FunctionMetadata, method: string; diff --git a/packages/type-extrinsics/src/utils/createUnchecked.ts b/packages/type-extrinsics/src/utils/createUnchecked.ts index ef559b7aaf..8166523c18 100644 --- a/packages/type-extrinsics/src/utils/createUnchecked.ts +++ b/packages/type-extrinsics/src/utils/createUnchecked.ts @@ -5,7 +5,7 @@ import { ExtrinsicFunction } from '../types'; import { FunctionMetadata } from '@polkadot/types/Metadata'; -import { Call, UncheckedMortalExtrinsic } from '@polkadot/types/index'; +import { Extrinsic, Method } from '@polkadot/types/index'; /** * From the metadata of a function in the module's storage, generate the function @@ -28,14 +28,14 @@ export default function createDescriptor ( arg.type.toString() !== 'Origin' ); - extrinsicFn = (...args: any[]): UncheckedMortalExtrinsic => { + extrinsicFn = (...args: any[]): Extrinsic => { if (expectedArgs.length.valueOf() !== args.length) { throw new Error(`Extrinsic ${section}.${method} expects ${expectedArgs.length.valueOf()} arguments, got ${args.length}.`); } - const call = new Call(callIndex, meta, args); - - return new UncheckedMortalExtrinsic(call); + return new Extrinsic({ + method: new Method(callIndex, meta, args) + }); }; extrinsicFn.callIndex = callIndex; diff --git a/packages/type-jsonrpc/src/author.ts b/packages/type-jsonrpc/src/author.ts index 59646a09ae..1ba72e1d4f 100644 --- a/packages/type-jsonrpc/src/author.ts +++ b/packages/type-jsonrpc/src/author.ts @@ -2,18 +2,18 @@ // This software may be modified and distributed under the terms // of the ISC license. See the LICENSE file for details. -import { MethodOpt, Section } from './types'; +import { RpcMethodOpt, RpcSection } from './types'; import createMethod from './create/method'; import createParam from './create/param'; -const pendingExtrinsics: MethodOpt = { +const pendingExtrinsics: RpcMethodOpt = { description: 'Returns all pending extrinsics, potentially grouped by sender', params: [], type: 'PendingExtrinsics' }; -const submitExtrinsic: MethodOpt = { +const submitExtrinsic: RpcMethodOpt = { isSigned: true, description: 'Submit a fully formatted extrinsic for block inclusion', params: [ @@ -36,4 +36,4 @@ export default { pendingExtrinsics: createMethod(section, 'pendingExtrinsics', pendingExtrinsics), submitExtrinsic: createMethod(section, 'submitExtrinsic', submitExtrinsic) } -} as Section; +} as RpcSection; diff --git a/packages/type-jsonrpc/src/chain.ts b/packages/type-jsonrpc/src/chain.ts index efe3575762..c2228b7e56 100644 --- a/packages/type-jsonrpc/src/chain.ts +++ b/packages/type-jsonrpc/src/chain.ts @@ -2,12 +2,12 @@ // This software may be modified and distributed under the terms // of the ISC license. See the LICENSE file for details. -import { MethodOpt, Section } from './types'; +import { RpcMethodOpt, RpcSection } from './types'; import createMethod from './create/method'; import createParam from './create/param'; -const getBlock: MethodOpt = { +const getBlock: RpcMethodOpt = { description: 'Get header and body of a relay chain block', params: [ createParam('hash', 'Hash') @@ -15,7 +15,7 @@ const getBlock: MethodOpt = { type: 'SignedBlock' }; -const getBlockHash: MethodOpt = { +const getBlockHash: RpcMethodOpt = { description: 'Get the block hash for a specific block', params: [ createParam('blockNumber', 'BlockNumber', { isOptional: true }) @@ -23,13 +23,13 @@ const getBlockHash: MethodOpt = { type: 'Hash' }; -const getHead: MethodOpt = { +const getHead: RpcMethodOpt = { description: 'Retrieves the best headerHash', params: [], type: 'Hash' }; -const getHeader: MethodOpt = { +const getHeader: RpcMethodOpt = { description: 'Retrieves the header for a specific block', params: [ createParam('hash', 'Hash') @@ -37,13 +37,13 @@ const getHeader: MethodOpt = { type: 'Header' }; -const getRuntimeVersion: MethodOpt = { +const getRuntimeVersion: RpcMethodOpt = { description: ' Get the runtime version', params: [], type: 'RuntimeVersion' }; -const getRuntimeVersionAt: MethodOpt = { +const getRuntimeVersionAt: RpcMethodOpt = { description: ' Get the runtime version at a specific block', params: [ createParam('hash', 'Hash') @@ -51,7 +51,7 @@ const getRuntimeVersionAt: MethodOpt = { type: 'RuntimeVersion' }; -const newHead: MethodOpt = { +const newHead: RpcMethodOpt = { description: 'Retrieves the best header via subscription', subscribe: [ 'chain_subscribeNewHead', @@ -80,4 +80,4 @@ export default { getRuntimeVersionAt: createMethod(section, 'getRuntimeVersionAt', getRuntimeVersionAt), newHead: createMethod(section, 'newHead', newHead) } -} as Section; +} as RpcSection; diff --git a/packages/type-jsonrpc/src/create/method.ts b/packages/type-jsonrpc/src/create/method.ts index 36e36e703c..ab3980e0b9 100644 --- a/packages/type-jsonrpc/src/create/method.ts +++ b/packages/type-jsonrpc/src/create/method.ts @@ -2,11 +2,11 @@ // This software may be modified and distributed under the terms // of the ISC license. See the LICENSE file for details. -import { MethodOpt, Method } from '../types'; +import { RpcMethodOpt, RpcMethod } from '../types'; import isUndefined from '@polkadot/util/is/undefined'; -export default function createMethod (section: string, method: string, { description, params, type, isDeprecated = false, isHidden = false, isSigned = false, subscribe }: MethodOpt): Method { +export default function createMethod (section: string, method: string, { description, params, type, isDeprecated = false, isHidden = false, isSigned = false, subscribe }: RpcMethodOpt): RpcMethod { return { description, isDeprecated, diff --git a/packages/type-jsonrpc/src/create/param.ts b/packages/type-jsonrpc/src/create/param.ts index 3143410ad5..48329cfc4c 100644 --- a/packages/type-jsonrpc/src/create/param.ts +++ b/packages/type-jsonrpc/src/create/param.ts @@ -3,13 +3,13 @@ // of the ISC license. See the LICENSE file for details. import { CodecTypes } from '@polkadot/types/types'; -import { Param } from '../types'; +import { RpcParam } from '../types'; -type ParamOptions = { +type RpcParamOptions = { isOptional?: boolean }; -export default function createParam (name: string, type: CodecTypes, { isOptional = false }: ParamOptions = { isOptional: false }): Param { +export default function createParam (name: string, type: CodecTypes, { isOptional = false }: RpcParamOptions = { isOptional: false }): RpcParam { return { isOptional, name, diff --git a/packages/type-jsonrpc/src/state.ts b/packages/type-jsonrpc/src/state.ts index 910ca7bdbd..0c8cdea176 100644 --- a/packages/type-jsonrpc/src/state.ts +++ b/packages/type-jsonrpc/src/state.ts @@ -2,12 +2,12 @@ // This software may be modified and distributed under the terms // of the ISC license. See the LICENSE file for details. -import { MethodOpt, Section } from './types'; +import { RpcMethodOpt, RpcSection } from './types'; import createMethod from './create/method'; import createParam from './create/param'; -const call: MethodOpt = { +const call: RpcMethodOpt = { description: 'Perform a call to a builtin on the chain', params: [ createParam('method', 'Text'), @@ -16,7 +16,7 @@ const call: MethodOpt = { type: 'Bytes' }; -const callAt: MethodOpt = { +const callAt: RpcMethodOpt = { description: 'Perform a call to a builtin on the chain (At block)', params: [ createParam('method', 'Text'), @@ -26,13 +26,13 @@ const callAt: MethodOpt = { type: 'Bytes' }; -const getMetadata: MethodOpt = { +const getMetadata: RpcMethodOpt = { description: 'Returns the runtime metadata', params: [], type: 'Metadata' }; -const getMetadataAt: MethodOpt = { +const getMetadataAt: RpcMethodOpt = { description: 'Returns the runtime metadata', params: [ createParam('block', 'Hash') @@ -40,7 +40,7 @@ const getMetadataAt: MethodOpt = { type: 'Metadata' }; -const getStorage: MethodOpt = { +const getStorage: RpcMethodOpt = { description: 'Retrieves the storage for a key', params: [ createParam('key', 'StorageKey') @@ -48,7 +48,7 @@ const getStorage: MethodOpt = { type: 'StorageData' }; -const getStorageAt: MethodOpt = { +const getStorageAt: RpcMethodOpt = { description: 'Retrieves the storage for a key at a specific block', params: [ createParam('key', 'Bytes'), @@ -57,7 +57,7 @@ const getStorageAt: MethodOpt = { type: 'Bytes' }; -const getStorageHash: MethodOpt = { +const getStorageHash: RpcMethodOpt = { description: 'Retrieves the storage hash', params: [ createParam('key', 'Bytes') @@ -65,7 +65,7 @@ const getStorageHash: MethodOpt = { type: 'Hash' }; -const getStorageHashAt: MethodOpt = { +const getStorageHashAt: RpcMethodOpt = { description: 'Retrieves the storage hash at a specific block', params: [ createParam('key', 'Bytes'), @@ -74,7 +74,7 @@ const getStorageHashAt: MethodOpt = { type: 'Hash' }; -const getStorageSize: MethodOpt = { +const getStorageSize: RpcMethodOpt = { description: 'Retrieves the storage size', params: [ createParam('key', 'Bytes') @@ -82,7 +82,7 @@ const getStorageSize: MethodOpt = { type: 'u64' }; -const getStorageSizeAt: MethodOpt = { +const getStorageSizeAt: RpcMethodOpt = { description: 'Retrieves the storage size at a specific block', params: [ createParam('key', 'Bytes'), @@ -91,7 +91,7 @@ const getStorageSizeAt: MethodOpt = { type: 'u64' }; -const storage: MethodOpt = { +const storage: RpcMethodOpt = { description: 'Subscribes to storage changes for the provided keys', subscribe: [ 'state_subscribeStorage', @@ -127,4 +127,4 @@ export default { getStorageSizeAt: createMethod(section, 'getStorageSizeAt', getStorageSizeAt), storage: createMethod(section, 'storage', storage) } -} as Section; +} as RpcSection; diff --git a/packages/type-jsonrpc/src/system.ts b/packages/type-jsonrpc/src/system.ts index dc9e65b00f..ef1d826908 100644 --- a/packages/type-jsonrpc/src/system.ts +++ b/packages/type-jsonrpc/src/system.ts @@ -2,23 +2,23 @@ // This software may be modified and distributed under the terms // of the ISC license. See the LICENSE file for details. -import { MethodOpt, Section } from './types'; +import { RpcMethodOpt, RpcSection } from './types'; import createMethod from './create/method'; -const chain: MethodOpt = { +const chain: RpcMethodOpt = { description: 'Retrieves the chain', params: [], type: 'Text' }; -const name: MethodOpt = { +const name: RpcMethodOpt = { description: 'Retrieves the node name', params: [], type: 'Text' }; -const version: MethodOpt = { +const version: RpcMethodOpt = { description: 'Retrieves the version of the node', params: [], type: 'Text' @@ -39,4 +39,4 @@ export default { name: createMethod(section, 'name', name), version: createMethod(section, 'version', version) } -} as Section; +} as RpcSection; diff --git a/packages/type-jsonrpc/src/types.d.ts b/packages/type-jsonrpc/src/types.d.ts index abdfb661dc..ad6d2da903 100644 --- a/packages/type-jsonrpc/src/types.d.ts +++ b/packages/type-jsonrpc/src/types.d.ts @@ -4,24 +4,24 @@ import { CodecTypes } from '@polkadot/types/types'; -export type Param = { +export type RpcParam = { isOptional: boolean, name: string, type: CodecTypes }; -export type MethodOpt = { +export type RpcMethodOpt = { description: string, isDeprecated?: boolean, isHidden?: boolean, isSigned?: boolean, isSubscription?: boolean, - params: Array, + params: Array, subscribe?: [string, string], type: CodecTypes }; -export type Method = { +export type RpcMethod = { alias?: string, description: string, isDeprecated: boolean, @@ -29,18 +29,18 @@ export type Method = { isSigned: boolean, isSubscription: boolean, method: string, - params: Array, + params: Array, section: string, subscribe: [string, string], type: CodecTypes }; -export type Section = { +export type RpcSection = { isDeprecated: boolean, isHidden: boolean, description: string, section: string, methods: { - [index: string]: Method + [index: string]: RpcMethod } }; diff --git a/packages/types/src/Address.ts b/packages/types/src/Address.ts index edaec822d5..c8e6224f61 100644 --- a/packages/types/src/Address.ts +++ b/packages/types/src/Address.ts @@ -46,7 +46,7 @@ export default class Address extends Base { } byteLength (): number { - return super.byteLength() + ( + return this.raw.byteLength() + ( this.raw instanceof AccountIndex ? 0 : 1 diff --git a/packages/types/src/Block.spec.js b/packages/types/src/Block.spec.js deleted file mode 100644 index 8deb0d4ba5..0000000000 --- a/packages/types/src/Block.spec.js +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2017-2018 @polkadot/types authors & contributors -// This software may be modified and distributed under the terms -// of the ISC license. See the LICENSE file for details. - -import hexToU8a from '@polkadot/util/hex/toU8a'; - -import Block from './Block'; - -describe('Block', () => { - it('decodes a block properly', () => { - const block = new Block(); - - block.fromU8a(hexToU8a( - '0x' + - // parent_hash - '0900000000000000000000000000000000000000000000000000000000000009' + - // number - '4300000000000000' + - // state_root - '0800000000000000000000000000000000000000000000000000000000000008' + - // transaction_root - '0700000000000000000000000000000000000000000000000000000000000007' + - // digest - '08' + // 2 << 2 - '0401' + - '0402' + - // transactions - '04' + // 1 << 2 - // 111 bytes in compact encoding - 'bd01' + - // prefix - 'ff' + - '0000000000000000000000000000000000000000000000000000000000000000' + - '00000000' + - '0300' + - '7527000000000000' + - '0000000000000000000000000000000000000000000000000000000000000000' + - '0000000000000000000000000000000000000000000000000000000000000000' - )); - - expect( - block.header.blockNumber.toNumber() - ).toEqual(67); - expect( - block.extrinsics.length - ).toEqual(1); // eslint-disable-line - expect( - block.extrinsics.get(0).length - ).toEqual(111); // eslint-disable-line - }); - - // FIXME check again when we have a valid chain/UI - it.skip('has a valid block hash', () => { - expect( - new Block({ - extrinsics: [ - [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 139, 165, 170, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - ], - header: { - digest: { - logs: [] - }, - extrinsicsRoot: '0x5ce1a2c55efaf371f06fd94672779daf130591a12f7513ae786bea4fa7bd499e', - number: 1556355, - parentHash: '0x09223919f63b5ded0c7bf7d953ba22bf30ea8a19e6be4de35f25163b2b268490', - stateRoot: '0xd45159e04f36955ecb9c73d6ca514ac2d0e3ce00f58588b7c142d36cf7d237ec' - } - }).hash.toHex() - ).toEqual('0xd1b7e2c8f1ba2665d89dba334dcf45caa12e34d22587a09e2d03372366a81d8b'); - }); -}); diff --git a/packages/types/src/Extrinsic.ts b/packages/types/src/Extrinsic.ts index d4908ce2d9..3984bae1f1 100644 --- a/packages/types/src/Extrinsic.ts +++ b/packages/types/src/Extrinsic.ts @@ -2,17 +2,50 @@ // This software may be modified and distributed under the terms // of the ISC license. See the LICENSE file for details. -import u8aToHex from '@polkadot/util/u8a/toHex'; +import { KeyringPair } from '@polkadot/util-keyring/types'; +import { AnyNumber, AnyU8a } from './types'; + import blake2Asu8a from '@polkadot/util-crypto/blake2/asU8a'; +import u8aConcat from '@polkadot/util/u8a/concat'; +import u8aToHex from '@polkadot/util/u8a/toHex'; -import Bytes from './Bytes'; +import Compact from './codec/Compact'; +import Struct from './codec/Struct'; +import ExtrinsicSignature from './ExtrinsicSignature'; import Hash from './Hash'; +import { FunctionMetadata } from './Metadata'; +import Method from './Method'; + +type ExtrinsicValue = { + method?: Method + signature?: ExtrinsicSignature +}; + +// console.error('ExtrinsicSignature', ExtrinsicSignature); +// console.error('Method', Method); + +/** + * Representation of an Extrinsic in the system. It contains the actual call, + * (optional) signature and encodes with an actual length prefix + * + * {@link https://github.com/paritytech/wiki/blob/master/Extrinsic.md#the-extrinsic-format-for-node}. + * + * Can be: + * - signed, to create a transaction + * - left as is, to create an inherent + */ +export default class Extrinsic extends Struct { + constructor (value?: ExtrinsicValue) { + super({ + signature: ExtrinsicSignature, + method: Method + }, value); + } + + get method (): Method { + return this.raw.method as Method; + } -// Representation of an Extrinsic in the system. -// -// NOTE At this point we are just keeping to a bare-bones Vec structure, -// this should be expanded to do the automatic decoding of an extrinsic -export default class Extrinsic extends Bytes { // convernience, encodes the extrinsic and returns the actual hash get hash (): Hash { return new Hash( @@ -20,6 +53,54 @@ export default class Extrinsic extends Bytes { ); } + get length (): number { + return this.toU8a(true).length; + } + + get meta (): FunctionMetadata { + return this.method.meta; + } + + // the actual [sectionIndex, methodIndex] as used + get callIndex (): Uint8Array { + return this.method.callIndex; + } + + get signature (): ExtrinsicSignature { + return this.raw.signature as ExtrinsicSignature; + } + + byteLength (): number { + const length = this.length; + + return length + Compact.encode(length).length; + } + + fromU8a (input: Uint8Array): Extrinsic { + const [offset, length] = Compact.decode(input); + + super.fromU8a(input.subarray(offset, offset + length.toNumber())); + + return this; + } + + sign (signerPair: KeyringPair, nonce: AnyNumber, blockHash: AnyU8a): Extrinsic { + this.signature.addSignature(this.method, signerPair, nonce, blockHash); + + return this; + } + + toU8a (isBare?: boolean): Uint8Array { + const encoded = super.toU8a(); + + return isBare + ? encoded + : u8aConcat( + Compact.encode(encoded.length), + encoded + ); + } + toHex (): string { return u8aToHex(this.toU8a()); } diff --git a/packages/types/src/TransactionEra.ts b/packages/types/src/ExtrinsicEra.ts similarity index 89% rename from packages/types/src/TransactionEra.ts rename to packages/types/src/ExtrinsicEra.ts index 0f8c82a18b..67b770c33c 100644 --- a/packages/types/src/TransactionEra.ts +++ b/packages/types/src/ExtrinsicEra.ts @@ -8,7 +8,7 @@ import U8aFixed from './codec/U8aFixed'; // Description of a transaction era // FIXME should be a enum? -export default class TransactionEra extends U8aFixed { +export default class ExtrinsicEra extends U8aFixed { constructor (value?: AnyU8a) { // FIXME this actually indicates an Immortal (i.e. 1 byte) super(value, 8); diff --git a/packages/types/src/ExtrinsicSignature.ts b/packages/types/src/ExtrinsicSignature.ts new file mode 100644 index 0000000000..1673404d26 --- /dev/null +++ b/packages/types/src/ExtrinsicSignature.ts @@ -0,0 +1,118 @@ +// Copyright 2017-2018 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. + +import { KeyringPair } from '@polkadot/util-keyring/types'; +import { AnyNumber, AnyU8a } from './types'; + +import u8aConcat from '@polkadot/util/u8a/concat'; + +import Struct from './codec/Struct'; +import Address from './Address'; +import ExtrinsicEra from './ExtrinsicEra'; +import Method from './Method'; +import Nonce from './Nonce'; +import Signature from './Signature'; +import SignaturePayload from './SignaturePayload'; + +type ExtrinsicSignatureValue = { + signer?: AnyU8a | Address, + signature?: AnyU8a + nonce?: AnyNumber, + era?: AnyU8a +}; + +const EMPTY_U8A = new Uint8Array(); +const IMMORTAL_ERA = new Uint8Array([0]); +const BIT_SIGNED = 0b10000000; +const BIT_UNSIGNED = 0; +const BIT_VERSION = 0b0000001; + +// Signature Information. +// 1/3/5/9/33 bytes: The signing account identity, in Address format +// 64 bytes: The Ed25519 signature of the Signing Payload +// 8 bytes: The Transaction Index of the signing account +// 2 bytes: The Transaction Era +export default class ExtrinsicSignature extends Struct { + constructor (value?: ExtrinsicSignatureValue) { + super({ + signer: Address, + signature: Signature, + nonce: Nonce, + era: ExtrinsicEra + }, value); + } + + get isSigned (): boolean { + return this.signature.length !== 0; + } + + get era (): ExtrinsicEra { + return this.raw.era as ExtrinsicEra; + } + + get nonce (): Nonce { + return this.raw.nonce as Nonce; + } + + get signature (): Signature { + return this.raw.signature as Signature; + } + + get signer (): Address { + return this.raw.signer as Address; + } + + get version (): number { + // Version Information. + // 1 byte: version information: + // - 7 low bits: version identifier (should be 0b0000001). + // - 1 high bit: signed flag: 1 if this is a transaction (e.g. contains a signature). + return BIT_VERSION | ( + this.isSigned + ? BIT_SIGNED + : BIT_UNSIGNED + ); + } + + addSignature (method: Method, signerPair: KeyringPair, nonce: AnyNumber, blockHash: AnyU8a, era: Uint8Array = IMMORTAL_ERA): ExtrinsicSignature { + const signer = new Address(signerPair.publicKey()); + + const signingPayload = new SignaturePayload({ + nonce, + method, + era, + blockHash + }); + const signature = new Signature(signingPayload.sign(signerPair)); + + this.raw.era = signingPayload.era; + this.raw.nonce = signingPayload.nonce; + this.raw.signer = signer; + this.raw.signature = signature; + + return this; + } + + fromU8a (input: Uint8Array): ExtrinsicSignature { + const version = input[0]; + + if ((version & BIT_SIGNED) === BIT_SIGNED) { + super.fromU8a(input.subarray(1)); + } else { + // Just clear signature, leave others as-is + this.raw.signature = new Signature(); + } + + return this; + } + + toU8a (isBare?: boolean): Uint8Array { + return u8aConcat( + new Uint8Array([this.version]), + this.isSigned + ? super.toU8a(isBare) + : EMPTY_U8A + ); + } +} diff --git a/packages/types/src/Call.ts b/packages/types/src/Method.ts similarity index 66% rename from packages/types/src/Call.ts rename to packages/types/src/Method.ts index 650c76b51d..cd84cc1cd5 100644 --- a/packages/types/src/Call.ts +++ b/packages/types/src/Method.ts @@ -8,21 +8,21 @@ import u8aConcat from '@polkadot/util/u8a/concat'; import createType from './codec/createType'; import Base from './codec/Base'; -import CallIndex from './CallIndex'; +import MethodIndex from './MethodIndex'; import { FunctionMetadata } from './Metadata'; /** * Extrinsic function descriptor, as defined in * {@link https://github.com/paritytech/wiki/blob/master/Extrinsic.md#the-extrinsic-format-for-node}. */ -export default class Call extends CallIndex { +export default class Method extends MethodIndex { protected _args: Array; protected _meta: FunctionMetadata; - constructor (index: Call | AnyU8a, meta: FunctionMetadata, args: Array) { + constructor (index: Method | AnyU8a, meta: FunctionMetadata, args: Array) { super(index); - if (index instanceof Call) { + if (index instanceof Method) { this._args = args || index.args; this._meta = meta || index.meta; } else { @@ -44,13 +44,16 @@ export default class Call extends CallIndex { } toU8a (isBare?: boolean): Uint8Array { - const args = this._meta.arguments - .filter((arg) => - arg.type.toString() !== 'Origin' - ) - .map((argument, index) => - createType(argument.type, this._args[index]).toU8a(isBare) - ); + // FIXME Even when decoded, we will need access to the meta + const args = this.meta + ? this.meta.arguments + .filter((arg) => + arg.type.toString() !== 'Origin' + ) + .map((argument, index) => + createType(argument.type, this.args[index]).toU8a(isBare) + ) + : []; return u8aConcat( super.toU8a(isBare), diff --git a/packages/types/src/CallIndex.spec.js b/packages/types/src/MethodIndex.spec.js similarity index 74% rename from packages/types/src/CallIndex.spec.js rename to packages/types/src/MethodIndex.spec.js index 53e423a55e..7e997237f2 100644 --- a/packages/types/src/CallIndex.spec.js +++ b/packages/types/src/MethodIndex.spec.js @@ -2,17 +2,17 @@ // This software may be modified and distributed under the terms // of the ISC license. See the LICENSE file for details. -import CallIndex from './CallIndex'; +import MethodIndex from './MethodIndex'; -describe('CallIndex', () => { +describe('MethodIndex', () => { it('handles u8a encoding correctly', () => { expect( - new CallIndex([1, 2]).toU8a() + new MethodIndex([1, 2]).toU8a() ).toEqual(new Uint8Array([1, 2])); }); it('provides access to section/method indexes', () => { - const ci = new CallIndex([1, 2]); + const ci = new MethodIndex([1, 2]); expect(ci.methodIndex).toEqual(2); expect(ci.sectionIndex).toEqual(1); diff --git a/packages/types/src/CallIndex.ts b/packages/types/src/MethodIndex.ts similarity index 90% rename from packages/types/src/CallIndex.ts rename to packages/types/src/MethodIndex.ts index 9cb9f3cdc7..2242e6a668 100644 --- a/packages/types/src/CallIndex.ts +++ b/packages/types/src/MethodIndex.ts @@ -6,7 +6,7 @@ import { AnyU8a } from './types'; import U8aFixed from './codec/U8aFixed'; -export default class CallIndex extends U8aFixed { +export default class MethodIndex extends U8aFixed { constructor (value?: AnyU8a) { super(value, 16); } diff --git a/packages/types/src/SignaturePayload.ts b/packages/types/src/SignaturePayload.ts index b0fd90c146..8ed8fa47d1 100644 --- a/packages/types/src/SignaturePayload.ts +++ b/packages/types/src/SignaturePayload.ts @@ -6,15 +6,15 @@ import { KeyringPair } from '@polkadot/util-keyring/types'; import { AnyNumber, AnyU8a } from './types'; import Struct from './codec/Struct'; -import Call from './Call'; +import Method from './Method'; import Hash from './Hash'; import Nonce from './Nonce'; -import TransactionEra from './TransactionEra'; +import ExtrinsicEra from './ExtrinsicEra'; type SignaturePayloadValue = { nonce?: AnyNumber, - call?: Call, - era?: AnyU8a | TransactionEra + method?: Method, + era?: AnyU8a | ExtrinsicEra blockHash?: AnyU8a }; @@ -29,8 +29,8 @@ export default class SignaturePayload extends Struct { constructor (value?: SignaturePayloadValue) { super({ nonce: Nonce, - call: Call, - era: TransactionEra, + method: Method, + era: ExtrinsicEra, blockHash: Hash }, value); } @@ -43,12 +43,12 @@ export default class SignaturePayload extends Struct { return this.raw.blockHash as Hash; } - get call (): Call { - return this.raw.call as Call; + get method (): Method { + return this.raw.method as Method; } - get era (): TransactionEra { - return this.raw.era as TransactionEra; + get era (): ExtrinsicEra { + return this.raw.era as ExtrinsicEra; } get nonce (): Nonce { diff --git a/packages/types/src/SignedBlock.rpc.json b/packages/types/src/SignedBlock.rpc.json index ea5e44d6b9..e02bab9efd 100644 --- a/packages/types/src/SignedBlock.rpc.json +++ b/packages/types/src/SignedBlock.rpc.json @@ -1 +1 @@ -{"jsonrpc":"2.0","result":{"block":{"extrinsics":[[255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,64,95,171,91,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]],"header":{"digest":{"logs":[]},"extrinsicsRoot":"0x233cf65d6f67f628b694c7da2d08020a937bc272560df7dd5cc1f11a7f85dc69","number":1565249,"parentHash":"0x0b0f28f64fdef451b6e2636ef18e9670183e1e4841db5a32ce476186611f6baf","stateRoot":"0xc372e08fa6edddd0ee415742eb551b8475100a40fe47a3d6470ad46b9b7b460d"}},"justification":{"hash":"0x737f58ac7f964353c56160187821ef4d2295d196c8479c21c7ae37f708550b57","round_number":1,"signatures":[["0x65d2273adeb04478658e183dc5edf41f1d86e42255442af62e72dbf1e6c0b977","0x6bfe453137983a7ef474cf3108e7cc0260621fac893e92c41d17952430164a1ee1600fd3f8c9d2d8440d391ac1f1a488ac6fd0185fa0ba722698903753c8bb0c"],["0x8c25a8812190a86c0c086b1c4087e31d82e3375652f9a75e828a4301c98245be","0x9e0ecfe993846758fb15920a7103a5cb4199e03481eec1ebf7abb43cb35e9703baf04b606000c788244ccde5d6fb0b22fc940099ced61e8a404d71787757980b"],["0xbb8943a83c953cc96f927ca2e7062e4819f0b258107e495fb40a78d27c2e1ad7","0xa282bc57b27feccc752f194dfe6e2281986a46bac31d06b629c9b62401804ad00a400a67d3770b7470d207d349f167eda72436d6eae7b90469a61eefe1c99800"],["0xea1a15140e562d9f582b38d64d8d1f575b9f837556fdec40fcc3e564259471c7","0x45926cb65bb59595f447eaac5e782029f7fabd47579fe4fec7b79c1c554abf1c31067a500362c2d84aadca3686bfc455d780d2c3265674154d33ea0349db2307"],["0x432d983331d08c86121cd2c86456cf3eeeb5a2f37bab7f2969453b51b4eed783","0x3a09b440194aa714606a2a223422b7795f7d1ac75dca4b6bc5f5031d51b4e282b264d231ca73ee234a814ea5f60e135e7df6dfa02b363ca1204dfe56c2a4ad03"],["0x2e5baf22ac662c0a3883ccf3e17580e6c41f056642040ddc16a877176becdc53","0x02a5605a3f28f7ed9063a4f465601af8625a7fbb69b4757b9838a90ed3e5e1598671853ee106512a833ab1eb7db48f7915b7b48d0b5c2915898d05f54ce23205"],["0x10b9ddcb0d59f795ab64608bd22215b55868ee01efe6d690b8988c63859a6b27","0x04a3e8d9b12163b8c3488968d447bf8b4968bbce55c09ee18ba57f5b9e10dd8f3ae344551d9014e8a1efb0e7e6e83d7cedf440a1d512266a83d4d25d8759ee06"],["0x044b0abaa1854772c75282aa9187935a56926e9c5f5e0b30cf6993c530c09d26","0x3844d377dc958c96eefbb56c777439142af43aebb764c230b74c3f56a4df3207abf4a347d8fe88e5d2641e82c48522079000c02fd89748705d9efb843128e40d"],["0x1689d1d5c9c5b072034ed95aa1ee22c2dd60df78d82de93dc0e3872bfa4c715a","0x481613e2c0b16ae14adc2e463bda352ebb5a839836c4e384bb4770608cdb38ad02b5ca571d19853f6e706ebf880edf12dc5d448d8d331ea2b8926b03aa9bcd0c"],["0x22fdc8c92de49cd1a11f03f591e507b0827e1e19df35b3b0a2a90ee35df4b06c","0xac7802d1e824c656b3e094cf18d1ff4758d2d8df0874a0be123893a0d8c95ddbe9cf40a765b6cfeecb7756b9f18294f9dca35451499c8a7a99d7621d9cd5610b"],["0xcb7cc7b2f624c92c6fad8ee77458a35c7acaade2b03e5f0634509cef1db7ce09","0x5fc45de00c1291ea605c6929ebe77bd5d2d998c7ad44d1f88bce4b86ecefbd447adbbf0290ea12b2b8a34db2c71f266ddccb54f2074340825edd8f7b0b235503"],["0x5d87486121bcfdfbb7b6d8cbd91558059f798587e194c36efb8b379bb8b3dd8e","0x47f046ecb4aca2ba36994b7e11565306a382615f589d26e827de357623c22d271e0998c4617fa8be3902acdf33cb72538839ca731d4476a0f2b41a4c8297000d"],["0xd164f617a7b5144504166c305f9940fb17cd1656e46ba55f344ee4e5f716c12f","0x663502ec1e40325992d2b7307764f6bd524d30968acf2bd3b0a6d43c5f973eebd192a796a455127d6750f407d14650201b225dc107361c2d634e46c3e0c9340e"],["0x3005b5aab73dc485beecf1df7732876a61c81c8f13d7a4883f1243ecbb9497dd","0x4fdcbb79bd4f852ede225e9e90e5bc6c8b9c8760ac016c4f081f1dfc93ef055b8bbd545b459dd82ef107b20013fae2da55fc31784d933a29261d55466628cd01"],["0xfbf09129e1ca12face363366917add306357e8f6221e57edbfa4e820784cf712","0xc620ff8b940e9be7eaf0f5c8d034c8fec33d1fafc2ea5921660486eff5087027e44bb1b38641894aadb055b9bdece9e480f6042ad801a07588bf19f4ba87cb0e"]]}},"id":8} +{"jsonrpc":"2.0","result":{"block":{"extrinsics":["0x010200dd2bb75b00000000"],"header":{"digest":{"logs":[]},"extrinsicsRoot":"0x06811f569c9b822d10c659695ec4b1f6391472b3a65ecc78131485bc3fafe780","number":2769,"parentHash":"0x89c31b0f09782a2c27c0be0c7e2f096b13ce6541a5d14cc43a9553e50a89314a","stateRoot":"0x6e4e88dc766d13c8975e7806e30cc1627e9553a2ebe59ab123f985d1c925c5ff"}},"justification":{"hash":"0x7ac267bb86a5b674582fba9e84d3e3e9988621124c3e33358f7771224d176795","round_number":0,"signatures":[["0xd172a74cda4c865912c32ba0a80a57ae69abae410e5ccb59dee84e2f4432db4f","0xf9aa2cd44ee75a40ec230b589f847e1cf1a921f4a85e9825f9cd3892d29eeda628c7bc44b9f55ec305c1ae745d6b96e163338bbd9ae262c60626a50405868701"]]}},"id":16} diff --git a/packages/types/src/SignedBlock.spec.js b/packages/types/src/SignedBlock.spec.js index 85435ae08c..01d1bb7565 100644 --- a/packages/types/src/SignedBlock.spec.js +++ b/packages/types/src/SignedBlock.spec.js @@ -11,12 +11,12 @@ describe('SignedBlock', () => { it('has the correct stateRoot', () => { expect( block.block.header.stateRoot.toString() - ).toEqual('0xc372e08fa6edddd0ee415742eb551b8475100a40fe47a3d6470ad46b9b7b460d'); + ).toEqual('0x6e4e88dc766d13c8975e7806e30cc1627e9553a2ebe59ab123f985d1c925c5ff'); }); it('has the justification', () => { expect( block.justification.hash.toHex() - ).toEqual('0x737f58ac7f964353c56160187821ef4d2295d196c8479c21c7ae37f708550b57'); + ).toEqual('0x7ac267bb86a5b674582fba9e84d3e3e9988621124c3e33358f7771224d176795'); }); }); diff --git a/packages/types/src/TransactionSignature.ts b/packages/types/src/TransactionSignature.ts deleted file mode 100644 index b593de9ac4..0000000000 --- a/packages/types/src/TransactionSignature.ts +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2017-2018 @polkadot/types authors & contributors -// This software may be modified and distributed under the terms -// of the ISC license. See the LICENSE file for details. - -import { AnyNumber, AnyU8a } from './types'; - -import Struct from './codec/Struct'; -import Address from './Address'; -import TransactionEra from './TransactionEra'; -import Nonce from './Nonce'; -import Signature from './Signature'; - -type TransactionSignatureValue = { - signer?: AnyU8a | Address, - signature?: AnyU8a - nonce?: AnyNumber, - era?: AnyU8a -}; - -// Signature Information. -// 1/3/5/9/33 bytes: The signing account identity, in Address format -// 64 bytes: The Ed25519 signature of the Signing Payload -// 8 bytes: The Transaction Index of the signing account -// 2 bytes: The Transaction Era -export default class TransactionSignature extends Struct { - constructor (value?: TransactionSignatureValue) { - super({ - signer: Address, - signature: Signature, - nonce: Nonce, - era: TransactionEra - }, value); - } - - get era (): TransactionEra { - return this.raw.era as TransactionEra; - } - - get nonce (): Nonce { - return this.raw.nonce as Nonce; - } - - get signature (): Signature { - return this.raw.signature as Signature; - } - - get signer (): Address { - return this.raw.signer as Address; - } -} diff --git a/packages/types/src/UncheckedMortalExtrinsic.ts b/packages/types/src/UncheckedMortalExtrinsic.ts deleted file mode 100644 index 040347e014..0000000000 --- a/packages/types/src/UncheckedMortalExtrinsic.ts +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2017-2018 @polkadot/extrinsics authors & contributors -// This software may be modified and distributed under the terms -// of the ISC license. See the LICENSE file for details. - -import { KeyringPair } from '@polkadot/util-keyring/types'; -import { AnyNumber, AnyU8a } from './types'; - -import u8aConcat from '@polkadot/util/u8a/concat'; - -import Address from './Address'; -import Call from './Call'; -import Extrinsic from './Extrinsic'; -import { FunctionMetadata } from './Metadata'; -import SignaturePayload from './SignaturePayload'; -import TransactionSignature from './TransactionSignature'; - -const EMPTY_U8A = new Uint8Array(); -const IMMORTAL_ERA = new Uint8Array([0]); - -/** - * Unchecked mortal extrinsic, as defined here: - * {@link https://github.com/paritytech/wiki/blob/master/Extrinsic.md#the-extrinsic-format-for-node}. - * Can be: - * - signed, to create a transaction - * - left as is, to create an inherent - */ -export default class UncheckedMortalExtrinsic extends Extrinsic { - protected _call: Call; - protected _signature?: Uint8Array; - - constructor (call: Call) { - super(); - - this._call = call; - this.raw = UncheckedMortalExtrinsic.encode(call); - } - - static encode (call: Call, signature?: TransactionSignature): Uint8Array { - // Version Information. - // 1 byte: version information: - // - 7 low bits: version identifier (should be 0b0000001). - // - 1 high bit: signed flag: 1 if this is a transaction (e.g. contains a signature). - const highBit = signature ? 0b10000000 : 0; - const version = 0b00000001; - - return u8aConcat( - new Uint8Array([highBit | version]), - signature - ? signature.toU8a() - : EMPTY_U8A, - call.toU8a() - ); - } - - get isSigned () { - return this._signature; - } - - get meta (): FunctionMetadata { - return this._call.meta; - } - - get callIndex (): Uint8Array { - return this._call.callIndex; - } - - get methodIndex (): number { - return this._call.methodIndex; - } - - get sectionIndex (): number { - return this._call.sectionIndex; - } - - sign (signerPair: KeyringPair, nonce: AnyNumber, blockHash: AnyU8a): UncheckedMortalExtrinsic { - const signature = this.createSignature(this._call, signerPair, nonce, blockHash); - - this._signature = signature.toU8a(); - this.raw = UncheckedMortalExtrinsic.encode(this._call, signature); - - return this; - } - - private createSignature (call: Call, signerPair: KeyringPair, nonce: AnyNumber, blockHash: AnyU8a, era: Uint8Array = IMMORTAL_ERA): TransactionSignature { - const signer = new Address(signerPair.publicKey()); - - const signingPayload = new SignaturePayload({ - nonce, - call, - era, - blockHash - }); - const signature = signingPayload.sign(signerPair); - - return new TransactionSignature({ - era: signingPayload.era, - nonce: signingPayload.nonce, - signer, - signature - }); - } -} diff --git a/packages/types/src/codec/Struct.ts b/packages/types/src/codec/Struct.ts index ef19bccb86..d2d2a76dbb 100644 --- a/packages/types/src/codec/Struct.ts +++ b/packages/types/src/codec/Struct.ts @@ -2,11 +2,12 @@ // This software may be modified and distributed under the terms // of the ISC license. See the LICENSE file for details. -import hexToU8a from '@polkadot/util/hex/toU8a'; import isHex from '@polkadot/util/is/hex'; import u8aConcat from '@polkadot/util/u8a/concat'; +import u8aToU8a from '@polkadot/util/u8a/toU8a'; import Base from './Base'; +import isU8a from '@polkadot/util/is/u8a'; // A Struct defines an Object with key/values - where the values are Base values. It removes // a lot of repetition from the actual coding, define a structure type, pass it the key/Base @@ -84,8 +85,8 @@ export default class Struct < } fromJSON (input: any): Struct { - if (isHex(input)) { - return this.fromU8a(hexToU8a(input)); + if (isHex(input) || isU8a(input)) { + return this.fromU8a(u8aToU8a(input)); } Object.keys(this.raw).forEach((key) => { diff --git a/packages/types/src/codec/createType.ts b/packages/types/src/codec/createType.ts index f169a2ad1a..4121131efe 100644 --- a/packages/types/src/codec/createType.ts +++ b/packages/types/src/codec/createType.ts @@ -4,7 +4,6 @@ import assert from '@polkadot/util/assert'; -import * as Types from '../index'; import Text from '../Text'; import Base from './Base'; import Tuple from './Tuple'; @@ -129,7 +128,9 @@ export function getTypeClass (value: TypeDef): Constructor { ); } - const Type = (Types as any)[value.type]; + // We are dynamically loading as to avoid circular dependencies + const Types = require('../index'); + const Type = Types[value.type]; assert(Type, `Unable to determine type from '${value.type}'`); diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 8c5c715755..781c20e4d8 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -18,9 +18,9 @@ export { default as Block } from './Block'; export { default as BlockNumber } from './BlockNumber'; export { default as Bool } from './Bool'; export { default as Bytes } from './Bytes'; -export { default as Call } from './Call'; -export { default as CallIndex } from './CallIndex'; export { default as Extrinsic } from './Extrinsic'; +export { default as ExtrinsicEra } from './ExtrinsicEra'; +export { default as ExtrinsicSignature } from './ExtrinsicSignature'; // NOTE Only used internally, exported as PendingExtrinsics // export { default as Extrinsics } from './Extrinsics'; export { default as Gas } from './Gas'; @@ -31,6 +31,8 @@ export { default as Hash } from './Hash'; export { default as Header } from './Header'; export { default as KeyValue } from './KeyValue'; export { default as Metadata } from './Metadata'; +export { default as Method } from './Method'; +export { default as MethodIndex } from './MethodIndex'; export { default as MisbehaviorReport } from './MisbehaviorReport'; export { default as Moment } from './Moment'; export { default as NewAccountOutcome } from './NewAccountOutcome'; @@ -52,8 +54,6 @@ export { default as StorageChangeSet } from './StorageChangeSet'; export { default as StorageData } from './StorageData'; export { default as StorageKey } from './StorageKey'; export { default as Text } from './Text'; -export { default as TransactionEra } from './TransactionEra'; -export { default as TransactionSignature } from './TransactionSignature'; // NOTE Type is currently only used internally (possibly in codec-related work) // export { default as Type } from './Type'; // NOTE We are exporting the U* classes as lowercase, matching with Rust @@ -63,7 +63,6 @@ export { default as u32 } from './U32'; export { default as u64 } from './U64'; export { default as u128 } from './U128'; export { default as u256 } from './U256'; -export { default as UncheckedMortalExtrinsic } from './UncheckedMortalExtrinsic'; export { default as ValidatorPrefs } from './ValidatorPrefs'; export { default as VoteThreshold } from './VoteThreshold'; export { default as VoteIndex } from './VoteIndex';