Bump common (#2832)

* Bump common

* Update for new common non-default exports

* Don't export createSubmittable

* Adjust exports

* default export adjustments

* Some additional non-default exports
This commit is contained in:
Jaco Greeff
2020-11-09 19:41:29 +01:00
committed by GitHub
parent e787c08bd9
commit 21d0622f84
116 changed files with 1245 additions and 1270 deletions
+1 -1
View File
@@ -31,7 +31,7 @@
"@babel/runtime": "^7.12.1",
"@polkadot/api": "2.6.2-0",
"@polkadot/types": "2.6.2-0",
"@polkadot/util": "^4.0.1",
"@polkadot/util": "^4.0.2-5",
"bn.js": "^5.1.3",
"rxjs": "^6.6.3"
}
+1 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import Abi from './Abi';
import { Abi } from '.';
import * as testContracts from '../test/contracts';
+2 -2
View File
@@ -7,7 +7,7 @@ import { AbiConstructor, AbiEvent, AbiMessage, AbiParam, DecodedEvent, DecodedMe
import { assert, assertReturn, compactAddLength, compactStripLength, isNumber, isObject, isString, logger, stringCamelCase, u8aConcat, u8aToHex } from '@polkadot/util';
import MetaRegistry from './MetaRegistry';
import { MetaRegistry } from './MetaRegistry';
const l = logger('Abi');
@@ -21,7 +21,7 @@ function findMessage <T extends AbiMessage> (list: T[], messageOrId: T | string
return assertReturn(message, `Attempted to call an invalid contract interface, ${JSON.stringify(messageOrId)}`);
}
export default class Abi {
export class Abi {
readonly #events: AbiEvent[];
public readonly constructors: AbiConstructor[];
@@ -4,7 +4,7 @@
import fs from 'fs';
import path from 'path';
import Abi from './Abi';
import { Abi } from '.';
import * as testContracts from '../test/contracts';
+1 -1
View File
@@ -24,7 +24,7 @@ const PRIMITIVE_ALIAS: Record<string, keyof InterfaceTypes> = {
const PRIMITIVE_ALWAYS = ['AccountId', 'AccountIndex', 'Address', 'Balance'];
export default class MetaRegistry extends TypeRegistry {
export class MetaRegistry extends TypeRegistry {
public readonly metaTypeDefs: TypeDef[] = [];
#siTypes: SiType[] = [];
+2 -2
View File
@@ -7,9 +7,9 @@ import { AnyJson, Registry } from '@polkadot/types/types';
import ApiBase from '@polkadot/api/base';
import { assert } from '@polkadot/util';
import Abi from '../Abi';
import { Abi } from '../Abi';
export default abstract class Base<ApiType extends ApiTypes> {
export abstract class Base<ApiType extends ApiTypes> {
public readonly abi: Abi;
public readonly api: ApiBase<ApiType>;
+4 -4
View File
@@ -13,10 +13,10 @@ import { SubmittableResult } from '@polkadot/api';
import ApiBase from '@polkadot/api/base';
import { isUndefined, stringCamelCase } from '@polkadot/util';
import Abi from '../Abi';
import { Abi } from '../Abi';
import { applyOnEvent } from '../util';
import Base from './Base';
import Contract from './Contract';
import { Base } from './Base';
import { Contract } from './Contract';
export class BlueprintSubmittableResult<ApiType extends ApiTypes> extends SubmittableResult {
public readonly contract?: Contract<ApiType>;
@@ -28,7 +28,7 @@ export class BlueprintSubmittableResult<ApiType extends ApiTypes> extends Submit
}
}
export default class Blueprint<ApiType extends ApiTypes> extends Base<ApiType> {
export class Blueprint<ApiType extends ApiTypes> extends Base<ApiType> {
public readonly codeHash: Hash;
readonly #tx: MapConstructorExec<ApiType> = {};
+4 -4
View File
@@ -10,10 +10,10 @@ import { SubmittableResult } from '@polkadot/api';
import ApiBase from '@polkadot/api/base';
import { compactAddLength, u8aToU8a } from '@polkadot/util';
import Abi from '../Abi';
import { Abi } from '../Abi';
import { applyOnEvent } from '../util';
import Base from './Base';
import Blueprint from './Blueprint';
import { Base } from './Base';
import { Blueprint } from './Blueprint';
export class CodeSubmittableResult<ApiType extends ApiTypes> extends SubmittableResult {
public readonly blueprint?: Blueprint<ApiType>;
@@ -25,7 +25,7 @@ export class CodeSubmittableResult<ApiType extends ApiTypes> extends Submittable
}
}
export default class Code<ApiType extends ApiTypes> extends Base<ApiType> {
export class Code<ApiType extends ApiTypes> extends Base<ApiType> {
public readonly code: Uint8Array;
constructor (api: ApiBase<ApiType>, abi: AnyJson | Abi, wasm: Uint8Array | string | Buffer, decorateMethod: DecorateMethod<ApiType>) {
+3 -3
View File
@@ -14,9 +14,9 @@ import { SubmittableResult } from '@polkadot/api';
import ApiBase from '@polkadot/api/base';
import { assert, bnToBn, isFunction, isUndefined, logger, stringCamelCase } from '@polkadot/util';
import Abi from '../Abi';
import { Abi } from '../Abi';
import { applyOnEvent, formatData } from '../util';
import Base from './Base';
import { Base } from './Base';
// As per Rust, 5 * GAS_PER_SEC
const MAX_CALL_GAS = new BN(5_000_000_000_000).subn(1);
@@ -60,7 +60,7 @@ function mapExecResult (registry: Registry, json: Record<string, AnyJson>): Cont
return registry.createType('ContractExecResult', { result: { err: { other: 'unknown' } } });
}
export default class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
export class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
public readonly address: AccountId;
readonly #tx: MapMessageExec<ApiType> = {};
+3 -3
View File
@@ -1,6 +1,6 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as Blueprint, BlueprintSubmittableResult } from './Blueprint';
export { default as Code, CodeSubmittableResult } from './Code';
export { default as Contract } from './Contract';
export { Blueprint, BlueprintSubmittableResult } from './Blueprint';
export { Code, CodeSubmittableResult } from './Code';
export { Contract } from './Contract';
+1 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as Abi } from './Abi';
export { Abi } from './Abi';
export { Blueprint as BlueprintRx, Code as CodeRx, Contract as ContractRx } from './rx';
export { Blueprint as BlueprintPromise, Code as CodePromise, Contract as ContractPromise } from './promise';
@@ -7,10 +7,10 @@ import { AnyJson } from '@polkadot/types/types';
import { ApiPromise } from '@polkadot/api';
import { decorateMethod } from '@polkadot/api/promise';
import Abi from '../Abi';
import BaseBlueprint from '../base/Blueprint';
import { Abi } from '../Abi';
import { Blueprint as BaseBlueprint } from '../base';
export default class Blueprint extends BaseBlueprint<'promise'> {
export class Blueprint extends BaseBlueprint<'promise'> {
constructor (api: ApiPromise, abi: AnyJson | Abi, codeHash: string | Hash) {
super(api, abi, codeHash, decorateMethod);
}
+3 -3
View File
@@ -5,10 +5,10 @@ import { ApiPromise } from '@polkadot/api';
import { decorateMethod } from '@polkadot/api/promise';
import { AnyJson } from '@polkadot/types/types';
import Abi from '../Abi';
import BaseCode from '../base/Code';
import { Abi } from '../Abi';
import { Code as BaseCode } from '../base';
export default class Code extends BaseCode<'promise'> {
export class Code extends BaseCode<'promise'> {
constructor (api: ApiPromise, abi: AnyJson | Abi, wasm: Uint8Array | string | Buffer) {
super(api, abi, wasm, decorateMethod);
}
@@ -7,10 +7,10 @@ import { AnyJson } from '@polkadot/types/types';
import { ApiPromise } from '@polkadot/api';
import { decorateMethod } from '@polkadot/api/promise';
import Abi from '../Abi';
import BaseContract from '../base/Contract';
import { Abi } from '../Abi';
import { Contract as BaseContract } from '../base';
export default class Contract extends BaseContract<'promise'> {
export class Contract extends BaseContract<'promise'> {
constructor (api: ApiPromise, abi: AnyJson | Abi, address: string | AccountId) {
super(api, abi, address, decorateMethod);
}
+3 -3
View File
@@ -1,6 +1,6 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as Blueprint } from './Blueprint';
export { default as Code } from './Code';
export { default as Contract } from './Contract';
export { Blueprint } from './Blueprint';
export { Code } from './Code';
export { Contract } from './Contract';
+3 -3
View File
@@ -7,10 +7,10 @@ import { AnyJson } from '@polkadot/types/types';
import { ApiRx } from '@polkadot/api';
import { decorateMethod } from '@polkadot/api/rx';
import Abi from '../Abi';
import BaseBlueprint from '../base/Blueprint';
import { Abi } from '../Abi';
import { Blueprint as BaseBlueprint } from '../base';
export default class Blueprint extends BaseBlueprint<'rxjs'> {
export class Blueprint extends BaseBlueprint<'rxjs'> {
constructor (api: ApiRx, abi: AnyJson | Abi, codeHash: string | Hash) {
super(api, abi, codeHash, decorateMethod);
}
+3 -3
View File
@@ -6,10 +6,10 @@ import { AnyJson } from '@polkadot/types/types';
import { ApiRx } from '@polkadot/api';
import { decorateMethod } from '@polkadot/api/rx';
import Abi from '../Abi';
import BaseCode from '../base/Code';
import { Abi } from '../Abi';
import { Code as BaseCode } from '../base';
export default class Code extends BaseCode<'rxjs'> {
export class Code extends BaseCode<'rxjs'> {
constructor (api: ApiRx, abi: AnyJson | Abi, wasm: Uint8Array | string | Buffer) {
super(api, abi, wasm, decorateMethod);
}
+3 -3
View File
@@ -7,10 +7,10 @@ import { AnyJson } from '@polkadot/types/types';
import { ApiRx } from '@polkadot/api';
import { decorateMethod } from '@polkadot/api/rx';
import Abi from '../Abi';
import BaseContract from '../base/Contract';
import { Abi } from '../Abi';
import { Contract as BaseContract } from '../base';
export default class Contract extends BaseContract<'rxjs'> {
export class Contract extends BaseContract<'rxjs'> {
constructor (api: ApiRx, abi: AnyJson | Abi, address: string | AccountId) {
super(api, abi, address, decorateMethod);
}
+3 -3
View File
@@ -1,6 +1,6 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as Blueprint } from './Blueprint';
export { default as Code } from './Code';
export { default as Contract } from './Contract';
export { Blueprint } from './Blueprint';
export { Code } from './Code';
export { Contract } from './Contract';
+1 -1
View File
@@ -8,7 +8,7 @@ import { Codec, CodecArg, TypeDef } from '@polkadot/types/types';
import ApiBase from '@polkadot/api/base';
import { Text, u64 } from '@polkadot/types';
import Abi from './Abi';
import { Abi } from '.';
export interface ContractBase<ApiType extends ApiTypes> {
readonly abi: Abi;
+3 -3
View File
@@ -33,14 +33,14 @@
"@polkadot/api": "2.6.2-0",
"@polkadot/rpc-core": "2.6.2-0",
"@polkadot/types": "2.6.2-0",
"@polkadot/util": "^4.0.1",
"@polkadot/util-crypto": "^4.0.1",
"@polkadot/util": "^4.0.2-5",
"@polkadot/util-crypto": "^4.0.2-5",
"bn.js": "^5.1.3",
"memoizee": "^0.4.14",
"rxjs": "^6.6.3"
},
"devDependencies": {
"@polkadot/keyring": "^4.0.1",
"@polkadot/keyring": "^4.0.2-5",
"@polkadot/rpc-provider": "2.6.2-0"
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import { Observable, from } from 'rxjs';
import ApiRx from '@polkadot/api/rx/Api';
import { ApiRx } from '@polkadot/api/rx';
import MockProvider from '@polkadot/rpc-provider/mock';
import { TypeRegistry } from '@polkadot/types';
+1 -1
View File
@@ -92,7 +92,7 @@ function injectFunctions<AllSections> (instanceId: string, api: ApiInterfaceRx,
// FIXME The return type of this function should be {...ExactDerive, ...DeriveCustom}
// For now we just drop the custom derive typings
/** @internal */
export default function decorateDerive (instanceId: string, api: ApiInterfaceRx, custom: DeriveCustom = {}): ExactDerive {
export function decorateDerive (instanceId: string, api: ApiInterfaceRx, custom: DeriveCustom = {}): ExactDerive {
return {
...injectFunctions(instanceId, api, derive),
...injectFunctions(instanceId, api, custom)
+3 -3
View File
@@ -30,14 +30,14 @@
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/api-derive": "2.6.2-0",
"@polkadot/keyring": "^4.0.1",
"@polkadot/keyring": "^4.0.2-5",
"@polkadot/metadata": "2.6.2-0",
"@polkadot/rpc-core": "2.6.2-0",
"@polkadot/rpc-provider": "2.6.2-0",
"@polkadot/types": "2.6.2-0",
"@polkadot/types-known": "2.6.2-0",
"@polkadot/util": "^4.0.1",
"@polkadot/util-crypto": "^4.0.1",
"@polkadot/util": "^4.0.2-5",
"@polkadot/util-crypto": "^4.0.2-5",
"bn.js": "^5.1.3",
"eventemitter3": "^4.0.7",
"rxjs": "^6.6.3"
+4 -4
View File
@@ -11,12 +11,12 @@ import { ApiInterfaceRx, ApiOptions, ApiTypes, DecorateMethod, DecoratedRpc, Dec
import BN from 'bn.js';
import { BehaviorSubject, Observable, combineLatest, of } from 'rxjs';
import { map, switchMap, take, tap, toArray } from 'rxjs/operators';
import decorateDerive, { ExactDerive } from '@polkadot/api-derive';
import { ExactDerive, decorateDerive } from '@polkadot/api-derive';
import { memo } from '@polkadot/api-derive/util';
import { expandMetadata } from '@polkadot/metadata';
import RpcCore from '@polkadot/rpc-core';
import { Metadata, expandMetadata } from '@polkadot/metadata';
import { RpcCore } from '@polkadot/rpc-core';
import { WsProvider } from '@polkadot/rpc-provider';
import { Metadata, Option, Raw, Text, TypeRegistry, u64 } from '@polkadot/types';
import { Option, Raw, Text, TypeRegistry, u64 } from '@polkadot/types';
import { DEFAULT_VERSION as EXTRINSIC_DEFAULT_VERSION } from '@polkadot/types/extrinsic/constants';
import StorageKey, { StorageEntry, unwrapStorageType } from '@polkadot/types/primitive/StorageKey';
import { assert, compactStripLength, logger, u8aToHex } from '@polkadot/util';
+2 -2
View File
@@ -8,7 +8,7 @@ import { IExtrinsic, IMethod } from '@polkadot/types/types';
import { ApiPromise } from '@polkadot/api';
import { HeaderExtended } from '@polkadot/api-derive';
import testKeyring, { TestKeyringMap } from '@polkadot/keyring/testingPairs';
import { TestKeyringMap, createTestPairs } from '@polkadot/keyring/testingPairs';
import { createTypeUnsafe, TypeRegistry } from '@polkadot/types';
import { SubmittableResult } from './';
@@ -183,7 +183,7 @@ async function tx (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
async function main (): Promise<void> {
const api = await ApiPromise.create();
const keyring = testKeyring();
const keyring = createTestPairs();
// eslint-disable-next-line @typescript-eslint/no-floating-promises
Promise.all([
+5 -4
View File
@@ -8,8 +8,9 @@ import { detectPackage } from '@polkadot/util';
detectPackage(require('./package.json'), typeof __dirname !== 'undefined' && __dirname);
export { Keyring } from '@polkadot/keyring';
export { default as WsProvider } from '@polkadot/rpc-provider/ws';
export { WsProvider } from '@polkadot/rpc-provider/ws';
export { default as ApiPromise } from './promise';
export { default as ApiRx } from './rx';
export * from './submittable';
export { ApiPromise } from './promise';
export { ApiRx } from './rx';
export { SubmittableResult } from './submittable';
-304
View File
@@ -1,304 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Callback, Codec } from '@polkadot/types/types';
import { ApiOptions, DecorateFn, DecorateMethodOptions, ObsInnerType, StorageEntryPromiseOverloads, UnsubscribePromise, VoidFn } from '../types';
import { EMPTY, Observable, Subscription } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { isFunction, assert } from '@polkadot/util';
import ApiBase from '../base';
import Combinator, { CombinatorCallback, CombinatorFunction } from './Combinator';
interface Tracker<T> {
reject: (value: Error) => Observable<never>;
resolve: (value: T) => void;
}
// extract the arguments and callback params from a value array possibly containing a callback
function extractArgs (args: unknown[], needsCallback: boolean): [unknown[], Callback<Codec> | undefined] {
let callback: Callback<Codec> | undefined;
const actualArgs = args.slice();
// If the last arg is a function, we pop it, put it into callback.
// actualArgs will then hold the actual arguments to be passed to `method`
if (args.length && isFunction(args[args.length - 1])) {
callback = actualArgs.pop() as Callback<Codec>;
}
// When we need a subscription, ensure that a valid callback is actually passed
assert(!needsCallback || isFunction(callback), 'Expected a callback to be passed with subscriptions');
return [actualArgs, callback];
}
// a Promise completion tracker, wrapping an isComplete variable that ensures the promise only resolves once
function promiseTracker<T> (resolve: (value: T) => void, reject: (value: Error) => void): Tracker<T> {
let isCompleted = false;
return {
reject: (error: Error): Observable<never> => {
if (!isCompleted) {
isCompleted = true;
reject(error);
}
return EMPTY;
},
resolve: (value: T): void => {
if (!isCompleted) {
isCompleted = true;
resolve(value);
}
}
};
}
// Decorate a call for a single-shot result - retrieve and then immediate unsubscribe
function decorateCall<Method extends DecorateFn<ObsInnerType<ReturnType<Method>>>> (method: Method, actualArgs: unknown[]): Promise<ObsInnerType<ReturnType<Method>>> {
return new Promise((resolve, reject): void => {
// single result tracker - either reject with Error or resolve with Codec result
const tracker = promiseTracker(resolve, reject);
// encoding errors reject immediately, any result unsubscribes and resolves
const subscription: Subscription = method(...actualArgs).pipe(
catchError((error) => tracker.reject(error))
).subscribe((result): void => {
tracker.resolve(result);
setTimeout(() => subscription.unsubscribe(), 0);
});
});
}
// Decorate a subscription where we have a result callback specified
function decorateSubscribe<Method extends DecorateFn<ObsInnerType<ReturnType<Method>>>> (method: Method, actualArgs: unknown[], resultCb: Callback<Codec>): UnsubscribePromise {
return new Promise<VoidFn>((resolve, reject): void => {
// either reject with error or resolve with unsubscribe callback
const tracker = promiseTracker(resolve, reject);
// errors reject immediately, the first result resolves with an unsubscribe promise, all results via callback
const subscription: Subscription = method(...actualArgs).pipe(
catchError((error) => tracker.reject(error)),
tap(() => tracker.resolve(() => subscription.unsubscribe()))
).subscribe((result): void => {
// queue result (back of queue to clear current)
setTimeout(() => resultCb(result) as void, 0);
});
});
}
/**
* @description Decorate method for ApiPromise, where the results are converted to the Promise equivalent
*/
export function decorateMethod<Method extends DecorateFn<ObsInnerType<ReturnType<Method>>>> (method: Method, options?: DecorateMethodOptions): StorageEntryPromiseOverloads {
const needsCallback = options && options.methodName && options.methodName.includes('subscribe');
return function (...args: unknown[]): Promise<ObsInnerType<ReturnType<Method>>> | UnsubscribePromise {
const [actualArgs, resultCb] = extractArgs(args, !!needsCallback);
return resultCb
? decorateSubscribe(method, actualArgs, resultCb)
: decorateCall((options?.overrideNoSub as Method) || method, actualArgs);
} as StorageEntryPromiseOverloads;
}
/**
* # @polkadot/api/promise
*
* ## Overview
*
* @name ApiPromise
* @description
* ApiPromise is a standard JavaScript wrapper around the RPC and interfaces on the Polkadot network. As a full Promise-based, all interface calls return Promises, including the static `.create(...)`. Subscription calls utilise `(value) => {}` callbacks to pass through the latest values.
*
* The API is well suited to real-time applications where either the single-shot state is needed or use is to be made of the subscription-based features of Polkadot (and Substrate) clients.
*
* @see [[ApiRx]]
*
* ## Usage
*
* Making rpc calls -
* <BR>
*
* ```javascript
* import ApiPromise from '@polkadot/api/promise';
*
* // initialise via static create
* const api = await ApiPromise.create();
*
* // make a subscription to the network head
* api.rpc.chain.subscribeNewHeads((header) => {
* console.log(`Chain is at #${header.number}`);
* });
* ```
* <BR>
*
* Subscribing to chain state -
* <BR>
*
* ```javascript
* import { ApiPromise, WsProvider } from '@polkadot/api';
*
* // initialise a provider with a specific endpoint
* const provider = new WsProvider('wss://example.com:9944')
*
* // initialise via isReady & new with specific provider
* const api = await new ApiPromise({ provider }).isReady;
*
* // retrieve the block target time
* const blockPeriod = await api.query.timestamp.blockPeriod().toNumber();
* let last = 0;
*
* // subscribe to the current block timestamp, updates automatically (callback provided)
* api.query.timestamp.now((timestamp) => {
* const elapsed = last
* ? `, ${timestamp.toNumber() - last}s since last`
* : '';
*
* last = timestamp.toNumber();
* console.log(`timestamp ${timestamp}${elapsed} (${blockPeriod}s target)`);
* });
* ```
* <BR>
*
* Submitting a transaction -
* <BR>
*
* ```javascript
* import ApiPromise from '@polkadot/api/promise';
*
* ApiPromise.create().then((api) => {
* const [nonce] = await api.query.system.account(keyring.alice.address);
*
* api.tx.balances
* // create transfer
* transfer(keyring.bob.address, 12345)
* // sign the transcation
* .sign(keyring.alice, { nonce })
* // send the transaction (optional status callback)
* .send((status) => {
* console.log(`current status ${status.type}`);
* })
* // retrieve the submitted extrinsic hash
* .then((hash) => {
* console.log(`submitted with hash ${hash}`);
* });
* });
* ```
*/
export default class ApiPromise extends ApiBase<'promise'> {
#isReadyPromise: Promise<ApiPromise>;
#isReadyOrErrorPromise: Promise<ApiPromise>;
/**
* @description Creates an ApiPromise instance using the supplied provider. Returns an Promise containing the actual Api instance.
* @param options options that is passed to the class contructor. Can be either [[ApiOptions]] or a
* provider (see the constructor arguments)
* @example
* <BR>
*
* ```javascript
* import Api from '@polkadot/api/promise';
*
* Api.create().then(async (api) => {
* const timestamp = await api.query.timestamp.now();
*
* console.log(`lastest block timestamp ${timestamp}`);
* });
* ```
*/
public static create (options?: ApiOptions): Promise<ApiPromise> {
return new ApiPromise(options).isReady;
}
/**
* @description Creates an instance of the ApiPromise class
* @param options Options to create an instance. This can be either [[ApiOptions]] or
* an [[WsProvider]].
* @example
* <BR>
*
* ```javascript
* import Api from '@polkadot/api/promise';
*
* new Api().isReady.then((api) => {
* api.rpc.subscribeNewHeads((header) => {
* console.log(`new block #${header.number.toNumber()}`);
* });
* });
* ```
*/
constructor (options?: ApiOptions) {
super(options, 'promise', decorateMethod);
this.#isReadyPromise = new Promise((resolve): void => {
super.once('ready', (): void => {
resolve(this);
});
});
this.#isReadyOrErrorPromise = new Promise((resolve, reject): void => {
super.once('ready', (): void => {
resolve(this);
});
super.once('error', (e): void => {
reject(e);
});
});
}
/**
* @description Promise that resolves the first time we are connected and loaded
*/
public get isReady (): Promise<ApiPromise> {
return this.#isReadyPromise;
}
/**
* @description Promise that resolves if we can connect, or reject if there is an error
*/
public get isReadyOrError (): Promise<ApiPromise> {
return this.#isReadyOrErrorPromise;
}
/**
* @description Returns a clone of this ApiPromise instance (new underlying provider connection)
*/
public clone (): ApiPromise {
return new ApiPromise({
...this._options,
source: this
});
}
/**
* @description Creates a combinator that can be used to combine the latest results from multiple subscriptions
* @param fns An array of function to combine, each in the form of `(cb: (value: void)) => void`
* @param callback A callback that will return an Array of all the values this combinator has been applied to
* @example
* <BR>
*
* ```javascript
* const address = '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFacT7';
*
* // combines values from balance & nonce as it updates
* api.combineLatest([
* api.rpc.chain.subscribeNewHeads,
* (cb) => api.query.system.account(address, cb)
* ], ([head, [balance, nonce]]) => {
* console.log(`#${head.number}: You have ${balance.free} units, with ${nonce} transactions sent`);
* });
* ```
*/
// eslint-disable-next-line @typescript-eslint/require-await
public async combineLatest <T extends any[] = any[]> (fns: (CombinatorFunction | [CombinatorFunction, ...any[]])[], callback: CombinatorCallback<T>): UnsubscribePromise {
const combinator = new Combinator(fns, callback);
return (): void => {
combinator.unsubscribe();
};
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ export interface CombinatorFunction {
(cb: Callback<any>): UnsubscribePromise;
}
export default class Combinator<T extends any[] = any[]> {
export class Combinator<T extends any[] = any[]> {
#allHasFired = false;
#callback: CombinatorCallback<T>;
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import { UnsubscribePromise } from '../types';
import Combinator from './Combinator';
import { Combinator } from './Combinator';
describe('Combinator', (): void => {
let fns: ((value: any) => void)[] = [];
@@ -3,20 +3,20 @@
import { ApiOptions, SubmittableExtrinsic } from '../types';
import createPair from '@polkadot/keyring/pair';
import testKeyring from '@polkadot/keyring/testing';
import { createPair } from '@polkadot/keyring/pair';
import { createTestKeyring } from '@polkadot/keyring/testing';
import Mock from '@polkadot/rpc-provider/mock/index';
import { TypeRegistry } from '@polkadot/types';
import { hexToU8a } from '@polkadot/util';
import { SingleAccountSigner } from '../../test/util';
import ApiPromise from './Api';
import { ApiPromise } from '.';
const TRANSFER_SIG = '0x7a10e5ed9a14284eca7bea53f81631981dddda5a3d2dee973b136475947264801465726e4829ae3994d9058df638d959d4e043c7f1924299546790dda1dea20a';
describe('ApiPromise', (): void => {
const registry = new TypeRegistry();
const keyring = testKeyring({ type: 'ed25519' });
const keyring = createTestKeyring({ type: 'ed25519' });
const aliceEd = keyring.addPair(
// eslint-disable-next-line @typescript-eslint/unbound-method
createPair({ toSS58: keyring.encodeAddress, type: 'ed25519' }, {
+300 -3
View File
@@ -1,7 +1,304 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import ApiPromise, { decorateMethod } from './Api';
import { Callback, Codec } from '@polkadot/types/types';
import { ApiOptions, DecorateFn, DecorateMethodOptions, ObsInnerType, StorageEntryPromiseOverloads, UnsubscribePromise, VoidFn } from '../types';
export default ApiPromise;
export { decorateMethod };
import { EMPTY, Observable, Subscription } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { isFunction, assert } from '@polkadot/util';
import ApiBase from '../base';
import { Combinator, CombinatorCallback, CombinatorFunction } from './Combinator';
interface Tracker<T> {
reject: (value: Error) => Observable<never>;
resolve: (value: T) => void;
}
// extract the arguments and callback params from a value array possibly containing a callback
function extractArgs (args: unknown[], needsCallback: boolean): [unknown[], Callback<Codec> | undefined] {
let callback: Callback<Codec> | undefined;
const actualArgs = args.slice();
// If the last arg is a function, we pop it, put it into callback.
// actualArgs will then hold the actual arguments to be passed to `method`
if (args.length && isFunction(args[args.length - 1])) {
callback = actualArgs.pop() as Callback<Codec>;
}
// When we need a subscription, ensure that a valid callback is actually passed
assert(!needsCallback || isFunction(callback), 'Expected a callback to be passed with subscriptions');
return [actualArgs, callback];
}
// a Promise completion tracker, wrapping an isComplete variable that ensures the promise only resolves once
function promiseTracker<T> (resolve: (value: T) => void, reject: (value: Error) => void): Tracker<T> {
let isCompleted = false;
return {
reject: (error: Error): Observable<never> => {
if (!isCompleted) {
isCompleted = true;
reject(error);
}
return EMPTY;
},
resolve: (value: T): void => {
if (!isCompleted) {
isCompleted = true;
resolve(value);
}
}
};
}
// Decorate a call for a single-shot result - retrieve and then immediate unsubscribe
function decorateCall<Method extends DecorateFn<ObsInnerType<ReturnType<Method>>>> (method: Method, actualArgs: unknown[]): Promise<ObsInnerType<ReturnType<Method>>> {
return new Promise((resolve, reject): void => {
// single result tracker - either reject with Error or resolve with Codec result
const tracker = promiseTracker(resolve, reject);
// encoding errors reject immediately, any result unsubscribes and resolves
const subscription: Subscription = method(...actualArgs).pipe(
catchError((error) => tracker.reject(error))
).subscribe((result): void => {
tracker.resolve(result);
setTimeout(() => subscription.unsubscribe(), 0);
});
});
}
// Decorate a subscription where we have a result callback specified
function decorateSubscribe<Method extends DecorateFn<ObsInnerType<ReturnType<Method>>>> (method: Method, actualArgs: unknown[], resultCb: Callback<Codec>): UnsubscribePromise {
return new Promise<VoidFn>((resolve, reject): void => {
// either reject with error or resolve with unsubscribe callback
const tracker = promiseTracker(resolve, reject);
// errors reject immediately, the first result resolves with an unsubscribe promise, all results via callback
const subscription: Subscription = method(...actualArgs).pipe(
catchError((error) => tracker.reject(error)),
tap(() => tracker.resolve(() => subscription.unsubscribe()))
).subscribe((result): void => {
// queue result (back of queue to clear current)
setTimeout(() => resultCb(result) as void, 0);
});
});
}
/**
* @description Decorate method for ApiPromise, where the results are converted to the Promise equivalent
*/
export function decorateMethod<Method extends DecorateFn<ObsInnerType<ReturnType<Method>>>> (method: Method, options?: DecorateMethodOptions): StorageEntryPromiseOverloads {
const needsCallback = options && options.methodName && options.methodName.includes('subscribe');
return function (...args: unknown[]): Promise<ObsInnerType<ReturnType<Method>>> | UnsubscribePromise {
const [actualArgs, resultCb] = extractArgs(args, !!needsCallback);
return resultCb
? decorateSubscribe(method, actualArgs, resultCb)
: decorateCall((options?.overrideNoSub as Method) || method, actualArgs);
} as StorageEntryPromiseOverloads;
}
/**
* # @polkadot/api/promise
*
* ## Overview
*
* @name ApiPromise
* @description
* ApiPromise is a standard JavaScript wrapper around the RPC and interfaces on the Polkadot network. As a full Promise-based, all interface calls return Promises, including the static `.create(...)`. Subscription calls utilise `(value) => {}` callbacks to pass through the latest values.
*
* The API is well suited to real-time applications where either the single-shot state is needed or use is to be made of the subscription-based features of Polkadot (and Substrate) clients.
*
* @see [[ApiRx]]
*
* ## Usage
*
* Making rpc calls -
* <BR>
*
* ```javascript
* import ApiPromise from '@polkadot/api/promise';
*
* // initialise via static create
* const api = await ApiPromise.create();
*
* // make a subscription to the network head
* api.rpc.chain.subscribeNewHeads((header) => {
* console.log(`Chain is at #${header.number}`);
* });
* ```
* <BR>
*
* Subscribing to chain state -
* <BR>
*
* ```javascript
* import { ApiPromise, WsProvider } from '@polkadot/api';
*
* // initialise a provider with a specific endpoint
* const provider = new WsProvider('wss://example.com:9944')
*
* // initialise via isReady & new with specific provider
* const api = await new ApiPromise({ provider }).isReady;
*
* // retrieve the block target time
* const blockPeriod = await api.query.timestamp.blockPeriod().toNumber();
* let last = 0;
*
* // subscribe to the current block timestamp, updates automatically (callback provided)
* api.query.timestamp.now((timestamp) => {
* const elapsed = last
* ? `, ${timestamp.toNumber() - last}s since last`
* : '';
*
* last = timestamp.toNumber();
* console.log(`timestamp ${timestamp}${elapsed} (${blockPeriod}s target)`);
* });
* ```
* <BR>
*
* Submitting a transaction -
* <BR>
*
* ```javascript
* import ApiPromise from '@polkadot/api/promise';
*
* ApiPromise.create().then((api) => {
* const [nonce] = await api.query.system.account(keyring.alice.address);
*
* api.tx.balances
* // create transfer
* transfer(keyring.bob.address, 12345)
* // sign the transcation
* .sign(keyring.alice, { nonce })
* // send the transaction (optional status callback)
* .send((status) => {
* console.log(`current status ${status.type}`);
* })
* // retrieve the submitted extrinsic hash
* .then((hash) => {
* console.log(`submitted with hash ${hash}`);
* });
* });
* ```
*/
export class ApiPromise extends ApiBase<'promise'> {
#isReadyPromise: Promise<ApiPromise>;
#isReadyOrErrorPromise: Promise<ApiPromise>;
/**
* @description Creates an ApiPromise instance using the supplied provider. Returns an Promise containing the actual Api instance.
* @param options options that is passed to the class contructor. Can be either [[ApiOptions]] or a
* provider (see the constructor arguments)
* @example
* <BR>
*
* ```javascript
* import Api from '@polkadot/api/promise';
*
* Api.create().then(async (api) => {
* const timestamp = await api.query.timestamp.now();
*
* console.log(`lastest block timestamp ${timestamp}`);
* });
* ```
*/
public static create (options?: ApiOptions): Promise<ApiPromise> {
return new ApiPromise(options).isReady;
}
/**
* @description Creates an instance of the ApiPromise class
* @param options Options to create an instance. This can be either [[ApiOptions]] or
* an [[WsProvider]].
* @example
* <BR>
*
* ```javascript
* import Api from '@polkadot/api/promise';
*
* new Api().isReady.then((api) => {
* api.rpc.subscribeNewHeads((header) => {
* console.log(`new block #${header.number.toNumber()}`);
* });
* });
* ```
*/
constructor (options?: ApiOptions) {
super(options, 'promise', decorateMethod);
this.#isReadyPromise = new Promise((resolve): void => {
super.once('ready', (): void => {
resolve(this);
});
});
this.#isReadyOrErrorPromise = new Promise((resolve, reject): void => {
super.once('ready', (): void => {
resolve(this);
});
super.once('error', (e): void => {
reject(e);
});
});
}
/**
* @description Promise that resolves the first time we are connected and loaded
*/
public get isReady (): Promise<ApiPromise> {
return this.#isReadyPromise;
}
/**
* @description Promise that resolves if we can connect, or reject if there is an error
*/
public get isReadyOrError (): Promise<ApiPromise> {
return this.#isReadyOrErrorPromise;
}
/**
* @description Returns a clone of this ApiPromise instance (new underlying provider connection)
*/
public clone (): ApiPromise {
return new ApiPromise({
...this._options,
source: this
});
}
/**
* @description Creates a combinator that can be used to combine the latest results from multiple subscriptions
* @param fns An array of function to combine, each in the form of `(cb: (value: void)) => void`
* @param callback A callback that will return an Array of all the values this combinator has been applied to
* @example
* <BR>
*
* ```javascript
* const address = '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFacT7';
*
* // combines values from balance & nonce as it updates
* api.combineLatest([
* api.rpc.chain.subscribeNewHeads,
* (cb) => api.query.system.account(address, cb)
* ], ([head, [balance, nonce]]) => {
* console.log(`#${head.number}: You have ${balance.free} units, with ${nonce} transactions sent`);
* });
* ```
*/
// eslint-disable-next-line @typescript-eslint/require-await
public async combineLatest <T extends any[] = any[]> (fns: (CombinatorFunction | [CombinatorFunction, ...any[]])[], callback: CombinatorCallback<T>): UnsubscribePromise {
const combinator = new Combinator(fns, callback);
return (): void => {
combinator.unsubscribe();
};
}
}
-191
View File
@@ -1,191 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Codec } from '@polkadot/types/types';
import { ApiOptions, DecorateFn } from '../types';
import { from, Observable } from 'rxjs';
import ApiBase from '../base';
export function decorateMethod <Method extends DecorateFn<Codec>> (method: Method): Method {
return method;
}
/**
* # @polkadot/api/rx
*
* ## Overview
*
* @name ApiRx
*
* @description
* ApiRx is a powerful RxJS Observable wrapper around the RPC and interfaces on the Polkadot network. As a full Observable API, all interface calls return RxJS Observables, including the static `.create(...)`. In the same fashion and subscription-based methods return long-running Observables that update with the latest values.
*
* The API is well suited to real-time applications where the latest state is needed, unlocking the subscription-based features of Polkadot (and Substrate) clients. Some familiarity with RxJS is a requirement to use the API, however just understanding `.subscribe` and `.pipe` on Observables will unlock full-scale use thereof.
*
* @see [[ApiPromise]]
*
* ## Usage
*
* Making rpc calls -
* <BR>
*
* ```javascript
* import ApiRx from '@polkadot/api/rx';
*
* // initialize via Promise & static create
* const api = await ApiRx.create().toPromise();
*
* // make a call to retrieve the current network head
* api.rpc.chain.subscribeNewHeads().subscribe((header) => {
* console.log(`Chain is at #${header.number}`);
* });
* ```
* <BR>
*
* Subscribing to chain state -
* <BR>
*
* ```javascript
* import { combineLatest } from 'rxjs';
* import { pairwise, switchMap } from 'rxjs/operators';
* import { ApiRx, WsProvider } from '@polkadot/api';
*
*
* // initialize a provider with a specific endpoint
* const provider = new WsProvider('wss://example.com:9944')
*
* // initialize via isReady & new with specific provider
* new ApiRx({ provider })
* .isReady
* .pipe(
* switchMap((api) =>
* combineLatest([
* api.query.timestamp.blockPeriod(),
* api.query.timestamp.now().pipe(pairwise())
* ])
* )
* )
* .subscribe(([blockPeriod, timestamp]) => {
* const elapsed = timestamp[1].toNumber() - timestamp[0].toNumber();
* console.log(`timestamp ${timestamp[1]} \nelapsed ${elapsed} \n(${blockPeriod}s target)`);
* });
* ```
* <BR>
*
* Submitting a transaction -
* <BR>
*
* ```javascript
* import { first, switchMap } from 'rxjs/operators';
* import ApiRx from '@polkadot/api/rx';
*
* // import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
* import testingPairs from '@polkadot/keyring/testingPairs';
* const keyring = testingPairs();
*
* // get api via Promise
* const api = await ApiRx.create().toPromise();
*
* // retrieve nonce for the account
* api.query.system
* .account(keyring.alice.address)
* .pipe(
* first(),
* // pipe nonce into transfer
* switchMap(([nonce]) =>
* api.tx.balances
* // create transfer
* .transfer(keyring.bob.address, 12345)
* // sign the transaction
* .sign(keyring.alice, { nonce })
* // send the transaction
* .send()
* )
* )
* // subscribe to overall result
* .subscribe(({ status }) => {
* if (status.isInBlock) {
* console.log('Completed at block hash', status.asFinalized.toHex());
* }
* });
* ```
*/
export default class ApiRx extends ApiBase<'rxjs'> {
#isReadyRx: Observable<ApiRx>;
/**
* @description Creates an ApiRx instance using the supplied provider. Returns an Observable containing the actual Api instance.
* @param options options that is passed to the class constructor. Can be either [[ApiOptions]] or [[WsProvider]]
* @example
* <BR>
*
* ```javascript
* import { switchMap } from 'rxjs/operators';
* import Api from '@polkadot/api/rx';
*
* Api.create()
* .pipe(
* switchMap((api) =>
* api.rpc.chain.subscribeNewHeads()
* ))
* .subscribe((header) => {
* console.log(`new block #${header.number.toNumber()}`);
* });
* ```
*/
public static create (options?: ApiOptions): Observable<ApiRx> {
return new ApiRx(options).isReady;
}
/**
* @description Create an instance of the ApiRx class
* @param options Options to create an instance. Can be either [[ApiOptions]] or [[WsProvider]]
* @example
* <BR>
*
* ```javascript
* import { switchMap } from 'rxjs/operators';
* import Api from '@polkadot/api/rx';
*
* new Api().isReady
* .pipe(
* switchMap((api) =>
* api.rpc.chain.subscribeNewHeads()
* ))
* .subscribe((header) => {
* console.log(`new block #${header.number.toNumber()}`);
* });
* ```
*/
constructor (options?: ApiOptions) {
super(options, 'rxjs', decorateMethod);
this.#isReadyRx = from<Promise<ApiRx>>(
// You can create an observable from an event, however my mind groks this form better
new Promise((resolve): void => {
super.on('ready', (): void => {
resolve(this);
});
})
);
}
/**
* @description Observable that returns the first time we are connected and loaded
*/
public get isReady (): Observable<ApiRx> {
return this.#isReadyRx;
}
/**
* @description Returns a clone of this ApiRx instance (new underlying provider connection)
*/
public clone (): ApiRx {
return new ApiRx({
...this._options,
source: this
});
}
}
@@ -5,16 +5,16 @@ import { SubmittableExtrinsic } from '../submittable/types';
import { Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import testingPairs from '@polkadot/keyring/testingPairs';
import { createTestPairs } from '@polkadot/keyring/testingPairs';
import Mock from '@polkadot/rpc-provider/mock/index';
import { TypeRegistry } from '@polkadot/types';
import { SingleAccountSigner } from '../../test/util';
import ApiRx from './Api';
import { ApiRx } from '.';
describe('ApiRx', (): void => {
const registry = new TypeRegistry();
const keyring = testingPairs({ type: 'ed25519' });
const keyring = createTestPairs({ type: 'ed25519' });
let provider: Mock;
beforeEach((): void => {
+187 -3
View File
@@ -1,7 +1,191 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import ApiRx, { decorateMethod } from './Api';
import { Codec } from '@polkadot/types/types';
import { ApiOptions, DecorateFn } from '../types';
export default ApiRx;
export { decorateMethod };
import { from, Observable } from 'rxjs';
import ApiBase from '../base';
export function decorateMethod <Method extends DecorateFn<Codec>> (method: Method): Method {
return method;
}
/**
* # @polkadot/api/rx
*
* ## Overview
*
* @name ApiRx
*
* @description
* ApiRx is a powerful RxJS Observable wrapper around the RPC and interfaces on the Polkadot network. As a full Observable API, all interface calls return RxJS Observables, including the static `.create(...)`. In the same fashion and subscription-based methods return long-running Observables that update with the latest values.
*
* The API is well suited to real-time applications where the latest state is needed, unlocking the subscription-based features of Polkadot (and Substrate) clients. Some familiarity with RxJS is a requirement to use the API, however just understanding `.subscribe` and `.pipe` on Observables will unlock full-scale use thereof.
*
* @see [[ApiPromise]]
*
* ## Usage
*
* Making rpc calls -
* <BR>
*
* ```javascript
* import ApiRx from '@polkadot/api/rx';
*
* // initialize via Promise & static create
* const api = await ApiRx.create().toPromise();
*
* // make a call to retrieve the current network head
* api.rpc.chain.subscribeNewHeads().subscribe((header) => {
* console.log(`Chain is at #${header.number}`);
* });
* ```
* <BR>
*
* Subscribing to chain state -
* <BR>
*
* ```javascript
* import { combineLatest } from 'rxjs';
* import { pairwise, switchMap } from 'rxjs/operators';
* import { ApiRx, WsProvider } from '@polkadot/api';
*
*
* // initialize a provider with a specific endpoint
* const provider = new WsProvider('wss://example.com:9944')
*
* // initialize via isReady & new with specific provider
* new ApiRx({ provider })
* .isReady
* .pipe(
* switchMap((api) =>
* combineLatest([
* api.query.timestamp.blockPeriod(),
* api.query.timestamp.now().pipe(pairwise())
* ])
* )
* )
* .subscribe(([blockPeriod, timestamp]) => {
* const elapsed = timestamp[1].toNumber() - timestamp[0].toNumber();
* console.log(`timestamp ${timestamp[1]} \nelapsed ${elapsed} \n(${blockPeriod}s target)`);
* });
* ```
* <BR>
*
* Submitting a transaction -
* <BR>
*
* ```javascript
* import { first, switchMap } from 'rxjs/operators';
* import ApiRx from '@polkadot/api/rx';
*
* // import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
* import testingPairs from '@polkadot/keyring/testingPairs';
* const keyring = testingPairs();
*
* // get api via Promise
* const api = await ApiRx.create().toPromise();
*
* // retrieve nonce for the account
* api.query.system
* .account(keyring.alice.address)
* .pipe(
* first(),
* // pipe nonce into transfer
* switchMap(([nonce]) =>
* api.tx.balances
* // create transfer
* .transfer(keyring.bob.address, 12345)
* // sign the transaction
* .sign(keyring.alice, { nonce })
* // send the transaction
* .send()
* )
* )
* // subscribe to overall result
* .subscribe(({ status }) => {
* if (status.isInBlock) {
* console.log('Completed at block hash', status.asFinalized.toHex());
* }
* });
* ```
*/
export class ApiRx extends ApiBase<'rxjs'> {
#isReadyRx: Observable<ApiRx>;
/**
* @description Creates an ApiRx instance using the supplied provider. Returns an Observable containing the actual Api instance.
* @param options options that is passed to the class constructor. Can be either [[ApiOptions]] or [[WsProvider]]
* @example
* <BR>
*
* ```javascript
* import { switchMap } from 'rxjs/operators';
* import Api from '@polkadot/api/rx';
*
* Api.create()
* .pipe(
* switchMap((api) =>
* api.rpc.chain.subscribeNewHeads()
* ))
* .subscribe((header) => {
* console.log(`new block #${header.number.toNumber()}`);
* });
* ```
*/
public static create (options?: ApiOptions): Observable<ApiRx> {
return new ApiRx(options).isReady;
}
/**
* @description Create an instance of the ApiRx class
* @param options Options to create an instance. Can be either [[ApiOptions]] or [[WsProvider]]
* @example
* <BR>
*
* ```javascript
* import { switchMap } from 'rxjs/operators';
* import Api from '@polkadot/api/rx';
*
* new Api().isReady
* .pipe(
* switchMap((api) =>
* api.rpc.chain.subscribeNewHeads()
* ))
* .subscribe((header) => {
* console.log(`new block #${header.number.toNumber()}`);
* });
* ```
*/
constructor (options?: ApiOptions) {
super(options, 'rxjs', decorateMethod);
this.#isReadyRx = from<Promise<ApiRx>>(
// You can create an observable from an event, however my mind groks this form better
new Promise((resolve): void => {
super.on('ready', (): void => {
resolve(this);
});
})
);
}
/**
* @description Observable that returns the first time we are connected and loaded
*/
public get isReady (): Observable<ApiRx> {
return this.#isReadyRx;
}
/**
* @description Returns a clone of this ApiRx instance (new underlying provider connection)
*/
public clone (): ApiRx {
return new ApiRx({
...this._options,
source: this
});
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ function extractInfo (events: EventRecord[] = []): DispatchInfo | undefined {
)[0];
}
export default class SubmittableResult implements ISubmittableResult {
export class SubmittableResult implements ISubmittableResult {
public readonly dispatchError?: DispatchError;
public readonly dispatchInfo?: DispatchInfo;
+2 -2
View File
@@ -14,7 +14,7 @@ import { assert, isBn, isFunction, isNumber, isString, isU8a } from '@polkadot/u
import { filterEvents, isKeyringPair } from '../util';
import ApiBase from '../base';
import SubmittableResult from './Result';
import { SubmittableResult } from './Result';
interface SubmittableOptions<ApiType extends ApiTypes> {
api: ApiInterfaceRx;
@@ -24,7 +24,7 @@ interface SubmittableOptions<ApiType extends ApiTypes> {
const identity = <T> (input: T): T => input;
export default function createClass <ApiType extends ApiTypes> ({ api, apiType, decorateMethod }: SubmittableOptions<ApiType>): Constructor<SubmittableExtrinsic<ApiType>> {
export function createClass <ApiType extends ApiTypes> ({ api, apiType, decorateMethod }: SubmittableOptions<ApiType>): Constructor<SubmittableExtrinsic<ApiType>> {
// an instance of the base extrinsic for us to extend
const ExtrinsicBase = api.registry.createClass('Extrinsic');
@@ -6,11 +6,11 @@ import { ApiInterfaceRx, ApiTypes } from '../types';
import { SubmittableExtrinsic } from './types';
import ApiBase from '../base';
import createClass from './createClass';
import { createClass } from './createClass';
type Creator<ApiType extends ApiTypes> = (extrinsic: Call | Uint8Array | string) => SubmittableExtrinsic<ApiType>;
export default function createSubmittable<ApiType extends ApiTypes> (apiType: ApiTypes, api: ApiInterfaceRx, decorateMethod: ApiBase<ApiType>['_decorateMethod']): Creator<ApiType> {
export function createSubmittable<ApiType extends ApiTypes> (apiType: ApiTypes, api: ApiInterfaceRx, decorateMethod: ApiBase<ApiType>['_decorateMethod']): Creator<ApiType> {
const Submittable = createClass<ApiType>({ api, apiType, decorateMethod });
return (extrinsic: Call | Extrinsic | Uint8Array | string): SubmittableExtrinsic<ApiType> =>
+2 -2
View File
@@ -1,5 +1,5 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as createSubmittable } from './createSubmittable';
export { default as SubmittableResult } from './Result';
export { createSubmittable } from './createSubmittable';
export { SubmittableResult } from './Result';
+1 -1
View File
@@ -3,7 +3,7 @@
import { Storage } from '@polkadot/metadata/decorate/types';
import Metadata, { storageFromMeta } from '@polkadot/metadata';
import { Metadata, storageFromMeta } from '@polkadot/metadata';
import metaStatic from '@polkadot/metadata/static';
import { TypeRegistry } from '@polkadot/types';
+3 -3
View File
@@ -31,11 +31,11 @@
"@babel/runtime": "^7.12.1",
"@polkadot/types": "2.6.2-0",
"@polkadot/types-known": "2.6.2-0",
"@polkadot/util": "^4.0.1",
"@polkadot/util-crypto": "^4.0.1",
"@polkadot/util": "^4.0.2-5",
"@polkadot/util-crypto": "^4.0.2-5",
"bn.js": "^5.1.3"
},
"devDependencies": {
"@polkadot/keyring": "^4.0.1"
"@polkadot/keyring": "^4.0.2-5"
}
}
+1 -1
View File
@@ -3,7 +3,7 @@
import { TypeRegistry } from '@polkadot/types';
import MagicNumber, { MAGIC_NUMBER } from './MagicNumber';
import { MagicNumber, MAGIC_NUMBER } from './MagicNumber';
describe('MagicNumber', (): void => {
const registry = new TypeRegistry();
+1 -1
View File
@@ -9,7 +9,7 @@ import U32 from '@polkadot/types/primitive/U32';
export const MAGIC_NUMBER = 0x6174656d; // `meta`, reversed for Little Endian encoding
export default class MagicNumber extends U32 {
export class MagicNumber extends U32 {
constructor (registry: Registry, value?: AnyNumber) {
super(registry, value);
+1 -1
View File
@@ -4,7 +4,7 @@
import { TypeRegistry } from '@polkadot/types';
import substrateData from './static';
import Metadata from './Metadata';
import { Metadata } from './Metadata';
describe('Metadata', (): void => {
it('allows creation from hex with JSON equivalence', (): void => {
+2 -2
View File
@@ -5,7 +5,7 @@ import { Registry } from '@polkadot/types/types';
import { isString, u8aConcat, u8aToU8a } from '@polkadot/util';
import MetadataVersioned from './MetadataVersioned';
import { MetadataVersioned } from './MetadataVersioned';
// magic u32 preceding the version id
const VERSION_IDX = 4;
@@ -49,7 +49,7 @@ function decodeMetadata (registry: Registry, _value?: Uint8Array | string): Meta
* @description
* The versioned runtime metadata as a decoded structure
*/
export default class Metadata extends MetadataVersioned {
export class Metadata extends MetadataVersioned {
constructor (registry: Registry, value?: Uint8Array | string) {
super(registry, decodeMetadata(registry, value));
}
+2 -2
View File
@@ -7,7 +7,7 @@ import { Registry } from '@polkadot/types/types';
import Struct from '@polkadot/types/codec/Struct';
import { assert } from '@polkadot/util';
import MagicNumber from './MagicNumber';
import { MagicNumber } from './MagicNumber';
import v9ToV10 from './v9/toV10';
import v10ToV11 from './v10/toV11';
import v11ToV12 from './v11/toV12';
@@ -23,7 +23,7 @@ type MetaAsX = 'asV9' | 'asV10' | 'asV11' | 'asV12';
* @description
* The versioned runtime metadata as a decoded structure
*/
export default class MetadataVersioned extends Struct {
export class MetadataVersioned extends Struct {
readonly #converted = new Map<number, MetaMapped>();
constructor (registry: Registry, value?: unknown) {
@@ -7,7 +7,7 @@ import { Metadata, TypeRegistry } from '@polkadot/types';
import rpcMetadata from '../../static';
import rpcMetadataV10 from '../../v10/static';
import fromMetadata from './fromMetadata';
import { constantsFromMeta } from './fromMetadata';
function init (meta: string): [Constants, TypeRegistry] {
const registry = new TypeRegistry();
@@ -15,7 +15,7 @@ function init (meta: string): [Constants, TypeRegistry] {
registry.setMetadata(metadata);
return [fromMetadata(registry, metadata), registry];
return [constantsFromMeta(registry, metadata), registry];
}
describe('fromMetadata', (): void => {
@@ -7,10 +7,10 @@ import { Constants, ConstantCodec, ModuleConstants } from '../types';
import { createTypeUnsafe } from '@polkadot/types/create';
import { hexToU8a, stringCamelCase } from '@polkadot/util';
import Metadata from '../..';
import { Metadata } from '../..';
/** @internal */
export default function fromMetadata (registry: Registry, metadata: Metadata): Constants {
export function constantsFromMeta (registry: Registry, metadata: Metadata): Constants {
return metadata.asLatest.modules.reduce((result: Constants, moduleMetadata): Constants => {
if (moduleMetadata.constants.isEmpty) {
return result;
@@ -4,7 +4,7 @@
import { Metadata, TypeRegistry } from '@polkadot/types';
import json from '../../static';
import fromMetadata from './fromMetadata';
import { extrinsicsFromMeta } from './fromMetadata';
// Use the pre-generated metadata
const registry = new TypeRegistry();
@@ -12,7 +12,7 @@ const metadata = new Metadata(registry, json);
registry.setMetadata(metadata);
const newExtrinsics = fromMetadata(registry, metadata);
const newExtrinsics = extrinsicsFromMeta(registry, metadata);
describe('fromMetadata', (): void => {
it('should throw if an incorrect number of args is supplied', (): void => {
@@ -9,7 +9,7 @@ import extrinsics from './';
import createUnchecked from './createUnchecked';
/** @internal */
export default function fromMetadata (registry: Registry, metadata: RegistryMetadata): ModulesWithCalls {
export function extrinsicsFromMeta (registry: Registry, metadata: RegistryMetadata): ModulesWithCalls {
const modules = metadata.asLatest.modules;
const isIndexed = modules.some(({ index }) => !index.eqn(255));
@@ -2,19 +2,19 @@
// SPDX-License-Identifier: Apache-2.0
import BN from 'bn.js';
import testingPairs from '@polkadot/keyring/testingPairs';
import { createTestPairs } from '@polkadot/keyring/testingPairs';
import { Metadata, TypeRegistry } from '@polkadot/types';
import metadataStatic from '../../static';
import fromMetadata from './fromMetadata';
import { extrinsicsFromMeta } from './fromMetadata';
const keyring = testingPairs({ type: 'ed25519' }, false);
const keyring = createTestPairs({ type: 'ed25519' }, false);
const registry = new TypeRegistry();
const metadata = new Metadata(registry, metadataStatic);
registry.setMetadata(metadata);
const extrinsics = fromMetadata(registry, metadata);
const extrinsics = extrinsicsFromMeta(registry, metadata);
describe('extrinsics', (): void => {
it('encodes an actual transfer (actual data)', (): void => {
+1 -1
View File
@@ -4,7 +4,7 @@
import { TypeRegistry } from '@polkadot/types/create';
import { u8aToHex } from '@polkadot/util';
import Metadata from '..';
import { Metadata } from '..';
import json from '../static';
import { constantsFromMeta, extrinsicsFromMeta, storageFromMeta } from './';
+5 -5
View File
@@ -6,15 +6,15 @@ import { DecoratedMeta } from './types';
import { assert } from '@polkadot/util';
import Metadata from '..';
import constantsFromMeta from './consts/fromMetadata';
import extrinsicsFromMeta from './extrinsics/fromMetadata';
import storageFromMeta from './storage/fromMetadata';
import { Metadata } from '..';
import { constantsFromMeta } from './consts/fromMetadata';
import { extrinsicsFromMeta } from './extrinsics/fromMetadata';
import { storageFromMeta } from './storage/fromMetadata';
/**
* Expands the metadata by decoration int consts, query and tx sections
*/
export default function expandMetadata (registry: Registry, value: Metadata): DecoratedMeta {
export function expandMetadata (registry: Registry, value: Metadata): DecoratedMeta {
assert(value instanceof Metadata, 'You need to pass a valid Metadata instance to Decorated');
return {
@@ -1,15 +1,15 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import testingPairs from '@polkadot/keyring/testingPairs';
import { createTestPairs } from '@polkadot/keyring/testingPairs';
import { TypeRegistry } from '@polkadot/types';
import { u8aToHex } from '@polkadot/util';
import Metadata from '../../';
import { Metadata } from '../../';
import rpcMetadata from '../../static';
import { storageFromMeta } from '../';
const keyring = testingPairs({ type: 'ed25519' });
const keyring = createTestPairs({ type: 'ed25519' });
describe('fromMetadata', (): void => {
describe('latest', (): void => {
@@ -6,12 +6,12 @@ import { ModuleStorage, Storage } from '../types';
import { stringCamelCase, stringLowerFirst } from '@polkadot/util';
import Metadata from '../../Metadata';
import { Metadata } from '../../Metadata';
import createFunction from './createFunction';
import getStorage from './storage';
/** @internal */
export default function fromMetadata (registry: Registry, metadata: Metadata): Storage {
export function storageFromMeta (registry: Registry, metadata: Metadata): Storage {
return metadata.asLatest.modules.reduce((result: Storage, moduleMetadata): Storage => {
if (moduleMetadata.storage.isNone) {
return result;
+2 -6
View File
@@ -1,9 +1,5 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import expandMetadata, { constantsFromMeta, extrinsicsFromMeta, storageFromMeta } from './decorate';
import Metadata from './Metadata';
export default Metadata;
export { constantsFromMeta, expandMetadata, extrinsicsFromMeta, storageFromMeta };
export { Metadata } from './Metadata';
export { constantsFromMeta, expandMetadata, extrinsicsFromMeta, storageFromMeta } from './decorate';
+1 -1
View File
@@ -7,7 +7,7 @@ import { MetadataInterface } from '../types';
import { unwrapStorageType } from '@polkadot/types/primitive/StorageKey';
import getUniqTypes from './getUniqTypes';
import Metadata from '..';
import { Metadata } from '..';
/** @internal */
export function decodeLatestSubstrate<Modules extends Codec> (registry: Registry, version: number, rpcData: string, staticSubstrate: Record<string, unknown>): void {
@@ -4,7 +4,7 @@
import { TypeRegistry } from '@polkadot/types';
import staticData from '../static';
import Metadata from '..';
import { Metadata } from '..';
describe('toCallsOnly', (): void => {
const registry = new TypeRegistry();
+1 -1
View File
@@ -14,7 +14,7 @@ Initialization -
```js
import Rpc from '@polkadot/rpc-core';
import WsProvider from '@polkadot/rpc-provider/ws';
import { WsProvider } from '@polkadot/rpc-provider/ws';
const provider = new WsProvider('http://127.0.0.1:9944');
const rpc = new Rpc(provider);
+2 -2
View File
@@ -32,11 +32,11 @@
"@polkadot/metadata": "2.6.2-0",
"@polkadot/rpc-provider": "2.6.2-0",
"@polkadot/types": "2.6.2-0",
"@polkadot/util": "^4.0.1",
"@polkadot/util": "^4.0.2-5",
"memoizee": "^0.4.14",
"rxjs": "^6.6.3"
},
"devDependencies": {
"@polkadot/keyring": "^4.0.1"
"@polkadot/keyring": "^4.0.2-5"
}
}
+5 -5
View File
@@ -1,19 +1,19 @@
// Copyright 2017-2020 @polkadot/rpc-core authors & contributors
// SPDX-License-Identifier: Apache-2.0
import testingPairs from '@polkadot/keyring/testingPairs';
import { createTestPairs } from '@polkadot/keyring/testingPairs';
import MockProvider from '@polkadot/rpc-provider/mock';
import { TypeRegistry } from '@polkadot/types';
import Rpc from '.';
import { RpcCore } from '.';
describe('Cached Observables', (): void => {
const registry = new TypeRegistry();
let rpc: Rpc;
const keyring = testingPairs();
let rpc: RpcCore;
const keyring = createTestPairs();
beforeEach((): void => {
rpc = new Rpc('123', registry, new MockProvider(registry));
rpc = new RpcCore('123', registry, new MockProvider(registry));
});
it('creates a single observable for subscriptions (multiple calls)', (): void => {
+3 -3
View File
@@ -5,19 +5,19 @@ import MockProvider from '@polkadot/rpc-provider/mock';
import { TypeRegistry } from '@polkadot/types';
import { isFunction } from '@polkadot/util';
import Rpc from '.';
import { RpcCore } from '.';
describe('Api', (): void => {
const registry = new TypeRegistry();
it('requires a provider with a send method', (): void => {
expect(
(): Rpc => new Rpc('234', registry, {} as any)
() => new RpcCore('234', registry, {} as any)
).toThrow(/Expected Provider/);
});
it('allows for the definition of user RPCs', (): void => {
const rpc = new Rpc('567', registry, new MockProvider(registry), {
const rpc = new RpcCore('567', registry, new MockProvider(registry), {
testing: {
foo: {
description: 'foo',
+2 -2
View File
@@ -61,13 +61,13 @@ function logErrorMessage (method: string, { params, type }: DefinitionRpc, error
*
* ```javascript
* import Rpc from '@polkadot/rpc-core';
* import WsProvider from '@polkadot/rpc-provider/ws';
* import { WsProvider } from '@polkadot/rpc-provider/ws';
*
* const provider = new WsProvider('ws://127.0.0.1:9944');
* const rpc = new Rpc(provider);
* ```
*/
export default class Rpc implements RpcInterface {
export class RpcCore implements RpcInterface {
#instanceId: string;
#registryDefault: Registry;
+3 -3
View File
@@ -5,11 +5,11 @@ import { DefinitionRpc } from '@polkadot/types/types';
import { TypeRegistry } from '@polkadot/types';
import Rpc from '.';
import { RpcCore } from '.';
describe('methodSend', (): void => {
const registry = new TypeRegistry();
let rpc: Rpc;
let rpc: RpcCore;
let methods: Record<string, DefinitionRpc>;
let provider: any;
@@ -35,7 +35,7 @@ describe('methodSend', (): void => {
})
};
rpc = new Rpc('987', registry, provider);
rpc = new RpcCore('987', registry, provider);
});
it('checks for mismatched parameters', (done): void => {
+3 -3
View File
@@ -5,14 +5,14 @@ import { Observable, of } from 'rxjs';
import MockProvider from '@polkadot/rpc-provider/mock';
import { TypeRegistry } from '@polkadot/types';
import Rpc from '.';
import { RpcCore } from '.';
describe('replay', (): void => {
const registry = new TypeRegistry();
let rpc: Rpc;
let rpc: RpcCore;
beforeEach((): void => {
rpc = new Rpc('653', registry, new MockProvider(registry));
rpc = new RpcCore('653', registry, new MockProvider(registry));
});
it('subscribes via the rpc section', (done): void => {
+1 -1
View File
@@ -19,7 +19,7 @@ yarn add @polkadot/rpc-provider
WebSocket Initialization -
```javascript
import WsProvider from '@polkadot/rpc-provider/ws';
import { WsProvider } from '@polkadot/rpc-provider/ws';
// this is the actual default endpoint
const provider = new WsProvider('ws://127.0.0.1:9944');
+5 -5
View File
@@ -30,15 +30,15 @@
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/types": "2.6.2-0",
"@polkadot/util": "^4.0.1",
"@polkadot/util-crypto": "^4.0.1",
"@polkadot/x-fetch": "^4.0.1",
"@polkadot/x-ws": "^4.0.1",
"@polkadot/util": "^4.0.2-5",
"@polkadot/util-crypto": "^4.0.2-5",
"@polkadot/x-fetch": "^4.0.2-5",
"@polkadot/x-ws": "^4.0.2-5",
"bn.js": "^5.1.3",
"eventemitter3": "^4.0.7"
},
"devDependencies": {
"@polkadot/keyring": "^4.0.1",
"@polkadot/keyring": "^4.0.2-5",
"@polkadot/metadata": "2.6.2-0",
"mock-socket": "^9.0.3",
"nock": "^13.0.4"
+6 -6
View File
@@ -2,30 +2,30 @@
// SPDX-License-Identifier: Apache-2.0
import { TEST_HTTP_URL } from '../../test/mockHttp';
import Http from './';
import { HttpProvider } from './';
describe('Http', (): void => {
let http: Http;
let http: HttpProvider;
beforeEach((): void => {
http = new Http(TEST_HTTP_URL);
http = new HttpProvider(TEST_HTTP_URL);
});
it('requires an http:// prefixed endpoint', (): void => {
expect(
(): Http => new Http('ws://')
() => new HttpProvider('ws://')
).toThrow(/with 'http/);
});
it('allows https:// endpoints', (): void => {
expect(
(): Http => new Http('https://')
() => new HttpProvider('https://')
).not.toThrow();
});
it('allows custom headers', (): void => {
expect(
(): Http => new Http('https://', { foo: 'bar' })
() => new HttpProvider('https://', { foo: 'bar' })
).not.toThrow();
});
+1 -1
View File
@@ -33,7 +33,7 @@ const l = logger('api-http');
*
* @see [[WsProvider]]
*/
export default class HttpProvider implements ProviderInterface {
export class HttpProvider implements ProviderInterface {
readonly #coder: Coder;
readonly #endpoint: string;
+3 -3
View File
@@ -4,14 +4,14 @@
import { Mock } from './../mock/types';
import { mockHttp, TEST_HTTP_URL } from '../../test/mockHttp';
import Http from './';
import { HttpProvider } from './';
describe('send', (): void => {
let http: Http;
let http: HttpProvider;
let mock: Mock;
beforeEach((): void => {
http = new Http(TEST_HTTP_URL);
http = new HttpProvider(TEST_HTTP_URL);
});
afterEach((): void => {
+2 -2
View File
@@ -1,5 +1,5 @@
// Copyright 2017-2020 @polkadot/rpc-provider authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as HttpProvider } from './http';
export { default as WsProvider } from './ws';
export { HttpProvider } from './http';
export { WsProvider } from './ws';
+3 -3
View File
@@ -10,10 +10,10 @@ import { MockStateSubscriptions, MockStateSubscriptionCallback, MockStateDb } fr
import BN from 'bn.js';
import EventEmitter from 'eventemitter3';
import Metadata, { storageFromMeta } from '@polkadot/metadata';
import { Metadata, storageFromMeta } from '@polkadot/metadata';
import rpcMetadata from '@polkadot/metadata/static';
import jsonrpc from '@polkadot/types/interfaces/jsonrpc';
import testKeyring from '@polkadot/keyring/testing';
import { createTestKeyring } from '@polkadot/keyring/testing';
import rpcHeader from '@polkadot/types/json/Header.004.json';
import rpcSignedBlock from '@polkadot/types/json/SignedBlock.004.immortal.json';
import { assert, bnToU8a, logger, u8aToHex } from '@polkadot/util';
@@ -31,7 +31,7 @@ const SUBSCRIPTIONS: string[] = Array.prototype.concat.apply(
)
) as string[];
const keyring = testKeyring({ type: 'ed25519' });
const keyring = createTestKeyring({ type: 'ed25519' });
const l = logger('api-mock');
/**
-468
View File
@@ -1,468 +0,0 @@
// Copyright 2017-2020 @polkadot/rpc-provider authors & contributors
// SPDX-License-Identifier: Apache-2.0
/* eslint-disable camelcase */
import { JsonRpcResponse, ProviderInterface, ProviderInterfaceCallback, ProviderInterfaceEmitted, ProviderInterfaceEmitCb } from '../types';
import EventEmitter from 'eventemitter3';
import { assert, isChildClass, isNull, isUndefined, logger } from '@polkadot/util';
import WS from '@polkadot/x-ws';
import Coder from '../coder';
import defaults from '../defaults';
import { getWSErrorString } from './errors';
interface SubscriptionHandler {
callback: ProviderInterfaceCallback;
type: string;
}
interface WsStateAwaiting {
callback: ProviderInterfaceCallback;
method: string;
params: any[];
subscription?: SubscriptionHandler;
}
interface WsStateSubscription extends SubscriptionHandler {
method: string;
params: any[];
}
const ALIASSES: { [index: string]: string } = {
chain_finalisedHead: 'chain_finalizedHead',
chain_subscribeFinalisedHeads: 'chain_subscribeFinalizedHeads',
chain_unsubscribeFinalisedHeads: 'chain_unsubscribeFinalizedHeads'
};
const RETRY_DELAY = 1000;
const l = logger('api-ws');
/**
* # @polkadot/rpc-provider/ws
*
* @name WsProvider
*
* @description The WebSocket Provider allows sending requests using WebSocket to a WebSocket RPC server TCP port. Unlike the [[HttpProvider]], it does support subscriptions and allows listening to events such as new blocks or balance changes.
*
* @example
* <BR>
*
* ```javascript
* import Api from '@polkadot/api/promise';
* import WsProvider from '@polkadot/rpc-provider/ws';
*
* const provider = new WsProvider('ws://127.0.0.1:9944');
* const api = new Api(provider);
* ```
*
* @see [[HttpProvider]]
*/
export default class WsProvider implements ProviderInterface {
readonly #coder: Coder;
readonly #endpoints: string[];
readonly #headers: Record<string, string>;
readonly #eventemitter: EventEmitter;
readonly #handlers: Record<string, WsStateAwaiting> = {};
readonly #queued: Record<string, string> = {};
readonly #waitingForId: Record<string, JsonRpcResponse> = {};
#autoConnectMs: number;
#endpointIndex: number;
#isConnected = false;
#subscriptions: Record<string, WsStateSubscription> = {};
#websocket: WebSocket | null;
/**
* @param {string | string[]} endpoint The endpoint url. Usually `ws://ip:9944` or `wss://ip:9944`, may provide an array of endpoint strings.
* @param {boolean} autoConnect Whether to connect automatically or not.
*/
constructor (endpoint: string | string[] = defaults.WS_URL, autoConnectMs: number | false = RETRY_DELAY, headers: Record<string, string> = {}) {
const endpoints = Array.isArray(endpoint)
? endpoint
: [endpoint];
assert(endpoints.length !== 0, 'WsProvider requires at least one Endpoint');
endpoints.forEach((endpoint) => {
assert(/^(wss|ws):\/\//.test(endpoint), `Endpoint should start with 'ws://', received '${endpoint}'`);
});
this.#eventemitter = new EventEmitter();
this.#autoConnectMs = autoConnectMs || 0;
this.#coder = new Coder();
this.#endpointIndex = -1;
this.#endpoints = endpoints;
this.#headers = headers;
this.#websocket = null;
if (autoConnectMs > 0) {
this.connectWithRetry().catch((): void => {
// does not throw
});
}
}
/**
* @summary `true` when this provider supports subscriptions
*/
public get hasSubscriptions (): boolean {
return true;
}
/**
* @summary Whether the node is connected or not.
* @return {boolean} true if connected
*/
public get isConnected (): boolean {
return this.#isConnected;
}
/**
* @description Returns a clone of the object
*/
public clone (): WsProvider {
return new WsProvider(this.#endpoints);
}
/**
* @summary Manually connect
* @description The [[WsProvider]] connects automatically by default, however if you decided otherwise, you may
* connect manually using this method.
*/
// eslint-disable-next-line @typescript-eslint/require-await
public async connect (): Promise<void> {
try {
this.#endpointIndex = (this.#endpointIndex + 1) % this.#endpoints.length;
this.#websocket = typeof WebSocket !== 'undefined' && isChildClass(WebSocket, WS)
? new WS(this.#endpoints[this.#endpointIndex])
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - WS may be an instance of w3cwebsocket, which supports headers
: new WS(this.#endpoints[this.#endpointIndex], undefined, undefined, this.#headers, undefined, {
// default: true
fragmentOutgoingMessages: true,
// default: 16K
fragmentationThreshold: 256 * 1024
});
this.#websocket.onclose = this.#onSocketClose;
this.#websocket.onerror = this.#onSocketError;
this.#websocket.onmessage = this.#onSocketMessage;
this.#websocket.onopen = this.#onSocketOpen;
} catch (error) {
l.error(error);
this.#emit('error', error);
throw error;
}
}
/**
* @description Connect, never throwing an error, but rather forcing a retry
*/
public async connectWithRetry (): Promise<void> {
try {
await this.connect();
} catch (error) {
setTimeout((): void => {
this.connectWithRetry().catch((): void => {
// does not throw
});
}, this.#autoConnectMs || RETRY_DELAY);
}
}
/**
* @description Manually disconnect from the connection, clearing autoconnect logic
*/
// eslint-disable-next-line @typescript-eslint/require-await
public async disconnect (): Promise<void> {
try {
assert(!isNull(this.#websocket), 'Cannot disconnect on a non-connected websocket');
// switch off autoConnect, we are in manual mode now
this.#autoConnectMs = 0;
// 1000 - Normal closure; the connection successfully completed
this.#websocket.close(1000);
this.#websocket = null;
} catch (error) {
l.error(error);
this.#emit('error', error);
throw error;
}
}
/**
* @summary Listens on events after having subscribed using the [[subscribe]] function.
* @param {ProviderInterfaceEmitted} type Event
* @param {ProviderInterfaceEmitCb} sub Callback
* @return unsubscribe function
*/
public on (type: ProviderInterfaceEmitted, sub: ProviderInterfaceEmitCb): () => void {
this.#eventemitter.on(type, sub);
return (): void => {
this.#eventemitter.removeListener(type, sub);
};
}
/**
* @summary Send JSON data using WebSockets to configured HTTP Endpoint or queue.
* @param method The RPC methods to execute
* @param params Encoded paramaters as appliucable for the method
* @param subscription Subscription details (internally used)
*/
public send (method: string, params: any[], subscription?: SubscriptionHandler): Promise<any> {
return new Promise((resolve, reject): void => {
try {
const json = this.#coder.encodeJson(method, params);
const id = this.#coder.getId();
const callback = (error?: Error | null, result?: any): void => {
error
? reject(error)
: resolve(result);
};
l.debug((): string[] => ['calling', method, json]);
this.#handlers[id] = {
callback,
method,
params,
subscription
};
if (this.isConnected && !isNull(this.#websocket)) {
this.#websocket.send(json);
} else {
this.#queued[id] = json;
}
} catch (error) {
reject(error);
}
});
}
/**
* @name subscribe
* @summary Allows subscribing to a specific event.
* @param {string} type Subscription type
* @param {string} method Subscription method
* @param {any[]} params Parameters
* @param {ProviderInterfaceCallback} callback Callback
* @return {Promise<number>} Promise resolving to the dd of the subscription you can use with [[unsubscribe]].
*
* @example
* <BR>
*
* ```javascript
* const provider = new WsProvider('ws://127.0.0.1:9944');
* const rpc = new Rpc(provider);
*
* rpc.state.subscribeStorage([[storage.system.account, <Address>]], (_, values) => {
* console.log(values)
* }).then((subscriptionId) => {
* console.log('balance changes subscription id: ', subscriptionId)
* })
* ```
*/
public async subscribe (type: string, method: string, params: any[], callback: ProviderInterfaceCallback): Promise<number | string> {
const id = await this.send(method, params, { callback, type }) as Promise<number | string>;
return id;
}
/**
* @summary Allows unsubscribing to subscriptions made with [[subscribe]].
*/
public async unsubscribe (type: string, method: string, id: number | string): Promise<boolean> {
const subscription = `${type}::${id}`;
// FIXME This now could happen with re-subscriptions. The issue is that with a re-sub
// the assigned id now does not match what the API user originally received. It has
// a slight complication in solving - since we cannot rely on the send id, but rather
// need to find the actual subscription id to map it
if (isUndefined(this.#subscriptions[subscription])) {
l.debug((): string => `Unable to find active subscription=${subscription}`);
return false;
}
delete this.#subscriptions[subscription];
const result = await this.send(method, [id]) as Promise<boolean>;
return result;
}
#emit = (type: ProviderInterfaceEmitted, ...args: any[]): void => {
this.#eventemitter.emit(type, ...args);
}
#onSocketClose = (event: CloseEvent): void => {
if (this.#autoConnectMs > 0) {
l.error(`disconnected from ${this.#endpoints[this.#endpointIndex]}: ${event.code}:: ${event.reason || getWSErrorString(event.code)}`);
}
this.#isConnected = false;
this.#emit('disconnected');
if (this.#autoConnectMs > 0) {
setTimeout((): void => {
this.connectWithRetry().catch(() => {
// does not throw
});
}, this.#autoConnectMs);
}
}
#onSocketError = (error: Event): void => {
l.debug((): any => ['socket error', error]);
this.#emit('error', error);
}
#onSocketMessage = (message: MessageEvent): void => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
l.debug(() => ['received', message.data]);
const response = JSON.parse(message.data as string) as JsonRpcResponse;
return isUndefined(response.method)
? this.#onSocketMessageResult(response)
: this.#onSocketMessageSubscribe(response);
}
#onSocketMessageResult = (response: JsonRpcResponse): void => {
const handler = this.#handlers[response.id];
if (!handler) {
l.debug((): string => `Unable to find handler for id=${response.id}`);
return;
}
try {
const { method, params, subscription } = handler;
const result = this.#coder.decodeResponse(response) as string;
// first send the result - in case of subs, we may have an update
// immediately if we have some queued results already
handler.callback(null, result);
if (subscription) {
const subId = `${subscription.type}::${result}`;
this.#subscriptions[subId] = {
...subscription,
method,
params
};
// if we have a result waiting for this subscription already
if (this.#waitingForId[subId]) {
this.#onSocketMessageSubscribe(this.#waitingForId[subId]);
}
}
} catch (error) {
handler.callback(error, undefined);
}
delete this.#handlers[response.id];
}
#onSocketMessageSubscribe = (response: JsonRpcResponse): void => {
const method = ALIASSES[response.method as string] || response.method || 'invalid';
const subId = `${method}::${response.params.subscription}`;
const handler = this.#subscriptions[subId];
if (!handler) {
// store the JSON, we could have out-of-order subid coming in
this.#waitingForId[subId] = response;
l.debug((): string => `Unable to find handler for subscription=${subId}`);
return;
}
// housekeeping
delete this.#waitingForId[subId];
try {
const result = this.#coder.decodeResponse(response);
handler.callback(null, result);
} catch (error) {
handler.callback(error, undefined);
}
}
#onSocketOpen = (): boolean => {
assert(!isNull(this.#websocket), 'WebSocket cannot be null in onOpen');
l.debug((): any[] => ['connected to', this.#endpoints[this.#endpointIndex]]);
this.#isConnected = true;
this.#emit('connected');
this.#sendQueue();
this.#resubscribe();
return true;
}
#resubscribe = (): void => {
const subscriptions = this.#subscriptions;
this.#subscriptions = {};
// eslint-disable-next-line @typescript-eslint/no-misused-promises
Object.keys(subscriptions).forEach(async (id): Promise<void> => {
const { callback, method, params, type } = subscriptions[id];
// only re-create subscriptions which are not in author (only area where
// transactions are created, i.e. submissions such as 'author_submitAndWatchExtrinsic'
// are not included (and will not be re-broadcast)
if (type.startsWith('author_')) {
return;
}
try {
await this.subscribe(type, method, params, callback);
} catch (error) {
l.error(error);
}
});
}
#sendQueue = (): void => {
Object.keys(this.#queued).forEach((id): void => {
try {
// we have done the websocket check in onSocketOpen, if an issue, will catch it
(this.#websocket as WebSocket).send(
this.#queued[id]
);
delete this.#queued[id];
} catch (error) {
l.error(error);
}
});
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
import { Mock } from './../mock/types';
import { mockWs, TEST_WS_URL } from '../../test/mockWs';
import WsProvider from './';
import { WsProvider } from './';
function sleepMs (ms = 0): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
+1 -1
View File
@@ -4,7 +4,7 @@
import { Mock } from './../mock/types';
import { mockWs, TEST_WS_URL } from '../../test/mockWs';
import WsProvider from './';
import { WsProvider } from './';
let ws: WsProvider;
let mock: Mock;
+464 -2
View File
@@ -1,6 +1,468 @@
// Copyright 2017-2020 @polkadot/rpc-provider authors & contributors
// SPDX-License-Identifier: Apache-2.0
import WsProvider from './Provider';
/* eslint-disable camelcase */
export default WsProvider;
import { JsonRpcResponse, ProviderInterface, ProviderInterfaceCallback, ProviderInterfaceEmitted, ProviderInterfaceEmitCb } from '../types';
import EventEmitter from 'eventemitter3';
import { assert, isChildClass, isNull, isUndefined, logger } from '@polkadot/util';
import WS from '@polkadot/x-ws';
import Coder from '../coder';
import defaults from '../defaults';
import { getWSErrorString } from './errors';
interface SubscriptionHandler {
callback: ProviderInterfaceCallback;
type: string;
}
interface WsStateAwaiting {
callback: ProviderInterfaceCallback;
method: string;
params: any[];
subscription?: SubscriptionHandler;
}
interface WsStateSubscription extends SubscriptionHandler {
method: string;
params: any[];
}
const ALIASSES: { [index: string]: string } = {
chain_finalisedHead: 'chain_finalizedHead',
chain_subscribeFinalisedHeads: 'chain_subscribeFinalizedHeads',
chain_unsubscribeFinalisedHeads: 'chain_unsubscribeFinalizedHeads'
};
const RETRY_DELAY = 1000;
const l = logger('api-ws');
/**
* # @polkadot/rpc-provider/ws
*
* @name WsProvider
*
* @description The WebSocket Provider allows sending requests using WebSocket to a WebSocket RPC server TCP port. Unlike the [[HttpProvider]], it does support subscriptions and allows listening to events such as new blocks or balance changes.
*
* @example
* <BR>
*
* ```javascript
* import Api from '@polkadot/api/promise';
* import { WsProvider } from '@polkadot/rpc-provider/ws';
*
* const provider = new WsProvider('ws://127.0.0.1:9944');
* const api = new Api(provider);
* ```
*
* @see [[HttpProvider]]
*/
export class WsProvider implements ProviderInterface {
readonly #coder: Coder;
readonly #endpoints: string[];
readonly #headers: Record<string, string>;
readonly #eventemitter: EventEmitter;
readonly #handlers: Record<string, WsStateAwaiting> = {};
readonly #queued: Record<string, string> = {};
readonly #waitingForId: Record<string, JsonRpcResponse> = {};
#autoConnectMs: number;
#endpointIndex: number;
#isConnected = false;
#subscriptions: Record<string, WsStateSubscription> = {};
#websocket: WebSocket | null;
/**
* @param {string | string[]} endpoint The endpoint url. Usually `ws://ip:9944` or `wss://ip:9944`, may provide an array of endpoint strings.
* @param {boolean} autoConnect Whether to connect automatically or not.
*/
constructor (endpoint: string | string[] = defaults.WS_URL, autoConnectMs: number | false = RETRY_DELAY, headers: Record<string, string> = {}) {
const endpoints = Array.isArray(endpoint)
? endpoint
: [endpoint];
assert(endpoints.length !== 0, 'WsProvider requires at least one Endpoint');
endpoints.forEach((endpoint) => {
assert(/^(wss|ws):\/\//.test(endpoint), `Endpoint should start with 'ws://', received '${endpoint}'`);
});
this.#eventemitter = new EventEmitter();
this.#autoConnectMs = autoConnectMs || 0;
this.#coder = new Coder();
this.#endpointIndex = -1;
this.#endpoints = endpoints;
this.#headers = headers;
this.#websocket = null;
if (autoConnectMs > 0) {
this.connectWithRetry().catch((): void => {
// does not throw
});
}
}
/**
* @summary `true` when this provider supports subscriptions
*/
public get hasSubscriptions (): boolean {
return true;
}
/**
* @summary Whether the node is connected or not.
* @return {boolean} true if connected
*/
public get isConnected (): boolean {
return this.#isConnected;
}
/**
* @description Returns a clone of the object
*/
public clone (): WsProvider {
return new WsProvider(this.#endpoints);
}
/**
* @summary Manually connect
* @description The [[WsProvider]] connects automatically by default, however if you decided otherwise, you may
* connect manually using this method.
*/
// eslint-disable-next-line @typescript-eslint/require-await
public async connect (): Promise<void> {
try {
this.#endpointIndex = (this.#endpointIndex + 1) % this.#endpoints.length;
this.#websocket = typeof WebSocket !== 'undefined' && isChildClass(WebSocket, WS)
? new WS(this.#endpoints[this.#endpointIndex])
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - WS may be an instance of w3cwebsocket, which supports headers
: new WS(this.#endpoints[this.#endpointIndex], undefined, undefined, this.#headers, undefined, {
// default: true
fragmentOutgoingMessages: true,
// default: 16K
fragmentationThreshold: 256 * 1024
});
this.#websocket.onclose = this.#onSocketClose;
this.#websocket.onerror = this.#onSocketError;
this.#websocket.onmessage = this.#onSocketMessage;
this.#websocket.onopen = this.#onSocketOpen;
} catch (error) {
l.error(error);
this.#emit('error', error);
throw error;
}
}
/**
* @description Connect, never throwing an error, but rather forcing a retry
*/
public async connectWithRetry (): Promise<void> {
try {
await this.connect();
} catch (error) {
setTimeout((): void => {
this.connectWithRetry().catch((): void => {
// does not throw
});
}, this.#autoConnectMs || RETRY_DELAY);
}
}
/**
* @description Manually disconnect from the connection, clearing autoconnect logic
*/
// eslint-disable-next-line @typescript-eslint/require-await
public async disconnect (): Promise<void> {
try {
assert(!isNull(this.#websocket), 'Cannot disconnect on a non-connected websocket');
// switch off autoConnect, we are in manual mode now
this.#autoConnectMs = 0;
// 1000 - Normal closure; the connection successfully completed
this.#websocket.close(1000);
this.#websocket = null;
} catch (error) {
l.error(error);
this.#emit('error', error);
throw error;
}
}
/**
* @summary Listens on events after having subscribed using the [[subscribe]] function.
* @param {ProviderInterfaceEmitted} type Event
* @param {ProviderInterfaceEmitCb} sub Callback
* @return unsubscribe function
*/
public on (type: ProviderInterfaceEmitted, sub: ProviderInterfaceEmitCb): () => void {
this.#eventemitter.on(type, sub);
return (): void => {
this.#eventemitter.removeListener(type, sub);
};
}
/**
* @summary Send JSON data using WebSockets to configured HTTP Endpoint or queue.
* @param method The RPC methods to execute
* @param params Encoded paramaters as appliucable for the method
* @param subscription Subscription details (internally used)
*/
public send (method: string, params: any[], subscription?: SubscriptionHandler): Promise<any> {
return new Promise((resolve, reject): void => {
try {
const json = this.#coder.encodeJson(method, params);
const id = this.#coder.getId();
const callback = (error?: Error | null, result?: any): void => {
error
? reject(error)
: resolve(result);
};
l.debug((): string[] => ['calling', method, json]);
this.#handlers[id] = {
callback,
method,
params,
subscription
};
if (this.isConnected && !isNull(this.#websocket)) {
this.#websocket.send(json);
} else {
this.#queued[id] = json;
}
} catch (error) {
reject(error);
}
});
}
/**
* @name subscribe
* @summary Allows subscribing to a specific event.
* @param {string} type Subscription type
* @param {string} method Subscription method
* @param {any[]} params Parameters
* @param {ProviderInterfaceCallback} callback Callback
* @return {Promise<number>} Promise resolving to the dd of the subscription you can use with [[unsubscribe]].
*
* @example
* <BR>
*
* ```javascript
* const provider = new WsProvider('ws://127.0.0.1:9944');
* const rpc = new Rpc(provider);
*
* rpc.state.subscribeStorage([[storage.system.account, <Address>]], (_, values) => {
* console.log(values)
* }).then((subscriptionId) => {
* console.log('balance changes subscription id: ', subscriptionId)
* })
* ```
*/
public async subscribe (type: string, method: string, params: any[], callback: ProviderInterfaceCallback): Promise<number | string> {
const id = await this.send(method, params, { callback, type }) as Promise<number | string>;
return id;
}
/**
* @summary Allows unsubscribing to subscriptions made with [[subscribe]].
*/
public async unsubscribe (type: string, method: string, id: number | string): Promise<boolean> {
const subscription = `${type}::${id}`;
// FIXME This now could happen with re-subscriptions. The issue is that with a re-sub
// the assigned id now does not match what the API user originally received. It has
// a slight complication in solving - since we cannot rely on the send id, but rather
// need to find the actual subscription id to map it
if (isUndefined(this.#subscriptions[subscription])) {
l.debug((): string => `Unable to find active subscription=${subscription}`);
return false;
}
delete this.#subscriptions[subscription];
const result = await this.send(method, [id]) as Promise<boolean>;
return result;
}
#emit = (type: ProviderInterfaceEmitted, ...args: any[]): void => {
this.#eventemitter.emit(type, ...args);
}
#onSocketClose = (event: CloseEvent): void => {
if (this.#autoConnectMs > 0) {
l.error(`disconnected from ${this.#endpoints[this.#endpointIndex]}: ${event.code}:: ${event.reason || getWSErrorString(event.code)}`);
}
this.#isConnected = false;
this.#emit('disconnected');
if (this.#autoConnectMs > 0) {
setTimeout((): void => {
this.connectWithRetry().catch(() => {
// does not throw
});
}, this.#autoConnectMs);
}
}
#onSocketError = (error: Event): void => {
l.debug((): any => ['socket error', error]);
this.#emit('error', error);
}
#onSocketMessage = (message: MessageEvent): void => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
l.debug(() => ['received', message.data]);
const response = JSON.parse(message.data as string) as JsonRpcResponse;
return isUndefined(response.method)
? this.#onSocketMessageResult(response)
: this.#onSocketMessageSubscribe(response);
}
#onSocketMessageResult = (response: JsonRpcResponse): void => {
const handler = this.#handlers[response.id];
if (!handler) {
l.debug((): string => `Unable to find handler for id=${response.id}`);
return;
}
try {
const { method, params, subscription } = handler;
const result = this.#coder.decodeResponse(response) as string;
// first send the result - in case of subs, we may have an update
// immediately if we have some queued results already
handler.callback(null, result);
if (subscription) {
const subId = `${subscription.type}::${result}`;
this.#subscriptions[subId] = {
...subscription,
method,
params
};
// if we have a result waiting for this subscription already
if (this.#waitingForId[subId]) {
this.#onSocketMessageSubscribe(this.#waitingForId[subId]);
}
}
} catch (error) {
handler.callback(error, undefined);
}
delete this.#handlers[response.id];
}
#onSocketMessageSubscribe = (response: JsonRpcResponse): void => {
const method = ALIASSES[response.method as string] || response.method || 'invalid';
const subId = `${method}::${response.params.subscription}`;
const handler = this.#subscriptions[subId];
if (!handler) {
// store the JSON, we could have out-of-order subid coming in
this.#waitingForId[subId] = response;
l.debug((): string => `Unable to find handler for subscription=${subId}`);
return;
}
// housekeeping
delete this.#waitingForId[subId];
try {
const result = this.#coder.decodeResponse(response);
handler.callback(null, result);
} catch (error) {
handler.callback(error, undefined);
}
}
#onSocketOpen = (): boolean => {
assert(!isNull(this.#websocket), 'WebSocket cannot be null in onOpen');
l.debug((): any[] => ['connected to', this.#endpoints[this.#endpointIndex]]);
this.#isConnected = true;
this.#emit('connected');
this.#sendQueue();
this.#resubscribe();
return true;
}
#resubscribe = (): void => {
const subscriptions = this.#subscriptions;
this.#subscriptions = {};
// eslint-disable-next-line @typescript-eslint/no-misused-promises
Object.keys(subscriptions).forEach(async (id): Promise<void> => {
const { callback, method, params, type } = subscriptions[id];
// only re-create subscriptions which are not in author (only area where
// transactions are created, i.e. submissions such as 'author_submitAndWatchExtrinsic'
// are not included (and will not be re-broadcast)
if (type.startsWith('author_')) {
return;
}
try {
await this.subscribe(type, method, params, callback);
} catch (error) {
l.error(error);
}
});
}
#sendQueue = (): void => {
Object.keys(this.#queued).forEach((id): void => {
try {
// we have done the websocket check in onSocketOpen, if an issue, will catch it
(this.#websocket as WebSocket).send(
this.#queued[id]
);
delete this.#queued[id];
} catch (error) {
l.error(error);
}
});
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
import { Mock } from './../mock/types';
import { mockWs, TEST_WS_URL } from '../../test/mockWs';
import WsProvider from './';
import { WsProvider } from './';
let ws: WsProvider;
let mock: Mock;
+1 -1
View File
@@ -6,7 +6,7 @@ import { Constructor } from '@polkadot/types/types';
import { Global, Mock } from './../mock/types';
import { mockWs, TEST_WS_URL } from '../../test/mockWs';
import WsProvider from './';
import { WsProvider } from './';
declare const global: Global;
+1 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2020 @polkadot/rpc-provider authors & contributors
// SPDX-License-Identifier: Apache-2.0
import WsProvider from './';
import { WsProvider } from './';
describe('state', (): void => {
it('requires an ws:// prefixed endpoint', (): void => {
@@ -6,7 +6,7 @@ import { Constructor } from '@polkadot/types/types';
import { Global, Mock } from './../mock/types';
import { mockWs, TEST_WS_URL } from '../../test/mockWs';
import WsProvider from './';
import { WsProvider } from './';
declare const global: Global;
@@ -6,7 +6,7 @@ import { Constructor } from '@polkadot/types/types';
import { Global, Mock } from './../mock/types';
import { mockWs, TEST_WS_URL } from '../../test/mockWs';
import WsProvider from './';
import { WsProvider } from './';
declare const global: Global;
+1 -1
View File
@@ -42,7 +42,7 @@
"@polkadot/metadata": "2.6.2-0",
"@polkadot/rpc-provider": "2.6.2-0",
"@polkadot/types": "2.6.2-0",
"@polkadot/util": "^4.0.1",
"@polkadot/util": "^4.0.2-5",
"handlebars": "^4.7.6",
"websocket": "^1.0.32",
"yargs": "^16.1.0"
+1 -1
View File
@@ -4,7 +4,7 @@
import Handlebars from 'handlebars';
import staticData from '@polkadot/metadata/static';
import Metadata from '@polkadot/metadata';
import { Metadata } from '@polkadot/metadata';
import { TypeRegistry } from '@polkadot/types/create';
import * as defaultDefs from '@polkadot/types/interfaces/definitions';
import { stringCamelCase } from '@polkadot/util';
+1 -1
View File
@@ -7,7 +7,7 @@ import { StorageEntryMetadataLatest } from '@polkadot/types/interfaces/metadata'
import { Registry } from '@polkadot/types/types';
import staticData from '@polkadot/metadata/static';
import Metadata from '@polkadot/metadata';
import { Metadata } from '@polkadot/metadata';
import * as defaultDefs from '@polkadot/types/interfaces/definitions';
import { unwrapStorageType } from '@polkadot/types/primitive/StorageKey';
import { TypeRegistry } from '@polkadot/types/create';
+1 -1
View File
@@ -6,7 +6,7 @@ import Handlebars from 'handlebars';
import { Registry } from '@polkadot/types/types';
import staticData from '@polkadot/metadata/static';
import Metadata from '@polkadot/metadata';
import { Metadata } from '@polkadot/metadata';
import * as defaultDefs from '@polkadot/types/interfaces/definitions';
import { Text } from '@polkadot/types/primitive';
import { TypeRegistry } from '@polkadot/types/create';
+1 -1
View File
@@ -5,7 +5,7 @@ import { MetadataLatest } from '@polkadot/types/interfaces/metadata';
import { Codec, DefinitionRpcParam } from '@polkadot/types/types';
import fs from 'fs';
import Metadata from '@polkadot/metadata';
import { Metadata } from '@polkadot/metadata';
import rpcdata from '@polkadot/metadata/static';
import Call from '@polkadot/types/generic/Call';
import { unwrapStorageType } from '@polkadot/types/primitive/StorageKey';
+1 -1
View File
@@ -30,7 +30,7 @@
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/types": "2.6.2-0",
"@polkadot/util": "^4.0.1",
"@polkadot/util": "^4.0.2-5",
"bn.js": "^5.1.3"
},
"devDependencies": {
+3 -3
View File
@@ -30,15 +30,15 @@
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/metadata": "2.6.2-0",
"@polkadot/util": "^4.0.1",
"@polkadot/util-crypto": "^4.0.1",
"@polkadot/util": "^4.0.2-5",
"@polkadot/util-crypto": "^4.0.2-5",
"@types/bn.js": "^4.11.6",
"bn.js": "^5.1.3",
"memoizee": "^0.4.14",
"rxjs": "^6.6.3"
},
"devDependencies": {
"@polkadot/keyring": "^4.0.1",
"@polkadot/keyring": "^4.0.2-5",
"@types/memoizee": "^0.4.4"
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ import BN from 'bn.js';
import { compactAddLength, compactFromU8a, compactStripLength, compactToU8a, isBigInt, isBn, isNumber, isString } from '@polkadot/util';
import { DEFAULT_BITLENGTH } from '@polkadot/util/compact/defaults';
import typeToConstructor from './utils/typeToConstructor';
import { typeToConstructor } from './utils';
import { UIntBitLength } from './AbstractInt';
export interface CompactEncodable extends Codec {
+1 -3
View File
@@ -7,9 +7,7 @@ import { AnyJson, Constructor, Codec, InterfaceTypes, Registry } from '../types'
import { isHex, hexToU8a, isObject, isU8a, logger, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
import Compact from './Compact';
import compareMap from './utils/compareMap';
import decodeU8a from './utils/decodeU8a';
import typeToConstructor from './utils/typeToConstructor';
import { compareMap, decodeU8a, typeToConstructor } from './utils';
const l = logger('Map');
+1 -1
View File
@@ -5,7 +5,7 @@ import { VoteThreshold } from '../interfaces/elections';
import { BlockNumber } from '../interfaces/runtime';
import { CodecTo } from '../types';
import Metadata from '@polkadot/metadata';
import { Metadata } from '@polkadot/metadata';
import rpcMetadata from '@polkadot/metadata/static';
import { TypeRegistry } from '../create';
+1 -1
View File
@@ -4,7 +4,7 @@
import { PropIndex } from '../interfaces/democracy';
import { Codec, CodecTo } from '../types';
import Metadata from '@polkadot/metadata';
import { Metadata } from '@polkadot/metadata';
import rpcMetadata from '@polkadot/metadata/static';
import { createTypeUnsafe, TypeRegistry } from '../create';
@@ -3,7 +3,7 @@
import { TypeRegistry } from '../../create';
import U32 from '../../primitive/U32';
import compareArray from './compareArray';
import { compareArray } from '.';
describe('compareArray', (): void => {
const registry = new TypeRegistry();
@@ -7,7 +7,7 @@ import { hasEq } from './util';
// NOTE These are used internally and when comparing objects, expects that
// when the second is an Codec[] that the first has to be as well
export default function compareArray (a: unknown[], b?: unknown): boolean {
export function compareArray (a: unknown[], b?: unknown): boolean {
if (Array.isArray(b)) {
return (a.length === b.length) && isUndefined(
a.find((value, index): boolean =>
@@ -4,7 +4,7 @@
import { Codec } from '../../types';
import { TypeRegistry } from '../../create';
import U32 from '../../primitive/U32';
import compareMap from './compareMap';
import { compareMap } from '.';
describe('compareMap', (): void => {
const registry = new TypeRegistry();
+1 -1
View File
@@ -26,7 +26,7 @@ function compareMapArray (a: Map<any, any>, b: [any, any][]): boolean {
// NOTE These are used internally and when comparing objects, expects that
// when the second is an Map<string, Codec> that the first has to be as well
export default function compareMap (a: Map<any, any>, b?: unknown): boolean {
export function compareMap (a: Map<any, any>, b?: unknown): boolean {
if (Array.isArray(b)) {
return compareMapArray(a, b);
} else if (b instanceof Map) {
+1 -1
View File
@@ -10,7 +10,7 @@ function compareSetArray (a: Set<unknown>, b: any[]): boolean {
// NOTE These are used internally and when comparing objects, expects that
// when the second is an Set<string, Codec> that the first has to be as well
export default function compareSet (a: Set<unknown>, b?: unknown): boolean {
export function compareSet (a: Set<unknown>, b?: unknown): boolean {
if (Array.isArray(b)) {
return compareSetArray(a, b);
} else if (b instanceof Set) {
+1 -1
View File
@@ -10,7 +10,7 @@ import { Codec, Constructor, Registry } from '../../types';
* @param u8a - The u8a to decode.
* @param types - The array of Constructor to decode the U8a against.
*/
export default function decodeU8a (registry: Registry, u8a: Uint8Array, _types: Constructor[] | { [index: string]: Constructor }): Codec[] {
export function decodeU8a (registry: Registry, u8a: Uint8Array, _types: Constructor[] | { [index: string]: Constructor }): Codec[] {
const types = Array.isArray(_types)
? _types
: Object.values(_types);
+6 -6
View File
@@ -1,11 +1,11 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as compareArray } from './compareArray';
export { default as compareMap } from './compareMap';
export { default as compareSet } from './compareSet';
export { default as decodeU8a } from './decodeU8a';
export { default as mapToTypeMap } from './mapToTypeMap';
export { default as typeToConstructor } from './typeToConstructor';
export { compareArray } from './compareArray';
export { compareMap } from './compareMap';
export { compareSet } from './compareSet';
export { decodeU8a } from './decodeU8a';
export { mapToTypeMap } from './mapToTypeMap';
export { typeToConstructor } from './typeToConstructor';
export * from './encodeTypes';
@@ -3,12 +3,12 @@
import { Constructor, InterfaceTypes, Registry } from '../../types';
import typeToConstructor from './typeToConstructor';
import { typeToConstructor } from './typeToConstructor';
/**
* @description takes an input map of the form `{ [string]: string | Constructor }` and returns a map of `{ [string]: Constructor }`
*/
export default function mapToTypeMap (registry: Registry, input: Record<string, keyof InterfaceTypes | Constructor>): Record<string, Constructor> {
export function mapToTypeMap (registry: Registry, input: Record<string, keyof InterfaceTypes | Constructor>): Record<string, Constructor> {
return Object
.entries(input)
.reduce((output: Record<string, Constructor>, [key, type]): Record<string, Constructor> => {

Some files were not shown because too many files have changed in this diff Show More