Adjust class privates via #, where applicable (#1921)
* Adjust class priates via #, where applicable * Remove stray log * Cleanup rpc-provider * Small adjustments * No private access in tests * Submittable privates * Use derive for nonce derivation * Tweak observers * Alphabetical privates
This commit is contained in:
+1
-1
@@ -26,7 +26,7 @@
|
||||
"@babel/core": "^7.8.4",
|
||||
"@babel/register": "^7.8.3",
|
||||
"@babel/runtime": "^7.8.4",
|
||||
"@polkadot/dev": "^0.40.22",
|
||||
"@polkadot/dev": "^0.41.1",
|
||||
"@polkadot/ts": "^0.2.3",
|
||||
"copyfiles": "^2.2.0"
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@ const _Header: Constructor<Header> = Struct.with(runtimeTypes.types.Header as an
|
||||
* A [[Block]] header with an additional `author` field that indicates the block author
|
||||
*/
|
||||
export default class HeaderExtended extends _Header {
|
||||
private _author?: AccountId;
|
||||
readonly #author?: AccountId;
|
||||
|
||||
constructor (registry: Registry, header?: Header, sessionValidators?: AccountId[]) {
|
||||
super(registry, header);
|
||||
|
||||
this._author = this.extractAuthor(sessionValidators);
|
||||
this.#author = this.extractAuthor(sessionValidators);
|
||||
}
|
||||
|
||||
private extractAuthor (sessionValidators: AccountId[] = []): AccountId | undefined {
|
||||
@@ -51,7 +51,7 @@ export default class HeaderExtended extends _Header {
|
||||
* @description Convenience method, returns the author for the block
|
||||
*/
|
||||
public get author (): AccountId | undefined {
|
||||
return this._author;
|
||||
return this.#author;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,12 +18,12 @@ const _ReferendumInfo: Constructor<ReferendumInfo> = Struct.with(democracyTypes.
|
||||
* A [[ReferendumInfo]] with an additional `index` field
|
||||
*/
|
||||
export default class ReferendumInfoExtended extends _ReferendumInfo {
|
||||
private _index: ReferendumIndex;
|
||||
readonly #index: ReferendumIndex;
|
||||
|
||||
constructor (registry: Registry, value: ReferendumInfo | ReferendumInfoExtended, index?: BN | number) {
|
||||
super(registry, value);
|
||||
|
||||
this._index = value instanceof ReferendumInfoExtended
|
||||
this.#index = value instanceof ReferendumInfoExtended
|
||||
? value.index
|
||||
: createType(registry, 'ReferendumIndex', index);
|
||||
}
|
||||
@@ -32,7 +32,7 @@ export default class ReferendumInfoExtended extends _ReferendumInfo {
|
||||
* @description Convenience getter, returns the referendumIndex
|
||||
*/
|
||||
public get index (): ReferendumIndex {
|
||||
return this._index;
|
||||
return this.#index;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,10 +7,10 @@ import { ApiInterfaceEvents } from '../types';
|
||||
import EventEmitter from 'eventemitter3';
|
||||
|
||||
export default class Events {
|
||||
private _eventemitter = new EventEmitter();
|
||||
#eventemitter = new EventEmitter();
|
||||
|
||||
protected emit (type: ApiInterfaceEvents, ...args: any[]): boolean {
|
||||
return this._eventemitter.emit(type, ...args);
|
||||
return this.#eventemitter.emit(type, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,7 +33,7 @@ export default class Events {
|
||||
* ```
|
||||
*/
|
||||
public on (type: ApiInterfaceEvents, handler: (...args: any[]) => any): this {
|
||||
this._eventemitter.on(type, handler);
|
||||
this.#eventemitter.on(type, handler);
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ export default class Events {
|
||||
* ```
|
||||
*/
|
||||
public off (type: ApiInterfaceEvents, handler: (...args: any[]) => any): this {
|
||||
this._eventemitter.removeListener(type, handler);
|
||||
this.#eventemitter.removeListener(type, handler);
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -85,7 +85,7 @@ export default class Events {
|
||||
* ```
|
||||
*/
|
||||
public once (type: ApiInterfaceEvents, handler: (...args: any[]) => any): this {
|
||||
this._eventemitter.once(type, handler);
|
||||
this.#eventemitter.once(type, handler);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ const KEEPALIVE_INTERVAL = 15000;
|
||||
const l = logger('api/init');
|
||||
|
||||
export default abstract class Init<ApiType extends ApiTypes> extends Decorate<ApiType> {
|
||||
private _healthTimer: NodeJS.Timeout | null = null;
|
||||
#healthTimer: NodeJS.Timeout | null = null;
|
||||
|
||||
private _updateSub?: Subscription;
|
||||
#updateSub?: Subscription;
|
||||
|
||||
constructor (options: ApiOptions, type: ApiTypes, decorateMethod: DecorateMethod<ApiType>) {
|
||||
super(options, type, decorateMethod);
|
||||
@@ -44,15 +44,15 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
|
||||
this._rx.queryMulti = this.decorateMulti(this.rxDecorateMethod);
|
||||
this._rx.signer = options.signer;
|
||||
|
||||
this._rpcCore.provider.on('disconnected', this._onProviderDisconnect);
|
||||
this._rpcCore.provider.on('error', this._onProviderError);
|
||||
this._rpcCore.provider.on('connected', this._onProviderConnect);
|
||||
this._rpcCore.provider.on('disconnected', this.#onProviderDisconnect);
|
||||
this._rpcCore.provider.on('error', this.#onProviderError);
|
||||
this._rpcCore.provider.on('connected', this.#onProviderConnect);
|
||||
|
||||
// If the provider was instantiated earlier, and has already emitted a
|
||||
// 'connected' event, then the `on('connected')` won't fire anymore. To
|
||||
// cater for this case, we call manually `this._onProviderConnect`.
|
||||
if (this._rpcCore.provider.isConnected()) {
|
||||
this._onProviderConnect();
|
||||
this.#onProviderConnect();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
|
||||
|
||||
this._genesisHash = genesisHash;
|
||||
|
||||
if (this._updateSub) {
|
||||
this._updateSub.unsubscribe();
|
||||
if (this.#updateSub) {
|
||||
this.#updateSub.unsubscribe();
|
||||
}
|
||||
|
||||
const { metadata = {} } = this._options;
|
||||
@@ -109,11 +109,11 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
|
||||
|
||||
// subscribe to metadata updates, inject the types on changes
|
||||
private subscribeUpdates (): void {
|
||||
if (this._updateSub) {
|
||||
if (this.#updateSub) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._updateSub = this._rpcCore.state.subscribeRuntimeVersion().pipe(
|
||||
this.#updateSub = this._rpcCore.state.subscribeRuntimeVersion().pipe(
|
||||
switchMap((version: RuntimeVersion) =>
|
||||
combineLatest(
|
||||
of(version),
|
||||
@@ -201,7 +201,7 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
|
||||
return true;
|
||||
}
|
||||
|
||||
private _onProviderConnect = async (): Promise<void> => {
|
||||
#onProviderConnect = async (): Promise<void> => {
|
||||
this.emit('connected');
|
||||
this._isConnected.next(true);
|
||||
|
||||
@@ -217,7 +217,7 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
|
||||
this.emit('ready', this);
|
||||
}
|
||||
|
||||
this._healthTimer = setInterval((): void => {
|
||||
this.#healthTimer = setInterval((): void => {
|
||||
this._rpcCore.system.health().toPromise().catch((): void => {
|
||||
// ignore
|
||||
});
|
||||
@@ -231,17 +231,17 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
|
||||
}
|
||||
}
|
||||
|
||||
private _onProviderDisconnect = (): void => {
|
||||
#onProviderDisconnect = (): void => {
|
||||
this.emit('disconnected');
|
||||
this._isConnected.next(false);
|
||||
|
||||
if (this._healthTimer) {
|
||||
clearInterval(this._healthTimer);
|
||||
this._healthTimer = null;
|
||||
if (this.#healthTimer) {
|
||||
clearInterval(this.#healthTimer);
|
||||
this.#healthTimer = null;
|
||||
}
|
||||
};
|
||||
|
||||
private _onProviderError = (error: Error): void => {
|
||||
#onProviderError = (error: Error): void => {
|
||||
this.emit('error', error);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,15 +22,21 @@ interface SignerRawOptions {
|
||||
signer?: Signer;
|
||||
}
|
||||
|
||||
let pkgJson: { name: string; version: string };
|
||||
|
||||
try {
|
||||
pkgJson = require('../package.json');
|
||||
} catch (error) {
|
||||
// development environment
|
||||
pkgJson = { name: '@polkadot/api', version: '-' };
|
||||
interface PkgJson {
|
||||
name: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
let pkgJson: PkgJson = { name: '@polkadot/api', version: '-' };
|
||||
|
||||
import('../package.json')
|
||||
.then((_pkgJson: any): void => {
|
||||
pkgJson = _pkgJson;
|
||||
})
|
||||
.catch((): void => {
|
||||
// ignore
|
||||
});
|
||||
|
||||
function assertResult<T> (value: T | undefined): T {
|
||||
assert(!isUndefined(value), 'Api needs to be initialized before using, listen on \'ready\'');
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import { detectPackage } from '@polkadot/util';
|
||||
|
||||
// FIXME This really should be `import(...).then(...)`, but need to check rejections
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
detectPackage(require('./package.json'), __dirname);
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ export function decorateMethod<Method extends AnyFunction> (method: Method, opti
|
||||
* ```
|
||||
*/
|
||||
export default class ApiPromise extends ApiBase<'promise'> {
|
||||
private _isReadyPromise: Promise<ApiPromise>;
|
||||
#isReadyPromise: Promise<ApiPromise>;
|
||||
|
||||
/**
|
||||
* @description Creates an ApiPromise instance using the supplied provider. Returns an Promise containing the actual Api instance.
|
||||
@@ -216,7 +216,7 @@ export default class ApiPromise extends ApiBase<'promise'> {
|
||||
constructor (options?: ApiOptions) {
|
||||
super(options, 'promise', decorateMethod);
|
||||
|
||||
this._isReadyPromise = new Promise((resolve, reject): void => {
|
||||
this.#isReadyPromise = new Promise((resolve, reject): void => {
|
||||
super.once('ready', (): void => {
|
||||
resolve(this);
|
||||
});
|
||||
@@ -230,7 +230,7 @@ export default class ApiPromise extends ApiBase<'promise'> {
|
||||
* @description Promise that returns the first time we are connected and loaded
|
||||
*/
|
||||
public get isReady (): Promise<ApiPromise> {
|
||||
return this._isReadyPromise;
|
||||
return this.#isReadyPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,31 +13,31 @@ export interface CombinatorFunction {
|
||||
}
|
||||
|
||||
export default class Combinator {
|
||||
protected _allHasFired = false;
|
||||
#allHasFired = false;
|
||||
|
||||
protected _callback: CombinatorCallback;
|
||||
#callback: CombinatorCallback;
|
||||
|
||||
protected _fired: boolean[] = [];
|
||||
#fired: boolean[] = [];
|
||||
|
||||
protected _fns: CombinatorFunction[] = [];
|
||||
#fns: CombinatorFunction[] = [];
|
||||
|
||||
protected _isActive = true;
|
||||
#isActive = true;
|
||||
|
||||
protected _results: any[] = [];
|
||||
#results: any[] = [];
|
||||
|
||||
protected _subscriptions: UnsubscribePromise[] = [];
|
||||
#subscriptions: UnsubscribePromise[] = [];
|
||||
|
||||
constructor (fns: (CombinatorFunction | [CombinatorFunction, ...any[]])[], callback: CombinatorCallback) {
|
||||
this._callback = callback;
|
||||
this.#callback = callback;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
this._subscriptions = fns.map(async (input, index): UnsubscribePromise => {
|
||||
this.#subscriptions = fns.map(async (input, index): UnsubscribePromise => {
|
||||
const [fn, ...args] = Array.isArray(input)
|
||||
? input
|
||||
: [input];
|
||||
|
||||
this._fired.push(false);
|
||||
this._fns.push(fn);
|
||||
this.#fired.push(false);
|
||||
this.#fns.push(fn);
|
||||
|
||||
// Not quite 100% how to have a variable number at the front here
|
||||
return (fn as Function)(...args, this.createCallback(index));
|
||||
@@ -45,43 +45,43 @@ export default class Combinator {
|
||||
}
|
||||
|
||||
protected allHasFired (): boolean {
|
||||
if (!this._allHasFired) {
|
||||
this._allHasFired = this._fired.filter((hasFired): boolean => !hasFired).length === 0;
|
||||
if (!this.#allHasFired) {
|
||||
this.#allHasFired = this.#fired.filter((hasFired): boolean => !hasFired).length === 0;
|
||||
}
|
||||
|
||||
return this._allHasFired;
|
||||
return this.#allHasFired;
|
||||
}
|
||||
|
||||
protected createCallback (index: number): (value: any) => void {
|
||||
return (value: any): void => {
|
||||
this._fired[index] = true;
|
||||
this._results[index] = value;
|
||||
this.#fired[index] = true;
|
||||
this.#results[index] = value;
|
||||
|
||||
this.triggerUpdate();
|
||||
};
|
||||
}
|
||||
|
||||
protected triggerUpdate (): void {
|
||||
if (!this._isActive || !isFunction(this._callback) || !this.allHasFired()) {
|
||||
if (!this.#isActive || !isFunction(this.#callback) || !this.allHasFired()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this._callback(this._results);
|
||||
this.#callback(this.#results);
|
||||
} catch (error) {
|
||||
// swallow, we don't want the handler to trip us up
|
||||
}
|
||||
}
|
||||
|
||||
public unsubscribe (): void {
|
||||
if (!this._isActive) {
|
||||
if (!this.#isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._isActive = false;
|
||||
this.#isActive = false;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
this._subscriptions.forEach(async (subscription): Promise<void> => {
|
||||
this.#subscriptions.forEach(async (subscription): Promise<void> => {
|
||||
try {
|
||||
const unsubscribe = await subscription;
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ export function decorateMethod <Method extends AnyFunction> (method: Method): Me
|
||||
* ```
|
||||
*/
|
||||
export default class ApiRx extends ApiBase<'rxjs'> {
|
||||
private _isReadyRx: Observable<ApiRx>;
|
||||
#isReadyRx: Observable<ApiRx>;
|
||||
|
||||
/**
|
||||
* @description Creates an ApiRx instance using the supplied provider. Returns an Observable containing the actual Api instance.
|
||||
@@ -163,7 +163,7 @@ export default class ApiRx extends ApiBase<'rxjs'> {
|
||||
constructor (options?: ApiOptions) {
|
||||
super(options, 'rxjs', decorateMethod);
|
||||
|
||||
this._isReadyRx = from(
|
||||
this.#isReadyRx = from(
|
||||
// You can create an observable from an event, however my mind groks this form better
|
||||
new Promise((resolve): void => {
|
||||
super.on('ready', (): void => {
|
||||
@@ -184,7 +184,7 @@ export default class ApiRx extends ApiBase<'rxjs'> {
|
||||
* @description Observable that returns the first time we are connected and loaded
|
||||
*/
|
||||
public get isReady (): Observable<ApiRx> {
|
||||
return this._isReadyRx;
|
||||
return this.#isReadyRx;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountData, Address, Call, ExtrinsicEra, ExtrinsicStatus, Hash, Header, Index, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
|
||||
import { Callback, Codec, Constructor, IKeyringPair, ITuple, Registry, SignatureOptions, ISubmittableResult } from '@polkadot/types/types';
|
||||
import { Address, Call, ExtrinsicEra, ExtrinsicStatus, Hash, Header, Index, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
|
||||
import { Callback, Codec, Constructor, IKeyringPair, Registry, SignatureOptions, ISubmittableResult } from '@polkadot/types/types';
|
||||
import { ApiInterfaceRx, ApiTypes, SignerResult } from '../types';
|
||||
import { AddressOrPair, SignerOptions, SubmittableExtrinsic, SubmittablePaymentResult, SubmittableResultResult, SubmittableResultSubscription, SubmittableThis } from './types';
|
||||
|
||||
@@ -35,38 +35,32 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
|
||||
const Extrinsic = ClassOf(api.registry, 'Extrinsic');
|
||||
|
||||
return class Submittable extends Extrinsic implements SubmittableExtrinsic<ApiType> {
|
||||
private readonly _api: ApiInterfaceRx;
|
||||
|
||||
private readonly _decorateMethod: ApiBase<ApiType>['decorateMethod'];
|
||||
|
||||
private readonly _ignoreStatusCb: boolean;
|
||||
readonly #ignoreStatusCb: boolean;
|
||||
|
||||
constructor (registry: Registry, extrinsic: Call | Uint8Array | string) {
|
||||
super(registry, extrinsic, { version: api.extrinsicType });
|
||||
|
||||
this._api = api;
|
||||
this._decorateMethod = decorateMethod;
|
||||
this._ignoreStatusCb = apiType === 'rxjs';
|
||||
this.#ignoreStatusCb = apiType === 'rxjs';
|
||||
}
|
||||
|
||||
// calculate the payment info for this transaction (if signed and submitted)
|
||||
public paymentInfo (account: AddressOrPair, options?: Partial<SignerOptions>): SubmittablePaymentResult<ApiType> {
|
||||
const [allOptions] = this._makeSignAndSendOptions(options);
|
||||
const [allOptions] = this.#makeSignAndSendOptions(options);
|
||||
const address = isKeyringPair(account) ? account.address : account.toString();
|
||||
|
||||
return this._decorateMethod(
|
||||
return decorateMethod(
|
||||
(): Observable<RuntimeDispatchInfo> =>
|
||||
this._getPrelimState(address, allOptions).pipe(
|
||||
this.#getPrelimState(address, allOptions).pipe(
|
||||
first(),
|
||||
switchMap(([nonce, header]): Observable<RuntimeDispatchInfo> => {
|
||||
// setup our options (same way as in signAndSend)
|
||||
const eraOptions = this._makeEraOptions(allOptions, { header, nonce });
|
||||
const signOptions = this._makeSignOptions(eraOptions, {});
|
||||
const eraOptions = this.#makeEraOptions(allOptions, { header, nonce });
|
||||
const signOptions = this.#makeSignOptions(eraOptions, {});
|
||||
|
||||
// add a fake signature to the extrinsic
|
||||
this.signFake(address, signOptions);
|
||||
|
||||
return this._api.rpc.payment.queryInfo(this.toHex());
|
||||
return api.rpc.payment.queryInfo(this.toHex());
|
||||
})
|
||||
)
|
||||
)();
|
||||
@@ -74,7 +68,7 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
|
||||
|
||||
// sign a transaction, returning the this to allow chaining, i.e. .sign(...).send()
|
||||
public sign (account: IKeyringPair, optionsOrNonce: Partial<SignerOptions>): this {
|
||||
super.sign(account, this._makeSignOptions(this._optionsOrNonce(optionsOrNonce), {}));
|
||||
super.sign(account, this.#makeSignOptions(this.#optionsOrNonce(optionsOrNonce), {}));
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -83,9 +77,9 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
|
||||
//
|
||||
// also supports signing through external signers
|
||||
public signAsync (account: AddressOrPair, optionsOrNonce: Partial<SignerOptions>): SubmittableThis<ApiType, this> {
|
||||
return this._decorateMethod(
|
||||
return decorateMethod(
|
||||
(): Observable<this> =>
|
||||
this._signObservable(account, optionsOrNonce).pipe(mapTo(this))
|
||||
this.#observeSign(account, optionsOrNonce).pipe(mapTo(this))
|
||||
)();
|
||||
}
|
||||
|
||||
@@ -100,16 +94,16 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
|
||||
|
||||
// signAndSend implementation for all 3 cases above
|
||||
public signAndSend (account: AddressOrPair, optionsOrStatus?: Partial<SignerOptions> | Callback<ISubmittableResult>, optionalStatusCb?: Callback<ISubmittableResult>): SubmittableResultResult<ApiType> | SubmittableResultSubscription<ApiType> {
|
||||
const [options, statusCb] = this._makeSignAndSendOptions(optionsOrStatus, optionalStatusCb);
|
||||
const isSubscription = this._api.hasSubscriptions && (this._ignoreStatusCb || !!statusCb);
|
||||
const [options, statusCb] = this.#makeSignAndSendOptions(optionsOrStatus, optionalStatusCb);
|
||||
const isSubscription = api.hasSubscriptions && (this.#ignoreStatusCb || !!statusCb);
|
||||
|
||||
return this._decorateMethod(
|
||||
return decorateMethod(
|
||||
(): Observable<Codec> => (
|
||||
this._signObservable(account, options).pipe(
|
||||
this.#observeSign(account, options).pipe(
|
||||
switchMap((updateId: number | undefined): Observable<ISubmittableResult> | Observable<Hash> =>
|
||||
isSubscription
|
||||
? this._subscribeObservable(updateId)
|
||||
: this._sendObservable(updateId)
|
||||
? this.#observeSubscribe(updateId)
|
||||
: this.#observeSend(updateId)
|
||||
)
|
||||
) as Observable<Codec>) // FIXME This is wrong, SubmittableResult is _not_ a codec
|
||||
)(statusCb);
|
||||
@@ -123,16 +117,65 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
|
||||
|
||||
// send implementation for both immediate Hash and statusCb variants
|
||||
public send (statusCb?: Callback<ISubmittableResult>): SubmittableResultResult<ApiType> | SubmittableResultSubscription<ApiType> {
|
||||
const isSubscription = this._api.hasSubscriptions && (this._ignoreStatusCb || !!statusCb);
|
||||
const isSubscription = api.hasSubscriptions && (this.#ignoreStatusCb || !!statusCb);
|
||||
|
||||
return this._decorateMethod(
|
||||
return decorateMethod(
|
||||
isSubscription
|
||||
? this._subscribeObservable
|
||||
: this._sendObservable
|
||||
? this.#observeSubscribe
|
||||
: this.#observeSend
|
||||
)(statusCb);
|
||||
}
|
||||
|
||||
private _makeSignAndSendOptions (optionsOrStatus?: Partial<SignerOptions> | Callback<ISubmittableResult>, statusCb?: Callback<ISubmittableResult>): [Partial<SignerOptions>, Callback<ISubmittableResult>?] {
|
||||
#getPrelimState = (address: string, options: Partial<SignerOptions>): Observable<[Index, Header | null]> => {
|
||||
return combineLatest([
|
||||
// if we have a nonce already, don't retrieve the latest, use what is there
|
||||
isUndefined(options.nonce)
|
||||
? api.derive.balances.account(address).pipe(
|
||||
map(({ accountNonce }): Index => accountNonce)
|
||||
)
|
||||
: of(createType(this.registry, 'Index', options.nonce)),
|
||||
// if we have an era provided already or eraLength is <= 0 (immortal)
|
||||
// don't get the latest block, just pass null, handle in mergeMap
|
||||
(isUndefined(options.era) || (isNumber(options.era) && options.era > 0))
|
||||
? api.rpc.chain.getHeader()
|
||||
: of(null)
|
||||
]);
|
||||
}
|
||||
|
||||
#makeEraOptions = (options: Partial<SignerOptions>, { header, nonce }: { header: Header | null; nonce: Index }): SignatureOptions => {
|
||||
if (!header) {
|
||||
if (isNumber(options.era)) {
|
||||
// since we have no header, it is immortal, remove any option overrides
|
||||
// so we only supply the genesisHash and no era to the construction
|
||||
delete options.era;
|
||||
delete options.blockHash;
|
||||
}
|
||||
|
||||
return this.#makeSignOptions(options, { nonce });
|
||||
}
|
||||
|
||||
return this.#makeSignOptions(options, {
|
||||
blockHash: header.hash,
|
||||
era: createType(this.registry, 'ExtrinsicEra', {
|
||||
current: header.number,
|
||||
period: options.era || DEFAULT_MORTAL_LENGTH
|
||||
}),
|
||||
nonce
|
||||
});
|
||||
}
|
||||
|
||||
#makeSignOptions = (options: Partial<SignerOptions>, extras: { blockHash?: Hash; era?: ExtrinsicEra; nonce?: Index }): SignatureOptions => {
|
||||
return {
|
||||
blockHash: api.genesisHash,
|
||||
...options,
|
||||
...extras,
|
||||
genesisHash: api.genesisHash,
|
||||
runtimeVersion: api.runtimeVersion,
|
||||
version: api.extrinsicType
|
||||
} as SignatureOptions;
|
||||
}
|
||||
|
||||
#makeSignAndSendOptions = (optionsOrStatus?: Partial<SignerOptions> | Callback<ISubmittableResult>, statusCb?: Callback<ISubmittableResult>): [Partial<SignerOptions>, Callback<ISubmittableResult>?] => {
|
||||
let options: Partial<SignerOptions> = {};
|
||||
|
||||
if (isFunction(optionsOrStatus)) {
|
||||
@@ -144,28 +187,81 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
|
||||
return [options, statusCb];
|
||||
}
|
||||
|
||||
private _signObservable (account: AddressOrPair, optionsOrNonce: Partial<SignerOptions>): Observable<number | undefined> {
|
||||
#observeSign = (account: AddressOrPair, optionsOrNonce: Partial<SignerOptions>): Observable<number | undefined> => {
|
||||
const address = isKeyringPair(account) ? account.address : account.toString();
|
||||
const options = this._optionsOrNonce(optionsOrNonce);
|
||||
const options = this.#optionsOrNonce(optionsOrNonce);
|
||||
let updateId: number | undefined;
|
||||
|
||||
return this._getPrelimState(address, options).pipe(
|
||||
return this.#getPrelimState(address, options).pipe(
|
||||
first(),
|
||||
mergeMap(async ([nonce, header]): Promise<void> => {
|
||||
const eraOptions = this._makeEraOptions(options, { header, nonce });
|
||||
const eraOptions = this.#makeEraOptions(options, { header, nonce });
|
||||
|
||||
if (isKeyringPair(account)) {
|
||||
this.sign(account, eraOptions);
|
||||
} else {
|
||||
updateId = await this._signViaSigner(address, eraOptions, header);
|
||||
updateId = await this.#signViaSigner(address, eraOptions, header);
|
||||
}
|
||||
}),
|
||||
mapTo(updateId)
|
||||
);
|
||||
}
|
||||
|
||||
private async _signViaSigner (address: Address | string | Uint8Array, options: SignatureOptions, header: Header | null): Promise<number> {
|
||||
const signer = options.signer || this._api.signer;
|
||||
#observeStatus = (status: ExtrinsicStatus): Observable<ISubmittableResult> => {
|
||||
if (!status.isFinalized && !status.isInBlock) {
|
||||
return of(new SubmittableResult({ status }));
|
||||
}
|
||||
|
||||
const blockHash = status.isInBlock
|
||||
? status.asInBlock
|
||||
: status.asFinalized;
|
||||
|
||||
return combineLatest([
|
||||
api.rpc.chain.getBlock(blockHash),
|
||||
api.query.system.events.at(blockHash)
|
||||
]).pipe(
|
||||
map(([signedBlock, allEvents]): ISubmittableResult =>
|
||||
new SubmittableResult({
|
||||
events: filterEvents(this.hash, signedBlock, allEvents),
|
||||
status
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#observeSend = (updateId = -1): Observable<Hash> => {
|
||||
return api.rpc.author
|
||||
.submitExtrinsic(this)
|
||||
.pipe(
|
||||
tap((hash): void => {
|
||||
this.#updateSigner(updateId, hash);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#observeSubscribe = (updateId = -1): Observable<ISubmittableResult> => {
|
||||
return api.rpc.author
|
||||
.submitAndWatchExtrinsic(this)
|
||||
.pipe(
|
||||
switchMap((status): Observable<ISubmittableResult> =>
|
||||
this.#observeStatus(status)
|
||||
),
|
||||
tap((status): void => {
|
||||
this.#updateSigner(updateId, status);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// NOTE here we actually override nonce if it was specified (backwards compat for
|
||||
// the previous signature - don't let userspace break, but allow then time to upgrade)
|
||||
#optionsOrNonce = (optionsOrNonce: Partial<SignerOptions>): Partial<SignerOptions> => {
|
||||
return isBn(optionsOrNonce) || isNumber(optionsOrNonce)
|
||||
? { nonce: optionsOrNonce }
|
||||
: optionsOrNonce;
|
||||
}
|
||||
|
||||
#signViaSigner = async (address: Address | string | Uint8Array, options: SignatureOptions, header: Header | null): Promise<number> => {
|
||||
const signer = options.signer || api.signer;
|
||||
|
||||
assert(signer, 'No signer specified, either via api.setSigner or via sign options');
|
||||
|
||||
@@ -193,119 +289,10 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
|
||||
return result.id;
|
||||
}
|
||||
|
||||
private _makeSignOptions (options: Partial<SignerOptions>, extras: { blockHash?: Hash; era?: ExtrinsicEra; nonce?: Index }): SignatureOptions {
|
||||
return {
|
||||
blockHash: this._api.genesisHash,
|
||||
...options,
|
||||
...extras,
|
||||
genesisHash: this._api.genesisHash,
|
||||
runtimeVersion: this._api.runtimeVersion,
|
||||
version: this._api.extrinsicType
|
||||
} as SignatureOptions;
|
||||
}
|
||||
|
||||
private _makeEraOptions (options: Partial<SignerOptions>, { header, nonce }: { header: Header | null; nonce: Index }): SignatureOptions {
|
||||
if (!header) {
|
||||
if (isNumber(options.era)) {
|
||||
// since we have no header, it is immortal, remove any option overrides
|
||||
// so we only supply the genesisHash and no era to the construction
|
||||
delete options.era;
|
||||
delete options.blockHash;
|
||||
}
|
||||
|
||||
return this._makeSignOptions(options, { nonce });
|
||||
#updateSigner = (updateId: number, status: Hash | ISubmittableResult): void => {
|
||||
if ((updateId !== -1) && api.signer && api.signer.update) {
|
||||
api.signer.update(updateId, status);
|
||||
}
|
||||
|
||||
return this._makeSignOptions(options, {
|
||||
blockHash: header.hash,
|
||||
era: createType(this.registry, 'ExtrinsicEra', {
|
||||
current: header.number,
|
||||
period: options.era || DEFAULT_MORTAL_LENGTH
|
||||
}),
|
||||
nonce
|
||||
});
|
||||
}
|
||||
|
||||
private _getPrelimState (address: string, options: Partial<SignerOptions>): Observable<[Index, Header | null]> {
|
||||
return combineLatest([
|
||||
// if we have a nonce already, don't retrieve the latest, use what is there
|
||||
isUndefined(options.nonce)
|
||||
// FIXME This apparently is having issues on latest Kusama for nonce retrieval,
|
||||
// hence we are using the accountNonce only
|
||||
// ? this._api.rpc.account.nextIndex
|
||||
// ? this._api.rpc.account.nextIndex(address)
|
||||
// : this._api.query.system.accountNonce(address)
|
||||
? this._api.query.system.account
|
||||
? this._api.query.system.account<ITuple<[Index, AccountData]>>(address).pipe(
|
||||
map(([nonce]): Index => nonce)
|
||||
)
|
||||
: this._api.query.system.accountNonce<Index>(address)
|
||||
: of(createType(this.registry, 'Index', options.nonce)),
|
||||
// if we have an era provided already or eraLength is <= 0 (immortal)
|
||||
// don't get the latest block, just pass null, handle in mergeMap
|
||||
(isUndefined(options.era) || (isNumber(options.era) && options.era > 0))
|
||||
? this._api.rpc.chain.getHeader()
|
||||
: of(null)
|
||||
]);
|
||||
}
|
||||
|
||||
private _updateSigner (updateId: number, status: Hash | ISubmittableResult): void {
|
||||
if ((updateId !== -1) && this._api.signer && this._api.signer.update) {
|
||||
this._api.signer.update(updateId, status);
|
||||
}
|
||||
}
|
||||
|
||||
private _statusObservable (status: ExtrinsicStatus): Observable<ISubmittableResult> {
|
||||
if (!status.isFinalized && !status.isInBlock) {
|
||||
return of(new SubmittableResult({ status }));
|
||||
}
|
||||
|
||||
const blockHash = status.isInBlock
|
||||
? status.asInBlock
|
||||
: status.asFinalized;
|
||||
|
||||
return combineLatest([
|
||||
this._api.rpc.chain.getBlock(blockHash),
|
||||
this._api.query.system.events.at(blockHash)
|
||||
]).pipe(
|
||||
map(([signedBlock, allEvents]): ISubmittableResult =>
|
||||
new SubmittableResult({
|
||||
events: filterEvents(this.hash, signedBlock, allEvents),
|
||||
status
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private _sendObservable = (updateId = -1): Observable<Hash> => {
|
||||
return this._api.rpc.author
|
||||
.submitExtrinsic(this)
|
||||
.pipe(
|
||||
tap((hash): void => {
|
||||
this._updateSigner(updateId, hash);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private _subscribeObservable = (updateId = -1): Observable<ISubmittableResult> => {
|
||||
return this._api.rpc.author
|
||||
.submitAndWatchExtrinsic(this)
|
||||
.pipe(
|
||||
switchMap((status): Observable<ISubmittableResult> =>
|
||||
this._statusObservable(status)
|
||||
),
|
||||
tap((status): void => {
|
||||
this._updateSigner(updateId, status);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// NOTE here we actually override nonce if it was specified (backwards compat for
|
||||
// the previous signature - don't let userspace break, but allow then time to upgrade)
|
||||
private _optionsOrNonce = (optionsOrNonce: Partial<SignerOptions>): Partial<SignerOptions> => {
|
||||
return isBn(optionsOrNonce) || isNumber(optionsOrNonce)
|
||||
? { nonce: optionsOrNonce }
|
||||
: optionsOrNonce;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ type MetaAsX = 'asV0' | 'asV1' | 'asV2' | 'asV3' | 'asV4' | 'asV5' | 'asV6' | 'a
|
||||
* The versioned runtime metadata as a decoded structure
|
||||
*/
|
||||
export default class MetadataVersioned extends Struct {
|
||||
private _converted: Map<number, MetaMapped> = new Map();
|
||||
readonly #converted: Map<number, MetaMapped> = new Map();
|
||||
|
||||
constructor (registry: Registry, value?: any) {
|
||||
super(registry, {
|
||||
@@ -59,11 +59,11 @@ export default class MetadataVersioned extends Struct {
|
||||
return this.metadata[asCurr] as T;
|
||||
}
|
||||
|
||||
if (!this._converted.has(version)) {
|
||||
this._converted.set(version, fromPrev(this.registry, this[asPrev] as F));
|
||||
if (!this.#converted.has(version)) {
|
||||
this.#converted.set(version, fromPrev(this.registry, this[asPrev] as F));
|
||||
}
|
||||
|
||||
return this._converted.get(version) as T;
|
||||
return this.#converted.get(version) as T;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,7 +65,7 @@ function createErrorMessage ({ method, params, type }: RpcMethod, error: Error):
|
||||
* ```
|
||||
*/
|
||||
export default class Rpc implements RpcInterface {
|
||||
private _storageCache = new Map<string, string | null>();
|
||||
readonly #storageCache = new Map<string, string | null>();
|
||||
|
||||
public readonly mapping: Map<string, RpcMethod> = new Map();
|
||||
|
||||
@@ -396,7 +396,7 @@ export default class Rpc implements RpcInterface {
|
||||
// - if a single result value, don't fill - it is not an update hole
|
||||
// - fallback to an empty option in all cases
|
||||
const value = isUndefined(found)
|
||||
? (witCache && this._storageCache.get(hexKey)) || null
|
||||
? (witCache && this.#storageCache.get(hexKey)) || null
|
||||
: found[1];
|
||||
const isEmpty = isNull(value);
|
||||
const input = isEmpty || this.treatAsHex(key)
|
||||
@@ -406,7 +406,7 @@ export default class Rpc implements RpcInterface {
|
||||
// store the retrieved result - the only issue with this cache is that there is no
|
||||
// clearing of it, so very long running processes (not just a couple of hours, longer)
|
||||
// will increase memory beyond what is allowed.
|
||||
this._storageCache.set(hexKey, value);
|
||||
this.#storageCache.set(hexKey, value);
|
||||
|
||||
if (meta.modifier.isOptional) {
|
||||
return new Option(
|
||||
|
||||
@@ -8,7 +8,7 @@ import { assert, isUndefined, isNumber, isString } from '@polkadot/util';
|
||||
|
||||
/** @internal */
|
||||
export default class RpcCoder {
|
||||
private id = 0;
|
||||
#id = 0;
|
||||
|
||||
public decodeResponse (response: JsonRpcResponse): any {
|
||||
assert(response, 'Empty response object received');
|
||||
@@ -39,7 +39,7 @@ export default class RpcCoder {
|
||||
|
||||
public encodeObject (method: string, params: any | any[]): JsonRpcRequest {
|
||||
return {
|
||||
id: ++this.id,
|
||||
id: ++this.#id,
|
||||
jsonrpc: '2.0',
|
||||
method,
|
||||
params
|
||||
@@ -47,7 +47,7 @@ export default class RpcCoder {
|
||||
}
|
||||
|
||||
public getId (): number {
|
||||
return this.id;
|
||||
return this.#id;
|
||||
}
|
||||
|
||||
private checkError (error?: JsonRpcResponseBaseError): void {
|
||||
|
||||
@@ -36,9 +36,9 @@ const l = logger('api-http');
|
||||
* @see [[WsProvider]]
|
||||
*/
|
||||
export default class HttpProvider implements ProviderInterface {
|
||||
private coder: Coder;
|
||||
readonly #coder: Coder;
|
||||
|
||||
private endpoint: string;
|
||||
readonly #endpoint: string;
|
||||
|
||||
/**
|
||||
* @param {string} endpoint The endpoint url starting with http://
|
||||
@@ -46,8 +46,8 @@ export default class HttpProvider implements ProviderInterface {
|
||||
constructor (endpoint: string = defaults.HTTP_URL) {
|
||||
assert(/^(https|http):\/\//.test(endpoint), `Endpoint should start with 'http://', received '${endpoint}'`);
|
||||
|
||||
this.coder = new Coder();
|
||||
this.endpoint = endpoint;
|
||||
this.#coder = new Coder();
|
||||
this.#endpoint = endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,8 +95,8 @@ export default class HttpProvider implements ProviderInterface {
|
||||
* @summary Send HTTP POST Request with Body to configured HTTP Endpoint.
|
||||
*/
|
||||
public async send (method: string, params: any[]): Promise<any> {
|
||||
const body = this.coder.encodeJson(method, params);
|
||||
const response = await fetch(this.endpoint, {
|
||||
const body = this.#coder.encodeJson(method, params);
|
||||
const response = await fetch(this.#endpoint, {
|
||||
body,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
@@ -110,7 +110,7 @@ export default class HttpProvider implements ProviderInterface {
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
return this.coder.decodeResponse(result);
|
||||
return this.#coder.decodeResponse(result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,25 +65,25 @@ const l = logger('api-ws');
|
||||
* @see [[HttpProvider]]
|
||||
*/
|
||||
export default class WsProvider implements WSProviderInterface {
|
||||
private _eventemitter: EventEmitter;
|
||||
readonly #coder: Coder;
|
||||
|
||||
private _isConnected = false;
|
||||
readonly #endpoint: string;
|
||||
|
||||
private autoConnect: boolean;
|
||||
readonly #eventemitter: EventEmitter;
|
||||
|
||||
private coder: Coder;
|
||||
readonly #handlers: Record<string, WsStateAwaiting> = {};
|
||||
|
||||
private endpoint: string;
|
||||
readonly #queued: Record<string, string> = {};
|
||||
|
||||
private handlers: Record<string, WsStateAwaiting>;
|
||||
readonly #waitingForId: Record<string, JsonRpcResponse> = {};
|
||||
|
||||
private queued: Record<string, string>;
|
||||
#autoConnect: boolean;
|
||||
|
||||
private subscriptions: Record<string, WsStateSubscription>;
|
||||
#isConnected = false;
|
||||
|
||||
private waitingForId: Record<string, JsonRpcResponse>;
|
||||
#subscriptions: Record<string, WsStateSubscription> = {};
|
||||
|
||||
private websocket: WebSocket | null;
|
||||
#websocket: WebSocket | null;
|
||||
|
||||
/**
|
||||
* @param {string} endpoint The endpoint url. Usually `ws://ip:9944` or `wss://ip:9944`
|
||||
@@ -92,15 +92,11 @@ export default class WsProvider implements WSProviderInterface {
|
||||
constructor (endpoint: string = defaults.WS_URL, autoConnect = true) {
|
||||
assert(/^(wss|ws):\/\//.test(endpoint), `Endpoint should start with 'ws://', received '${endpoint}'`);
|
||||
|
||||
this._eventemitter = new EventEmitter();
|
||||
this.autoConnect = autoConnect;
|
||||
this.coder = new Coder();
|
||||
this.endpoint = endpoint;
|
||||
this.handlers = {};
|
||||
this.queued = {};
|
||||
this.subscriptions = {};
|
||||
this.waitingForId = {};
|
||||
this.websocket = null;
|
||||
this.#eventemitter = new EventEmitter();
|
||||
this.#autoConnect = autoConnect;
|
||||
this.#coder = new Coder();
|
||||
this.#endpoint = endpoint;
|
||||
this.#websocket = null;
|
||||
|
||||
if (autoConnect) {
|
||||
this.connect();
|
||||
@@ -118,7 +114,7 @@ export default class WsProvider implements WSProviderInterface {
|
||||
* @description Returns a clone of the object
|
||||
*/
|
||||
public clone (): WsProvider {
|
||||
return new WsProvider(this.endpoint);
|
||||
return new WsProvider(this.#endpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,12 +124,11 @@ export default class WsProvider implements WSProviderInterface {
|
||||
*/
|
||||
public connect (): void {
|
||||
try {
|
||||
this.websocket = new WebSocket(this.endpoint);
|
||||
|
||||
this.websocket.onclose = this.onSocketClose;
|
||||
this.websocket.onerror = this.onSocketError;
|
||||
this.websocket.onmessage = this.onSocketMessage;
|
||||
this.websocket.onopen = this.onSocketOpen;
|
||||
this.#websocket = new WebSocket(this.#endpoint);
|
||||
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);
|
||||
}
|
||||
@@ -143,16 +138,16 @@ export default class WsProvider implements WSProviderInterface {
|
||||
* @description Manually disconnect from the connection, clearing autoconnect logic
|
||||
*/
|
||||
public disconnect (): void {
|
||||
if (isNull(this.websocket)) {
|
||||
if (isNull(this.#websocket)) {
|
||||
throw new Error('Cannot disconnect on a non-open websocket');
|
||||
}
|
||||
|
||||
// switch off autoConnect, we are in manual mode now
|
||||
this.autoConnect = false;
|
||||
this.#autoConnect = false;
|
||||
|
||||
// 1000 - Normal closure; the connection successfully completed
|
||||
this.websocket.close(1000);
|
||||
this.websocket = null;
|
||||
this.#websocket.close(1000);
|
||||
this.#websocket = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,7 +155,7 @@ export default class WsProvider implements WSProviderInterface {
|
||||
* @return {boolean} true if connected
|
||||
*/
|
||||
public isConnected (): boolean {
|
||||
return this._isConnected;
|
||||
return this.#isConnected;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,9 +165,10 @@ export default class WsProvider implements WSProviderInterface {
|
||||
* @return unsubscribe function
|
||||
*/
|
||||
public on (type: ProviderInterfaceEmitted, sub: ProviderInterfaceEmitCb): () => void {
|
||||
this._eventemitter.on(type, sub);
|
||||
this.#eventemitter.on(type, sub);
|
||||
|
||||
return (): void => {
|
||||
this._eventemitter.removeListener(type, sub);
|
||||
this.#eventemitter.removeListener(type, sub);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -185,8 +181,8 @@ export default class WsProvider implements WSProviderInterface {
|
||||
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 json = this.#coder.encodeJson(method, params);
|
||||
const id = this.#coder.getId();
|
||||
const callback = (error?: Error | null, result?: any): void => {
|
||||
error
|
||||
? reject(error)
|
||||
@@ -195,17 +191,17 @@ export default class WsProvider implements WSProviderInterface {
|
||||
|
||||
l.debug((): string[] => ['calling', method, json]);
|
||||
|
||||
this.handlers[id] = {
|
||||
this.#handlers[id] = {
|
||||
callback,
|
||||
method,
|
||||
params,
|
||||
subscription
|
||||
};
|
||||
|
||||
if (this.isConnected() && !isNull(this.websocket)) {
|
||||
this.websocket.send(json);
|
||||
if (this.isConnected() && !isNull(this.#websocket)) {
|
||||
this.#websocket.send(json);
|
||||
} else {
|
||||
this.queued[id] = json;
|
||||
this.#queued[id] = json;
|
||||
}
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
@@ -252,55 +248,55 @@ export default class WsProvider implements WSProviderInterface {
|
||||
// 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])) {
|
||||
if (isUndefined(this.#subscriptions[subscription])) {
|
||||
l.debug((): string => `Unable to find active subscription=${subscription}`);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
delete this.subscriptions[subscription];
|
||||
delete this.#subscriptions[subscription];
|
||||
|
||||
const result = await this.send(method, [id]);
|
||||
|
||||
return result as boolean;
|
||||
}
|
||||
|
||||
private emit (type: ProviderInterfaceEmitted, ...args: any[]): void {
|
||||
this._eventemitter.emit(type, ...args);
|
||||
#emit = (type: ProviderInterfaceEmitted, ...args: any[]): void => {
|
||||
this.#eventemitter.emit(type, ...args);
|
||||
}
|
||||
|
||||
private onSocketClose = (event: CloseEvent): void => {
|
||||
if (this.autoConnect) {
|
||||
l.error(`disconnected from ${this.endpoint} code: '${event.code}' reason: '${event.reason}'`);
|
||||
#onSocketClose = (event: CloseEvent): void => {
|
||||
if (this.#autoConnect) {
|
||||
l.error(`disconnected from ${this.#endpoint} code: '${event.code}' reason: '${event.reason}'`);
|
||||
}
|
||||
|
||||
this._isConnected = false;
|
||||
this.emit('disconnected');
|
||||
this.#isConnected = false;
|
||||
this.#emit('disconnected');
|
||||
|
||||
if (this.autoConnect) {
|
||||
if (this.#autoConnect) {
|
||||
setTimeout((): void => {
|
||||
this.connect();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
private onSocketError = (error: Event): void => {
|
||||
#onSocketError = (error: Event): void => {
|
||||
l.debug((): any => ['socket error', error]);
|
||||
this.emit('error', error);
|
||||
this.#emit('error', error);
|
||||
}
|
||||
|
||||
private onSocketMessage = (message: MessageEvent): void => {
|
||||
#onSocketMessage = (message: MessageEvent): void => {
|
||||
l.debug((): any => ['received', message.data]);
|
||||
|
||||
const response: JsonRpcResponse = JSON.parse(message.data as string);
|
||||
|
||||
return isUndefined(response.method)
|
||||
? this.onSocketMessageResult(response)
|
||||
: this.onSocketMessageSubscribe(response);
|
||||
? this.#onSocketMessageResult(response)
|
||||
: this.#onSocketMessageSubscribe(response);
|
||||
}
|
||||
|
||||
private onSocketMessageResult = (response: JsonRpcResponse): void => {
|
||||
const handler = this.handlers[response.id];
|
||||
#onSocketMessageResult = (response: JsonRpcResponse): void => {
|
||||
const handler = this.#handlers[response.id];
|
||||
|
||||
if (!handler) {
|
||||
l.debug((): string => `Unable to find handler for id=${response.id}`);
|
||||
@@ -309,7 +305,7 @@ export default class WsProvider implements WSProviderInterface {
|
||||
|
||||
try {
|
||||
const { method, params, subscription } = handler;
|
||||
const result = this.coder.decodeResponse(response);
|
||||
const result = this.#coder.decodeResponse(response);
|
||||
|
||||
// first send the result - in case of subs, we may have an update
|
||||
// immediately if we have some queued results already
|
||||
@@ -318,42 +314,42 @@ export default class WsProvider implements WSProviderInterface {
|
||||
if (subscription) {
|
||||
const subId = `${subscription.type}::${result}`;
|
||||
|
||||
this.subscriptions[subId] = {
|
||||
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]);
|
||||
if (this.#waitingForId[subId]) {
|
||||
this.#onSocketMessageSubscribe(this.#waitingForId[subId]);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
handler.callback(error, undefined);
|
||||
}
|
||||
|
||||
delete this.handlers[response.id];
|
||||
delete this.#handlers[response.id];
|
||||
}
|
||||
|
||||
private onSocketMessageSubscribe = (response: JsonRpcResponse): void => {
|
||||
#onSocketMessageSubscribe = (response: JsonRpcResponse): void => {
|
||||
const method = ALIASSES[response.method as string] || response.method;
|
||||
const subId = `${method}::${response.params.subscription}`;
|
||||
const handler = this.subscriptions[subId];
|
||||
const handler = this.#subscriptions[subId];
|
||||
|
||||
if (!handler) {
|
||||
// store the JSON, we could have out-of-order subid coming in
|
||||
this.waitingForId[subId] = response;
|
||||
this.#waitingForId[subId] = response;
|
||||
|
||||
l.debug((): string => `Unable to find handler for subscription=${subId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// housekeeping
|
||||
delete this.waitingForId[subId];
|
||||
delete this.#waitingForId[subId];
|
||||
|
||||
try {
|
||||
const result = this.coder.decodeResponse(response);
|
||||
const result = this.#coder.decodeResponse(response);
|
||||
|
||||
handler.callback(null, result);
|
||||
} catch (error) {
|
||||
@@ -361,24 +357,24 @@ export default class WsProvider implements WSProviderInterface {
|
||||
}
|
||||
}
|
||||
|
||||
private onSocketOpen = (): boolean => {
|
||||
assert(!isNull(this.websocket), 'WebSocket cannot be null in onOpen');
|
||||
#onSocketOpen = (): boolean => {
|
||||
assert(!isNull(this.#websocket), 'WebSocket cannot be null in onOpen');
|
||||
|
||||
l.debug((): any[] => ['connected to', this.endpoint]);
|
||||
l.debug((): any[] => ['connected to', this.#endpoint]);
|
||||
|
||||
this._isConnected = true;
|
||||
this.emit('connected');
|
||||
this.#isConnected = true;
|
||||
|
||||
this.sendQueue();
|
||||
this.resubscribe();
|
||||
this.#emit('connected');
|
||||
this.#sendQueue();
|
||||
this.#resubscribe();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private resubscribe (): void {
|
||||
const subscriptions = this.subscriptions;
|
||||
#resubscribe = (): void => {
|
||||
const subscriptions = this.#subscriptions;
|
||||
|
||||
this.subscriptions = {};
|
||||
this.#subscriptions = {};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
Object.keys(subscriptions).forEach(async (id): Promise<void> => {
|
||||
@@ -399,15 +395,15 @@ export default class WsProvider implements WSProviderInterface {
|
||||
});
|
||||
}
|
||||
|
||||
private sendQueue (): void {
|
||||
Object.keys(this.queued).forEach((id): void => {
|
||||
#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]
|
||||
(this.#websocket as WebSocket).send(
|
||||
this.#queued[id]
|
||||
);
|
||||
|
||||
delete this.queued[id];
|
||||
delete this.#queued[id];
|
||||
} catch (error) {
|
||||
l.error(error);
|
||||
}
|
||||
|
||||
@@ -21,38 +21,23 @@ describe('onConnect', (): void => {
|
||||
|
||||
it('Does not connect when autoConnect is false', (): void => {
|
||||
const provider: WsProvider = new WsProvider(TEST_WS_URL, false);
|
||||
// We need to access the private WsProvider property 'websocket' here which would otherwise trigger a tslint error.
|
||||
expect((provider as any).websocket).toBeNull();
|
||||
|
||||
expect(provider.isConnected()).toBe(false);
|
||||
});
|
||||
|
||||
it('Does connect when autoConnect is true', (): void => {
|
||||
const provider: WsProvider = new WsProvider(TEST_WS_URL, true);
|
||||
|
||||
expect((provider as any).websocket).not.toBeNull();
|
||||
expect(provider.isConnected()).not.toBe(true);
|
||||
});
|
||||
|
||||
it('Creates a new WebSocket instance by calling the connect() method', (): void => {
|
||||
const provider: WsProvider = new WsProvider(TEST_WS_URL, false);
|
||||
|
||||
expect((provider as any).websocket).toBeNull();
|
||||
expect(provider.isConnected()).toBe(false);
|
||||
|
||||
provider.connect();
|
||||
|
||||
expect((provider as any).websocket).not.toBeNull();
|
||||
expect((provider as any).websocket instanceof WebSocket).toBe(true);
|
||||
});
|
||||
|
||||
it('Creates the on handlers', (): void => {
|
||||
const provider: WsProvider = new WsProvider(TEST_WS_URL);
|
||||
|
||||
expect((provider as any).websocket).not.toBeNull();
|
||||
expect((provider as any).websocket).toEqual(expect.objectContaining({
|
||||
listeners: expect.objectContaining({
|
||||
close: [expect.any(Function)],
|
||||
error: [expect.any(Function)],
|
||||
message: [expect.any(Function)],
|
||||
open: [expect.any(Function)]
|
||||
})
|
||||
}));
|
||||
expect(provider.isConnected()).not.toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/rpc-provider authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import WsProvider from './';
|
||||
|
||||
describe('WsProvider', (): void => {
|
||||
let provider: WsProvider;
|
||||
|
||||
beforeEach((): void => {
|
||||
provider = new WsProvider('ws://127.0.0.1:1234', false);
|
||||
});
|
||||
|
||||
it('calls the handler when found', (done): void => {
|
||||
// We need to access the private WsProvider property 'handlers' here which otherwise trigger a tslint error..
|
||||
(provider as any).handlers[5] = {
|
||||
callback: (_: any, result: any): void => {
|
||||
expect(result).toEqual('test');
|
||||
done();
|
||||
},
|
||||
method: '',
|
||||
params: []
|
||||
};
|
||||
|
||||
// We need to access the private WsProvider property 'onSocketMessage' here which would otherwise trigger a tslint error.
|
||||
(provider as any).onSocketMessage(
|
||||
new MessageEvent('test', { data: '{"jsonrpc":"2.0","id":5,"result":"test"}' })
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/rpc-provider authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import WsProvider from './';
|
||||
|
||||
describe('onMessageSubscribe', (): void => {
|
||||
let provider: WsProvider;
|
||||
|
||||
beforeEach((): void => {
|
||||
provider = new WsProvider('ws://127.0.0.1:1234', false);
|
||||
});
|
||||
|
||||
it('calls the subscriber with data', (done): void => {
|
||||
// We need to access the private WsProvider property 'handlers' here which otherwise triggers a tslint error..
|
||||
(provider as any).handlers[11] = {
|
||||
callback: (_: any, id: number): void => {
|
||||
expect(typeof id).toBe('number');
|
||||
},
|
||||
method: 'test',
|
||||
params: [],
|
||||
subscription: {
|
||||
callback: (_: any, result: any): void => {
|
||||
expect(result).toEqual('test');
|
||||
done();
|
||||
},
|
||||
type: 'test'
|
||||
}
|
||||
};
|
||||
|
||||
// We need to access the private WsProvider property 'onSocketMessage' here which would otherwise trigger a tslint error.
|
||||
(provider as any).onSocketMessage(new MessageEvent('test', { data: '{"jsonrpc":"2.0","id":11,"result":22}' }));
|
||||
(provider as any).onSocketMessage(new MessageEvent('test', { data: '{"jsonrpc":"2.0","method":"test","params":{"subscription":22,"result":"test"}}' }));
|
||||
});
|
||||
|
||||
it('calls the subscriber with error', (done): void => {
|
||||
// We need to access the private WsProvider property 'handlers' here which otherwise trigger a tslint error..
|
||||
(provider as any).handlers[11] = {
|
||||
callback: (_: any, id: number): void => {
|
||||
expect(typeof id).toBe('number');
|
||||
},
|
||||
method: 'test',
|
||||
params: [],
|
||||
subscription: {
|
||||
callback: (error: any): void => {
|
||||
expect(error.message).toMatch(/test/);
|
||||
done();
|
||||
},
|
||||
type: 'test'
|
||||
}
|
||||
};
|
||||
|
||||
// We need to access the private WsProvider property 'onSocketMessage' here which would otherwise trigger a tslint error.
|
||||
(provider as any).onSocketMessage(new MessageEvent('test', { data: '{"jsonrpc":"2.0","id":11,"result":22}' }));
|
||||
(provider as any).onSocketMessage(new MessageEvent('test', { data: '{"jsonrpc":"2.0","method":"test","params":{"subscription":22,"error":{"message":"test"}}}' }));
|
||||
});
|
||||
});
|
||||
@@ -39,21 +39,16 @@ describe('send', (): void => {
|
||||
});
|
||||
|
||||
it('handles internal errors', (): Promise<any> => {
|
||||
createMock([]);
|
||||
|
||||
(global as any).WebSocket = class {
|
||||
public send (): void {
|
||||
throw new Error('send error');
|
||||
createMock([{
|
||||
id: 1,
|
||||
method: 'test_body',
|
||||
reply: {
|
||||
result: 'ok'
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
provider = createWs(true);
|
||||
|
||||
// HACK this is a private method...
|
||||
(provider as any).websocket.onopen();
|
||||
|
||||
return provider
|
||||
.send('test_encoding', ['param'])
|
||||
return createWs(true)
|
||||
.send('test_encoding', [{ error: 'send error' }])
|
||||
.catch((error): void => {
|
||||
expect(error.message).toEqual('send error');
|
||||
});
|
||||
|
||||
@@ -30,19 +30,19 @@ export function isBigInt (value: any): value is BigInt {
|
||||
export default abstract class AbstractInt extends BN implements Codec {
|
||||
public readonly registry: Registry;
|
||||
|
||||
protected _bitLength: UIntBitLength;
|
||||
readonly #bitLength: UIntBitLength;
|
||||
|
||||
private _isHexJson: boolean;
|
||||
readonly #isHexJson: boolean;
|
||||
|
||||
private _isSigned: boolean;
|
||||
readonly #isSigned: boolean;
|
||||
|
||||
protected constructor (registry: Registry, isSigned: boolean, value: AnyNumber = 0, bitLength: UIntBitLength = DEFAULT_UINT_BITS, isHexJson = true) {
|
||||
super(AbstractInt.decodeAbstracInt(value, bitLength, isSigned));
|
||||
|
||||
this.registry = registry;
|
||||
this._bitLength = bitLength;
|
||||
this._isHexJson = isHexJson;
|
||||
this._isSigned = isSigned;
|
||||
this.#bitLength = bitLength;
|
||||
this.#isHexJson = isHexJson;
|
||||
this.#isSigned = isSigned;
|
||||
|
||||
assert(super.bitLength() <= bitLength, `${this.toRawType()}: Input too large. Found input with ${super.bitLength()} bits, expected ${bitLength}`);
|
||||
}
|
||||
@@ -83,7 +83,7 @@ export default abstract class AbstractInt extends BN implements Codec {
|
||||
* @description The length of the value when encoded as a Uint8Array
|
||||
*/
|
||||
public get encodedLength (): number {
|
||||
return this._bitLength / 8;
|
||||
return this.#bitLength / 8;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,14 +104,14 @@ export default abstract class AbstractInt extends BN implements Codec {
|
||||
* @description Checks if the value is an unsigned type
|
||||
*/
|
||||
public get isUnsigned (): boolean {
|
||||
return !this._isSigned;
|
||||
return !this.#isSigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the number of bits in the value
|
||||
*/
|
||||
public bitLength (): UIntBitLength {
|
||||
return this._bitLength;
|
||||
return this.#bitLength;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,7 +123,7 @@ export default abstract class AbstractInt extends BN implements Codec {
|
||||
// number and BN inputs (no `.eqn` needed) - numbers will be converted
|
||||
return super.eq(
|
||||
isHex(other)
|
||||
? hexToBn(other.toString(), { isLe: false, isNegative: this._isSigned })
|
||||
? hexToBn(other.toString(), { isLe: false, isNegative: this.#isSigned })
|
||||
: bnToBn(other)
|
||||
);
|
||||
}
|
||||
@@ -134,7 +134,7 @@ export default abstract class AbstractInt extends BN implements Codec {
|
||||
public isMax (): boolean {
|
||||
const u8a = this.toU8a().filter((byte): boolean => byte === 0xff);
|
||||
|
||||
return u8a.length === (this._bitLength / 8);
|
||||
return u8a.length === (this.#bitLength / 8);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,7 +164,7 @@ export default abstract class AbstractInt extends BN implements Codec {
|
||||
// FIXME this return type should by string | number, but BN's return type
|
||||
// is string.
|
||||
// Maximum allowed integer for JS is 2^53 - 1, set limit at 52
|
||||
return this._isHexJson || (super.bitLength() > 52)
|
||||
return this.#isHexJson || (super.bitLength() > 52)
|
||||
? this.toHex()
|
||||
: this.toNumber();
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ import { compareMap, decodeU8a, typeToConstructor } from './utils';
|
||||
export default class BTreeMap<K extends Codec = Codec, V extends Codec = Codec> extends Map<K, V> implements Codec {
|
||||
public readonly registry: Registry;
|
||||
|
||||
protected _KeyClass: Constructor<K>;
|
||||
private readonly _KeyClass: Constructor<K>;
|
||||
|
||||
protected _ValClass: Constructor<V>;
|
||||
private readonly _ValClass: Constructor<V>;
|
||||
|
||||
constructor (registry: Registry, keyType: Constructor<K> | InterfaceTypes, valType: Constructor<V> | InterfaceTypes, rawValue: any) {
|
||||
const KeyClass = typeToConstructor(registry, keyType);
|
||||
|
||||
@@ -15,7 +15,7 @@ import { compareSet, decodeU8a, typeToConstructor } from './utils';
|
||||
export default class BTreeSet<V extends Codec = Codec> extends Set<V> implements Codec {
|
||||
public readonly registry: Registry;
|
||||
|
||||
protected _ValClass: Constructor<V>;
|
||||
private readonly _ValClass: Constructor<V>;
|
||||
|
||||
constructor (registry: Registry, valType: Constructor<V> | InterfaceTypes, rawValue: any) {
|
||||
const ValClass = typeToConstructor(registry, valType);
|
||||
|
||||
@@ -16,7 +16,7 @@ import Raw from './Raw';
|
||||
export default abstract class Base<T extends Codec> implements Codec {
|
||||
public readonly registry: Registry;
|
||||
|
||||
protected raw: T;
|
||||
protected readonly raw: T;
|
||||
|
||||
protected constructor (registry: Registry, value?: any) {
|
||||
this.registry = registry;
|
||||
|
||||
@@ -27,13 +27,10 @@ const BITLENGTH: UIntBitLength = 64;
|
||||
export default class CodecDate extends Date implements Codec {
|
||||
public readonly registry: Registry;
|
||||
|
||||
protected raw: Date; // FIXME Remove this once we convert all types out of Base
|
||||
|
||||
constructor (registry: Registry, value: CodecDate | Date | AnyNumber = 0) {
|
||||
super(CodecDate.decodeDate(value));
|
||||
|
||||
this.registry = registry;
|
||||
this.raw = this;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
||||
@@ -40,7 +40,7 @@ export default class Int extends AbstractInt {
|
||||
*/
|
||||
public toHex (isLe = false): string {
|
||||
return bnToHex(this, {
|
||||
bitLength: this._bitLength,
|
||||
bitLength: this.bitLength(),
|
||||
isLe,
|
||||
isNegative: true
|
||||
});
|
||||
@@ -50,7 +50,7 @@ export default class Int extends AbstractInt {
|
||||
* @description Returns the base runtime type name for this instance
|
||||
*/
|
||||
public toRawType (): string {
|
||||
return `i${this._bitLength}`;
|
||||
return `i${this.bitLength()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +60,7 @@ export default class Int extends AbstractInt {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public toU8a (isBare?: boolean): Uint8Array {
|
||||
return bnToU8a(this, {
|
||||
bitLength: this._bitLength,
|
||||
bitLength: this.bitLength(),
|
||||
isLe: true,
|
||||
isNegative: true
|
||||
});
|
||||
|
||||
@@ -42,7 +42,7 @@ export default class UInt extends AbstractInt {
|
||||
public toHex (isLe = false): string {
|
||||
// For display/JSON, this is BE, for compare, use isLe
|
||||
return bnToHex(this, {
|
||||
bitLength: this._bitLength,
|
||||
bitLength: this.bitLength(),
|
||||
isLe,
|
||||
isNegative: false
|
||||
});
|
||||
@@ -67,7 +67,7 @@ export default class UInt extends AbstractInt {
|
||||
// underlying it always matches (no matter which length it actually is)
|
||||
return this instanceof ClassOf(this.registry, 'Balance')
|
||||
? 'Balance'
|
||||
: `u${this._bitLength}`;
|
||||
: `u${this.bitLength()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +77,7 @@ export default class UInt extends AbstractInt {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public toU8a (isBare?: boolean): Uint8Array {
|
||||
return bnToU8a(this, {
|
||||
bitLength: this._bitLength,
|
||||
bitLength: this.bitLength(),
|
||||
isLe: true,
|
||||
isNegative: false
|
||||
});
|
||||
|
||||
@@ -77,21 +77,21 @@ function decorateExtrinsics (registry: Registry, metadata: RegistryMetadata, met
|
||||
}
|
||||
|
||||
export class TypeRegistry implements Registry {
|
||||
private _chainProperties?: ChainProperties;
|
||||
readonly #classes: Map<string, Constructor> = new Map();
|
||||
|
||||
private _classes: Map<string, Constructor> = new Map();
|
||||
readonly #definitions: Map<string, string> = new Map();
|
||||
|
||||
private _definitions: Map<string, string> = new Map();
|
||||
readonly #metadataCalls: Record<string, CallFunction> = {};
|
||||
|
||||
private _metadataCalls: Record<string, CallFunction> = {};
|
||||
readonly #metadataErrors: Record<string, RegistryError> = {};
|
||||
|
||||
private _metadataErrors: Record<string, RegistryError> = {};
|
||||
readonly #metadataEvents: Record<string, Constructor<EventData>> = {};
|
||||
|
||||
private _metadataEvents: Record<string, Constructor<EventData>> = {};
|
||||
readonly #unknownTypes: Map<string, boolean> = new Map();
|
||||
|
||||
private _metadataExtensions: string[] = defaultExtensions;
|
||||
#chainProperties?: ChainProperties;
|
||||
|
||||
private _unknownTypes: Map<string, boolean> = new Map();
|
||||
#metadataExtensions: string[] = defaultExtensions;
|
||||
|
||||
constructor () {
|
||||
// we only want to import these on creation, i.e. we want to avoid types
|
||||
@@ -110,27 +110,27 @@ export class TypeRegistry implements Registry {
|
||||
}
|
||||
|
||||
public get chainDecimals (): number {
|
||||
return this._chainProperties?.tokenDecimals.isSome
|
||||
? this._chainProperties.tokenDecimals.unwrap().toNumber()
|
||||
return this.#chainProperties?.tokenDecimals.isSome
|
||||
? this.#chainProperties.tokenDecimals.unwrap().toNumber()
|
||||
: 12;
|
||||
}
|
||||
|
||||
public get chainSS58 (): number | undefined {
|
||||
return this._chainProperties?.ss58Format.isSome
|
||||
? this._chainProperties.ss58Format.unwrap().toNumber()
|
||||
return this.#chainProperties?.ss58Format.isSome
|
||||
? this.#chainProperties.ss58Format.unwrap().toNumber()
|
||||
: undefined;
|
||||
}
|
||||
|
||||
public get chainToken (): string {
|
||||
return this._chainProperties?.tokenSymbol.isSome
|
||||
? this._chainProperties.tokenSymbol.unwrap().toString()
|
||||
return this.#chainProperties?.tokenSymbol.isSome
|
||||
? this.#chainProperties.tokenSymbol.unwrap().toString()
|
||||
: formatBalance.getDefaults().unit;
|
||||
}
|
||||
|
||||
// find a specific call
|
||||
public findMetaCall (callIndex: Uint8Array): CallFunction {
|
||||
const hexIndex = u8aToHex(callIndex);
|
||||
const fn = this._metadataCalls[hexIndex];
|
||||
const fn = this.#metadataCalls[hexIndex];
|
||||
|
||||
assert(!isUndefined(fn), `findMetaCall: Unable to find Call with index ${hexIndex}/[${callIndex}]`);
|
||||
|
||||
@@ -144,7 +144,7 @@ export class TypeRegistry implements Registry {
|
||||
? errorIndex
|
||||
: new Uint8Array([errorIndex.index.toNumber(), errorIndex.error.toNumber()])
|
||||
);
|
||||
const error = this._metadataErrors[hexIndex];
|
||||
const error = this.#metadataErrors[hexIndex];
|
||||
|
||||
assert(!isUndefined(error), `findMetaError: Unable to find Error with index ${hexIndex}/[${errorIndex}]`);
|
||||
|
||||
@@ -153,7 +153,7 @@ export class TypeRegistry implements Registry {
|
||||
|
||||
public findMetaEvent (eventIndex: Uint8Array): Constructor<EventData> {
|
||||
const hexIndex = u8aToHex(eventIndex);
|
||||
const Event = this._metadataEvents[hexIndex];
|
||||
const Event = this.#metadataEvents[hexIndex];
|
||||
|
||||
assert(!isUndefined(Event), `findMetaEvent: Unable to find Event with index ${hexIndex}/[${eventIndex}]`);
|
||||
|
||||
@@ -161,11 +161,11 @@ export class TypeRegistry implements Registry {
|
||||
}
|
||||
|
||||
public get <T extends Codec = Codec> (name: string, withUnknown?: boolean): Constructor<T> | undefined {
|
||||
let Type = this._classes.get(name);
|
||||
let Type = this.#classes.get(name);
|
||||
|
||||
// we have not already created the type, attempt it
|
||||
if (!Type) {
|
||||
const definition = this._definitions.get(name);
|
||||
const definition = this.#definitions.get(name);
|
||||
let BaseType: Constructor<Codec> | undefined;
|
||||
|
||||
// we have a definition, so create the class now (lazily)
|
||||
@@ -174,7 +174,7 @@ export class TypeRegistry implements Registry {
|
||||
} else if (withUnknown) {
|
||||
console.warn(`Unable to resolve type ${name}, it will fail on constrution`);
|
||||
|
||||
this._unknownTypes.set(name, true);
|
||||
this.#unknownTypes.set(name, true);
|
||||
BaseType = Unconstructable.with(name);
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ export class TypeRegistry implements Registry {
|
||||
// Additionally, we now pass through the registry, which is a link to ourselves
|
||||
Type = class extends BaseType {};
|
||||
|
||||
this._classes.set(name, Type);
|
||||
this.#classes.set(name, Type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,11 +192,11 @@ export class TypeRegistry implements Registry {
|
||||
}
|
||||
|
||||
public getChainProperties (): ChainProperties | undefined {
|
||||
return this._chainProperties;
|
||||
return this.#chainProperties;
|
||||
}
|
||||
|
||||
public getDefinition (name: string): string | undefined {
|
||||
return this._definitions.get(name);
|
||||
return this.#definitions.get(name);
|
||||
}
|
||||
|
||||
public getOrThrow <T extends Codec = Codec> (name: string, msg?: string): Constructor<T> {
|
||||
@@ -214,23 +214,23 @@ export class TypeRegistry implements Registry {
|
||||
}
|
||||
|
||||
public getSignedExtensionExtra (): Record<string, InterfaceTypes> {
|
||||
return expandExtensionTypes(this._metadataExtensions, 'extra');
|
||||
return expandExtensionTypes(this.#metadataExtensions, 'extra');
|
||||
}
|
||||
|
||||
public getSignedExtensionTypes (): Record<string, InterfaceTypes> {
|
||||
return expandExtensionTypes(this._metadataExtensions, 'types');
|
||||
return expandExtensionTypes(this.#metadataExtensions, 'types');
|
||||
}
|
||||
|
||||
public hasClass (name: string): boolean {
|
||||
return this._classes.has(name);
|
||||
return this.#classes.has(name);
|
||||
}
|
||||
|
||||
public hasDef (name: string): boolean {
|
||||
return this._definitions.has(name);
|
||||
return this.#definitions.has(name);
|
||||
}
|
||||
|
||||
public hasType (name: string): boolean {
|
||||
return !this._unknownTypes.get(name) && (this.hasClass(name) || this.hasDef(name));
|
||||
return !this.#unknownTypes.get(name) && (this.hasClass(name) || this.hasDef(name));
|
||||
}
|
||||
|
||||
public register (type: Constructor | RegistryTypes): void;
|
||||
@@ -242,11 +242,11 @@ export class TypeRegistry implements Registry {
|
||||
public register (arg1: string | Constructor | RegistryTypes, arg2?: Constructor): void {
|
||||
// NOTE Constructors appear as functions here
|
||||
if (isFunction(arg1)) {
|
||||
this._classes.set(arg1.name, arg1);
|
||||
this.#classes.set(arg1.name, arg1);
|
||||
} else if (isString(arg1)) {
|
||||
assert(isFunction(arg2), `Expected class definition passed to '${arg1}' registration`);
|
||||
|
||||
this._classes.set(arg1, arg2);
|
||||
this.#classes.set(arg1, arg2);
|
||||
} else {
|
||||
this.registerObject(arg1);
|
||||
}
|
||||
@@ -256,18 +256,18 @@ export class TypeRegistry implements Registry {
|
||||
Object.entries(obj).forEach(([name, type]): void => {
|
||||
if (isFunction(type)) {
|
||||
// This _looks_ a bit funny, but `typeof Clazz === 'function'
|
||||
this._classes.set(name, type);
|
||||
this.#classes.set(name, type);
|
||||
} else {
|
||||
const def = isString(type)
|
||||
? type
|
||||
: JSON.stringify(type);
|
||||
|
||||
// we already have this type, remove the classes registered for it
|
||||
if (this._classes.has(name)) {
|
||||
this._classes.delete(name);
|
||||
if (this.#classes.has(name)) {
|
||||
this.#classes.delete(name);
|
||||
}
|
||||
|
||||
this._definitions.set(name, def);
|
||||
this.#definitions.set(name, def);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -275,22 +275,22 @@ export class TypeRegistry implements Registry {
|
||||
// sets the chain properties
|
||||
public setChainProperties (properties?: ChainProperties): void {
|
||||
if (properties) {
|
||||
this._chainProperties = properties;
|
||||
this.#chainProperties = properties;
|
||||
}
|
||||
}
|
||||
|
||||
// sets the metadata
|
||||
public setMetadata (metadata: RegistryMetadata): void {
|
||||
decorateExtrinsics(this, metadata, this._metadataCalls);
|
||||
decorateErrors(this, metadata, this._metadataErrors);
|
||||
decorateEvents(this, metadata, this._metadataEvents);
|
||||
decorateExtrinsics(this, metadata, this.#metadataCalls);
|
||||
decorateErrors(this, metadata, this.#metadataErrors);
|
||||
decorateEvents(this, metadata, this.#metadataEvents);
|
||||
|
||||
// setup the available extensions
|
||||
this._metadataExtensions = metadata.asLatest.extrinsic.version.gtn(0)
|
||||
this.#metadataExtensions = metadata.asLatest.extrinsic.version.gtn(0)
|
||||
? metadata.asLatest.extrinsic.signedExtensions.map((key): string => key.toString())
|
||||
: defaultExtensions;
|
||||
|
||||
const unknown = findUnknownExtensions(this._metadataExtensions);
|
||||
const unknown = findUnknownExtensions(this.#metadataExtensions);
|
||||
|
||||
if (unknown.length) {
|
||||
console.warn(`Unknown signed extensions [${unknown.join(', ')}] found, treating them as no-efect`);
|
||||
|
||||
@@ -17,49 +17,49 @@ import Null from '../primitive/Null';
|
||||
* Wrapper for the actual data that forms part of an [[Event]]
|
||||
*/
|
||||
export class EventData extends Tuple {
|
||||
private _meta: EventMetadataLatest;
|
||||
readonly #meta: EventMetadataLatest;
|
||||
|
||||
private _method: string;
|
||||
readonly #method: string;
|
||||
|
||||
private _section: string;
|
||||
readonly #section: string;
|
||||
|
||||
private _typeDef: TypeDef[];
|
||||
readonly #typeDef: TypeDef[];
|
||||
|
||||
constructor (registry: Registry, Types: Constructor[], value: Uint8Array, typeDef: TypeDef[], meta: RegistryMetadataEvent, section: string, method: string) {
|
||||
super(registry, Types, value);
|
||||
|
||||
this._meta = meta as EventMetadataLatest;
|
||||
this._method = method;
|
||||
this._section = section;
|
||||
this._typeDef = typeDef;
|
||||
this.#meta = meta as EventMetadataLatest;
|
||||
this.#method = method;
|
||||
this.#section = section;
|
||||
this.#typeDef = typeDef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The wrapped [[EventMetadata]]
|
||||
*/
|
||||
public get meta (): EventMetadataLatest {
|
||||
return this._meta;
|
||||
return this.#meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The method as a string
|
||||
*/
|
||||
public get method (): string {
|
||||
return this._method;
|
||||
return this.#method;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The section as a string
|
||||
*/
|
||||
public get section (): string {
|
||||
return this._section;
|
||||
return this.#section;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The [[TypeDef]] for this event
|
||||
*/
|
||||
public get typeDef (): TypeDef[] {
|
||||
return this._typeDef;
|
||||
return this.#typeDef;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import { detectPackage } from '@polkadot/util';
|
||||
|
||||
// FIXME This really should be `import(...).then(...)`, but need to check rejections
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
detectPackage(require('./package.json'), __dirname);
|
||||
|
||||
|
||||
@@ -50,7 +50,8 @@ function decodeText (value: Text | string | AnyU8a | { toString: () => string })
|
||||
// - Strings should probably be trimmed (docs do come through with extra padding)
|
||||
export default class Text extends String implements Codec {
|
||||
public readonly registry: Registry;
|
||||
private _override: string | null = null;
|
||||
|
||||
#override: string | null = null;
|
||||
|
||||
constructor (registry: Registry, value: Text | string | AnyU8a | { toString: () => string } = '') {
|
||||
super(decodeText(value));
|
||||
@@ -100,7 +101,7 @@ export default class Text extends String implements Codec {
|
||||
* @description Set an override value for this
|
||||
*/
|
||||
public setOverride (override: string): void {
|
||||
this._override = override;
|
||||
this.#override = override;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,7 +138,7 @@ export default class Text extends String implements Codec {
|
||||
* @description Returns the string representation of the value
|
||||
*/
|
||||
public toString (): string {
|
||||
return this._override || super.toString();
|
||||
return this.#override || super.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -416,6 +416,13 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.8.0"
|
||||
|
||||
"@babel/plugin-syntax-import-meta@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.8.3.tgz#230afff79d3ccc215b5944b438e4e266daf3d84d"
|
||||
integrity sha512-vYiGd4wQ9gx0Lngb7+bPCwQXGK/PR6FeTIJ+TIOlq+OfOKG/kCAOO2+IBac3oMM9qV7/fU76hfcqxUaLKZf1hQ==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
|
||||
"@babel/plugin-syntax-json-strings@^7.8.0":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
|
||||
@@ -1967,15 +1974,16 @@
|
||||
dependencies:
|
||||
"@types/node" ">= 8"
|
||||
|
||||
"@polkadot/dev@^0.40.22":
|
||||
version "0.40.22"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/dev/-/dev-0.40.22.tgz#6306f3d0400180f57bdfa63ce63ee2e9da96d3f8"
|
||||
integrity sha512-c1m1rk4FFXq/Jy67CzJkZLNtB7agjrB4Tbbwum7WItcdb6GrjnWB32ZmHEBPd982CTyiBRi5Y2OoUZMp6uR13A==
|
||||
"@polkadot/dev@^0.41.1":
|
||||
version "0.41.1"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/dev/-/dev-0.41.1.tgz#00585db9d4a78b143c7a9572636fb404dbe9de27"
|
||||
integrity sha512-DWmXD1WDDX/xUfLoF1r/dP9E2158iPHSOEURfnyZrvBgMNYh5FqFZ7dO4sMPebZlHeg5jaK/GzhR0kKr78s8SA==
|
||||
dependencies:
|
||||
"@babel/cli" "^7.8.4"
|
||||
"@babel/core" "^7.8.4"
|
||||
"@babel/plugin-proposal-class-properties" "^7.8.3"
|
||||
"@babel/plugin-proposal-decorators" "^7.8.3"
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3"
|
||||
"@babel/plugin-proposal-numeric-separator" "^7.8.3"
|
||||
"@babel/plugin-proposal-object-rest-spread" "^7.8.3"
|
||||
"@babel/plugin-proposal-optional-chaining" "^7.8.3"
|
||||
@@ -1983,6 +1991,8 @@
|
||||
"@babel/plugin-proposal-private-methods" "^7.8.3"
|
||||
"@babel/plugin-syntax-bigint" "^7.8.3"
|
||||
"@babel/plugin-syntax-dynamic-import" "^7.8.3"
|
||||
"@babel/plugin-syntax-import-meta" "^7.8.3"
|
||||
"@babel/plugin-syntax-top-level-await" "^7.8.3"
|
||||
"@babel/plugin-transform-runtime" "^7.8.3"
|
||||
"@babel/preset-env" "^7.8.4"
|
||||
"@babel/preset-react" "^7.8.3"
|
||||
|
||||
Reference in New Issue
Block a user