Minor API-related readability cleanups (#1333)
* Minor API-related readability cleanups * Oops, remove trial protected, revert to private * Unneeded as Observable<...> casts * Split state retrieval from signAndSend * Typo in comment * Cleanup descriptions
This commit is contained in:
@@ -37,18 +37,11 @@ const _Payload: Constructor<SignerPayloadType> = Struct.with({
|
||||
});
|
||||
|
||||
export default class Payload extends _Payload {
|
||||
/**
|
||||
* @description Returns this as a SignerPayloadType. This works since the Struct.with injects all the getters automatically (just ensure the 2 definitiona are matching)
|
||||
*/
|
||||
public get self (): SignerPayloadType {
|
||||
return this as any as SignerPayloadType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Creates an representation of the structure as an ISignerPayload JSON
|
||||
*/
|
||||
public toPayload (): SignerPayload {
|
||||
const { address, blockHash, blockNumber, era, genesisHash, method, nonce, runtimeVersion: { specVersion }, tip, version } = this.self;
|
||||
const { address, blockHash, blockNumber, era, genesisHash, method, nonce, runtimeVersion: { specVersion }, tip, version } = this;
|
||||
|
||||
return {
|
||||
address: address.toString(),
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, Address, Call, ExtrinsicEra, ExtrinsicStatus, EventRecord, Hash, Header, Index, SignedBlock } from '@polkadot/types/interfaces';
|
||||
import { AccountId, Address, Call, ExtrinsicEra, ExtrinsicStatus, EventRecord, Hash, Header, Index } from '@polkadot/types/interfaces';
|
||||
import { AnyNumber, AnyU8a, Callback, Codec, IExtrinsic, IExtrinsicEra, IKeyringPair, SignatureOptions } from '@polkadot/types/types';
|
||||
import { ApiInterfaceRx, ApiTypes } from './types';
|
||||
|
||||
@@ -110,8 +110,7 @@ export default function createSubmittableExtrinsic<ApiType> (
|
||||
type: ApiTypes,
|
||||
api: ApiInterfaceRx,
|
||||
decorateMethod: ApiBase<ApiType>['decorateMethod'],
|
||||
extrinsic: Call | Uint8Array | string,
|
||||
trackingCb?: Callback<ISubmittableResult>
|
||||
extrinsic: Call | Uint8Array | string
|
||||
): SubmittableExtrinsic<ApiType> {
|
||||
const _extrinsic = createType('Extrinsic', extrinsic, { version: api.extrinsicType }) as unknown as SubmittableExtrinsic<ApiType>;
|
||||
const _noStatusCb = type === 'rxjs';
|
||||
@@ -124,35 +123,27 @@ export default function createSubmittableExtrinsic<ApiType> (
|
||||
|
||||
function statusObservable (status: ExtrinsicStatus): Observable<ISubmittableResult> {
|
||||
if (!status.isFinalized) {
|
||||
const result = new SubmittableResult({ status });
|
||||
|
||||
trackingCb && trackingCb(result);
|
||||
|
||||
return of(result);
|
||||
return of(new SubmittableResult({ status }));
|
||||
}
|
||||
|
||||
const blockHash = status.asFinalized;
|
||||
|
||||
return combineLatest([
|
||||
api.rpc.chain.getBlock(blockHash) as Observable<SignedBlock>,
|
||||
api.rpc.chain.getBlock(blockHash),
|
||||
api.query.system.events.at(blockHash) as Observable<Vec<EventRecord>>
|
||||
]).pipe(
|
||||
map(([signedBlock, allEvents]): SubmittableResult => {
|
||||
const result = new SubmittableResult({
|
||||
map(([signedBlock, allEvents]): SubmittableResult =>
|
||||
new SubmittableResult({
|
||||
events: filterEvents(_extrinsic.hash, signedBlock, allEvents),
|
||||
status
|
||||
});
|
||||
|
||||
trackingCb && trackingCb(result);
|
||||
|
||||
return result;
|
||||
})
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function sendObservable (updateId: number = -1): Observable<Hash> {
|
||||
return (api.rpc.author
|
||||
.submitExtrinsic(_extrinsic) as Observable<Hash>)
|
||||
return api.rpc.author
|
||||
.submitExtrinsic(_extrinsic)
|
||||
.pipe(
|
||||
tap((hash): void => {
|
||||
updateSigner(updateId, hash);
|
||||
@@ -161,8 +152,8 @@ export default function createSubmittableExtrinsic<ApiType> (
|
||||
}
|
||||
|
||||
function subscribeObservable (updateId: number = -1): Observable<ISubmittableResult> {
|
||||
return (api.rpc.author
|
||||
.submitAndWatchExtrinsic(_extrinsic) as Observable<ExtrinsicStatus>)
|
||||
return api.rpc.author
|
||||
.submitAndWatchExtrinsic(_extrinsic)
|
||||
.pipe(
|
||||
switchMap((status): Observable<ISubmittableResult> =>
|
||||
statusObservable(status)
|
||||
@@ -206,6 +197,20 @@ export default function createSubmittableExtrinsic<ApiType> (
|
||||
});
|
||||
}
|
||||
|
||||
function 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.query.system.accountNonce<Index>(address)
|
||||
: of(createType('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)
|
||||
]);
|
||||
}
|
||||
|
||||
const signOrigin = _extrinsic.sign;
|
||||
|
||||
Object.defineProperties(
|
||||
@@ -246,71 +251,60 @@ export default function createSubmittableExtrinsic<ApiType> (
|
||||
let updateId: number | undefined;
|
||||
|
||||
return decorateMethod(
|
||||
(): Observable<Codec> => ((
|
||||
combineLatest([
|
||||
// if we have a nonce already, don't retrieve the latest, use what is there
|
||||
isUndefined(options.nonce)
|
||||
? api.query.system.accountNonce<Index>(address)
|
||||
: of(createType('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() as Observable<Header>
|
||||
: of(null)
|
||||
])
|
||||
).pipe(
|
||||
first(),
|
||||
mergeMap(async ([nonce, header]): Promise<void> => {
|
||||
const eraOptions = expandEraOptions(options, { header, nonce });
|
||||
(): Observable<Codec> => (
|
||||
getPrelimState(address, options).pipe(
|
||||
first(),
|
||||
mergeMap(async ([nonce, header]): Promise<void> => {
|
||||
const eraOptions = expandEraOptions(options, { header, nonce });
|
||||
|
||||
// FIXME This is becoming real messy with all the options - way past
|
||||
// "a method should fit on a single screen" stage. (Probably want to
|
||||
// clean this when we remove `api.signer.sign` in the next beta cycle)
|
||||
if (isKeyringPair(account)) {
|
||||
this.sign(account, eraOptions);
|
||||
} else if (api.signer) {
|
||||
const payload = new SignerPayload({
|
||||
...eraOptions,
|
||||
address,
|
||||
method: _extrinsic.method,
|
||||
blockNumber: header ? header.number : 0
|
||||
});
|
||||
|
||||
if (api.signer.signPayload) {
|
||||
const { id, signature } = await api.signer.signPayload(payload.toPayload());
|
||||
|
||||
// Here we explicitly call `toPayload()` again instead of working with an object
|
||||
// (reference) as passed to the signer. This means that we are sure that the
|
||||
// payload data is not modified from our inputs, but the signer
|
||||
_extrinsic.addSignature(address, signature, payload.toPayload());
|
||||
updateId = id;
|
||||
} else if (api.signer.signRaw) {
|
||||
const { id, signature } = await api.signer.signRaw(payload.toRaw());
|
||||
|
||||
// as above, always trust our payload as the signle sourec of truth
|
||||
_extrinsic.addSignature(address, signature, payload.toPayload());
|
||||
updateId = id;
|
||||
} else if (api.signer.sign) {
|
||||
console.warn('The Signer.sign interface is deprecated and will be removed in a future version, Swap to using the Signer.signPayload interface instead.');
|
||||
|
||||
updateId = await api.signer.sign(_extrinsic, address, {
|
||||
// FIXME This is becoming real messy with all the options - way past
|
||||
// "a method should fit on a single screen" stage. (Probably want to
|
||||
// clean this when we remove `api.signer.sign` in the next beta cycle)
|
||||
if (isKeyringPair(account)) {
|
||||
this.sign(account, eraOptions);
|
||||
} else if (api.signer) {
|
||||
const payload = new SignerPayload({
|
||||
...eraOptions,
|
||||
blockNumber: header ? header.number.toBn() : new BN(0),
|
||||
genesisHash: api.genesisHash
|
||||
address,
|
||||
method: _extrinsic.method,
|
||||
blockNumber: header ? header.number : 0
|
||||
});
|
||||
|
||||
if (api.signer.signPayload) {
|
||||
const { id, signature } = await api.signer.signPayload(payload.toPayload());
|
||||
|
||||
// Here we explicitly call `toPayload()` again instead of working with an object
|
||||
// (reference) as passed to the signer. This means that we are sure that the
|
||||
// payload data is not modified from our inputs, but the signer
|
||||
_extrinsic.addSignature(address, signature, payload.toPayload());
|
||||
updateId = id;
|
||||
} else if (api.signer.signRaw) {
|
||||
const { id, signature } = await api.signer.signRaw(payload.toRaw());
|
||||
|
||||
// as above, always trust our payload as the signle sourec of truth
|
||||
_extrinsic.addSignature(address, signature, payload.toPayload());
|
||||
updateId = id;
|
||||
} else if (api.signer.sign) {
|
||||
console.warn('The Signer.sign interface is deprecated and will be removed in a future version, Swap to using the Signer.signPayload interface instead.');
|
||||
|
||||
updateId = await api.signer.sign(_extrinsic, address, {
|
||||
...eraOptions,
|
||||
blockNumber: header ? header.number.toBn() : new BN(0),
|
||||
genesisHash: api.genesisHash
|
||||
});
|
||||
} else {
|
||||
throw new Error('Invalid signer interface');
|
||||
}
|
||||
} else {
|
||||
throw new Error('Invalid signer interface');
|
||||
throw new Error('no signer exists');
|
||||
}
|
||||
} else {
|
||||
throw new Error('no signer exists');
|
||||
}
|
||||
}),
|
||||
switchMap((): Observable<ISubmittableResult> | Observable<Hash> => {
|
||||
return isSubscription
|
||||
? subscribeObservable(updateId)
|
||||
: sendObservable(updateId);
|
||||
})
|
||||
) as Observable<Codec>)
|
||||
}),
|
||||
switchMap((): Observable<ISubmittableResult> | Observable<Hash> => {
|
||||
return isSubscription
|
||||
? subscribeObservable(updateId)
|
||||
: sendObservable(updateId);
|
||||
})
|
||||
) as Observable<Codec>) // FIXME This is wrong, SubmittableResult is _not_ a codec
|
||||
)(statusCb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ export default abstract class Decorate<ApiType> extends Events {
|
||||
decorated.key = (arg1?: Arg, arg2?: Arg): string =>
|
||||
u8aToHex(compactStripLength(creator(creator.meta.type.isDoubleMap ? [arg1, arg2] : arg1))[1]);
|
||||
|
||||
// When using double map storage function, user need to path double map key as an array
|
||||
// When using double map storage function, user need to pass double map key as an array
|
||||
decorated.multi = decorateMethod((args: (Arg | Arg[])[]): Observable<Codec[]> =>
|
||||
this._rpcCore.state.subscribeStorage(
|
||||
args.map((arg: Arg[] | Arg): [StorageEntry, Arg | Arg[]] => [creator, arg])));
|
||||
|
||||
@@ -12,13 +12,57 @@ import { isFunction, assert } from '@polkadot/util';
|
||||
import ApiBase from '../base';
|
||||
import Combinator, { CombinatorCallback, CombinatorFunction } from './Combinator';
|
||||
|
||||
interface Tracker {
|
||||
reject: (value: Error) => Observable<never>;
|
||||
resolve: (value: () => void) => void;
|
||||
}
|
||||
|
||||
// extract the arguments and callback params from a value array possibly containing a callback
|
||||
function extractArgs (args: any[], needsCallback: boolean): [any[], 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();
|
||||
}
|
||||
|
||||
// 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 (resolve: (value: () => void) => void, reject: (value: Error) => void): Tracker {
|
||||
let isCompleted = false;
|
||||
const complete = (fn: Function, value: any): void => {
|
||||
if (!isCompleted) {
|
||||
isCompleted = true;
|
||||
|
||||
fn(value);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
reject: (error: Error): Observable<never> => {
|
||||
complete(reject, error);
|
||||
|
||||
return EMPTY;
|
||||
},
|
||||
resolve: (value: any): void => {
|
||||
complete(resolve, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* # @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.
|
||||
*
|
||||
@@ -102,10 +146,8 @@ export default class ApiPromise extends ApiBase<'promise'> {
|
||||
|
||||
/**
|
||||
* @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>
|
||||
*
|
||||
@@ -125,10 +167,8 @@ export default class ApiPromise extends ApiBase<'promise'> {
|
||||
|
||||
/**
|
||||
* @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>
|
||||
*
|
||||
@@ -197,49 +237,31 @@ export default class ApiPromise extends ApiBase<'promise'> {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Decorate method for ApiPromise, where the results are converted to the Promise equivalent
|
||||
*/
|
||||
protected decorateMethod<Method extends AnyFunction> (method: Method, options?: DecorateMethodOptions): StorageEntryPromiseOverloads {
|
||||
const needsCallback = options && options.methodName && options.methodName.includes('subscribe');
|
||||
|
||||
return function (...args: any[]): Promise<ObsInnerType<ReturnType<Method>>> | UnsubscribePromise {
|
||||
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();
|
||||
}
|
||||
|
||||
// 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');
|
||||
const [actualArgs, callback] = extractArgs(args, !!needsCallback);
|
||||
|
||||
if (!callback) {
|
||||
return method(...actualArgs).pipe(first()).toPromise() as Promise<ObsInnerType<ReturnType<Method>>>;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject): void => {
|
||||
let isCompleted = false;
|
||||
const tracker = promiseTracker(resolve, reject);
|
||||
const subscription = method(...actualArgs)
|
||||
.pipe(
|
||||
// if we find an error (invalid params, etc), reject the promise
|
||||
catchError((error): Observable<never> => {
|
||||
if (!isCompleted) {
|
||||
isCompleted = true;
|
||||
|
||||
reject(error);
|
||||
}
|
||||
|
||||
// we don't want to continue, so empty observable it is
|
||||
return EMPTY;
|
||||
}),
|
||||
catchError((error): Observable<never> =>
|
||||
tracker.reject(error)
|
||||
),
|
||||
// upon the first result, resolve the with the unsub function
|
||||
tap((): void => {
|
||||
if (!isCompleted) {
|
||||
isCompleted = true;
|
||||
|
||||
resolve((): void => subscription.unsubscribe());
|
||||
}
|
||||
})
|
||||
tap((): void =>
|
||||
tracker.resolve((): void => subscription.unsubscribe())
|
||||
)
|
||||
)
|
||||
.subscribe(callback);
|
||||
}) as UnsubscribePromise;
|
||||
|
||||
@@ -114,9 +114,7 @@ export default class ApiRx extends ApiBase<'rxjs'> {
|
||||
|
||||
/**
|
||||
* @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 contructor. Can be either [[ApiOptions]] or [[WsProvider]]
|
||||
*
|
||||
* @example
|
||||
* <BR>
|
||||
*
|
||||
@@ -140,9 +138,7 @@ export default class ApiRx extends ApiBase<'rxjs'> {
|
||||
|
||||
/**
|
||||
* @description Create an instance of the ApiRx class
|
||||
*
|
||||
* @param options Options to create an instance. Can be either [[ApiOptions]] or [[WsProvider]]
|
||||
*
|
||||
* @example
|
||||
* <BR>
|
||||
*
|
||||
@@ -164,7 +160,7 @@ export default class ApiRx extends ApiBase<'rxjs'> {
|
||||
super(options, 'rxjs');
|
||||
|
||||
this._isReadyRx = from(
|
||||
// convinced you can observable from an event, however my mind groks this form better
|
||||
// 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);
|
||||
|
||||
@@ -31,7 +31,8 @@ describeE2E()('Rx e2e queries', (wsUrl: string): void => {
|
||||
});
|
||||
|
||||
it('makes a query at a specific block', (done): void => {
|
||||
(api.rpc.chain.getHeader() as Observable<Header>)
|
||||
api.rpc.chain
|
||||
.getHeader()
|
||||
.pipe(
|
||||
switchMap(({ hash }: Header): Observable<any> =>
|
||||
api.query.system.events.at(hash)
|
||||
|
||||
@@ -27,7 +27,8 @@ describeE2E()('Rx e2e transactions', (wsUrl: string): void => {
|
||||
});
|
||||
|
||||
it('makes a transfer', (done): void => {
|
||||
(api.query.system.accountNonce(keyring.bob_stash.address) as Observable<Index>)
|
||||
api.query.system
|
||||
.accountNonce<Index>(keyring.bob_stash.address)
|
||||
.pipe(
|
||||
first(),
|
||||
switchMap((nonce: Index): Observable<SubmittableResult> =>
|
||||
@@ -46,16 +47,17 @@ describeE2E()('Rx e2e transactions', (wsUrl: string): void => {
|
||||
|
||||
it('makes a proposal', (done): void => {
|
||||
const amount = calculateAccountDeposit(api);
|
||||
(api.query.system.accountNonce(keyring.bob_stash.address) as Observable<Index>)
|
||||
const proposal = api.tx.system && api.tx.system.setCode
|
||||
? api.tx.system.setCode(randomAsHex2097152) // since impl_version 94 https://github.com/paritytech/substrate/pull/2802
|
||||
: api.tx.consensus.setCode(randomAsHex(4096)); // impl_version 0 - 93
|
||||
|
||||
api.query.system
|
||||
.accountNonce<Index>(keyring.bob_stash.address)
|
||||
.pipe(
|
||||
first(),
|
||||
switchMap((nonce: Index): Observable<SubmittableResult> =>
|
||||
api.tx.democracy
|
||||
.propose(
|
||||
api.tx.system && api.tx.system.setCode
|
||||
? api.tx.system.setCode(randomAsHex2097152) // since impl_version 94 https://github.com/paritytech/substrate/pull/2802
|
||||
: api.tx.consensus.setCode(randomAsHex(4096)) // impl_version 0 - 93
|
||||
, amount)
|
||||
.propose(proposal, amount)
|
||||
.sign(keyring.bob_stash, { nonce })
|
||||
.send()
|
||||
)
|
||||
|
||||
@@ -7,7 +7,6 @@ import Text from './Text';
|
||||
type Mapper = (value: string) => string;
|
||||
|
||||
const ALLOWED_BOXES = ['Compact', 'Option', 'Vec'];
|
||||
|
||||
/**
|
||||
* @name Type
|
||||
* @description
|
||||
@@ -18,6 +17,47 @@ const ALLOWED_BOXES = ['Compact', 'Option', 'Vec'];
|
||||
export default class Type extends Text {
|
||||
private _originalLength: number;
|
||||
|
||||
private static _mappings: Mapper[] = [
|
||||
// alias <T::InherentOfflineReport as InherentOfflineReport>::Inherent -> InherentOfflineReport
|
||||
Type._alias('<T::InherentOfflineReport as InherentOfflineReport>::Inherent', 'InherentOfflineReport'),
|
||||
// alias TreasuryProposal from Proposal<T::AccountId, BalanceOf<T>>
|
||||
Type._alias('Proposal<T::AccountId, BalanceOf<T>>', 'TreasuryProposal'),
|
||||
// <T::Balance as HasCompact>
|
||||
Type._cleanupCompact(),
|
||||
// Remove all the trait prefixes
|
||||
Type._removeTraits(),
|
||||
// remove PairOf<T> -> (T, T)
|
||||
Type._removePairOf(),
|
||||
// remove boxing, `Box<Proposal>` -> `Proposal`
|
||||
Type._removeWrap('Box'),
|
||||
// remove generics, `MisbehaviorReport<Hash, BlockNumber>` -> `MisbehaviorReport`
|
||||
Type._removeGenerics(),
|
||||
// alias String -> Text (compat with jsonrpc methods)
|
||||
Type._alias('String', 'Text'),
|
||||
// alias () -> Null
|
||||
Type._alias('\\(\\)', 'Null'),
|
||||
// alias Vec<u8> -> Bytes
|
||||
Type._alias('Vec<u8>', 'Bytes'),
|
||||
// alias &[u8] -> Bytes
|
||||
Type._alias('&\\[u8\\]', 'Bytes'),
|
||||
// alias RawAddress -> Address
|
||||
Type._alias('RawAddress', 'Address'),
|
||||
// alias Lookup::Source to Address (_could_ be AccountId on certain chains)
|
||||
Type._alias('Lookup::Source', 'Address'),
|
||||
// alias Lookup::Target to AccountId (always the case)
|
||||
Type._alias('Lookup::Target', 'AccountId'),
|
||||
// alias for grandpa, as used in polkadot
|
||||
Type._alias('grandpa::AuthorityId', 'AuthorityId'),
|
||||
// specific for SessionIndex (could make this session::, but be conservative)
|
||||
Type._alias('session::SessionIndex', 'SessionIndex'),
|
||||
// HACK duplication between contracts & primitives, however contracts prefixed with exec
|
||||
Type._alias('exec::StorageKey', 'ContractStorageKey'),
|
||||
// flattens tuples with one value, `(AccountId)` -> `AccountId`
|
||||
Type._flattenSingleTuple(),
|
||||
// converts ::Type to Type, <T as Trait<I>>::Proposal -> ::Proposal
|
||||
Type._removeColonPrefix()
|
||||
];
|
||||
|
||||
public constructor (value: Text | Uint8Array | string = '') {
|
||||
// First decode it with Text
|
||||
const textValue = new Text(value);
|
||||
@@ -34,48 +74,7 @@ export default class Type extends Text {
|
||||
}
|
||||
|
||||
private static decodeType (value: string): string {
|
||||
const mappings: Mapper[] = [
|
||||
// alias <T::InherentOfflineReport as InherentOfflineReport>::Inherent -> InherentOfflineReport
|
||||
Type._alias('<T::InherentOfflineReport as InherentOfflineReport>::Inherent', 'InherentOfflineReport'),
|
||||
// alias TreasuryProposal from Proposal<T::AccountId, BalanceOf<T>>
|
||||
Type._alias('Proposal<T::AccountId, BalanceOf<T>>', 'TreasuryProposal'),
|
||||
// <T::Balance as HasCompact>
|
||||
Type._cleanupCompact(),
|
||||
// Remove all the trait prefixes
|
||||
Type._removeTraits(),
|
||||
// remove PairOf<T> -> (T, T)
|
||||
Type._removePairOf(),
|
||||
// remove boxing, `Box<Proposal>` -> `Proposal`
|
||||
Type._removeWrap('Box'),
|
||||
// remove generics, `MisbehaviorReport<Hash, BlockNumber>` -> `MisbehaviorReport`
|
||||
Type._removeGenerics(),
|
||||
// alias String -> Text (compat with jsonrpc methods)
|
||||
Type._alias('String', 'Text'),
|
||||
// alias () -> Null
|
||||
Type._alias('\\(\\)', 'Null'),
|
||||
// alias Vec<u8> -> Bytes
|
||||
Type._alias('Vec<u8>', 'Bytes'),
|
||||
// alias &[u8] -> Bytes
|
||||
Type._alias('&\\[u8\\]', 'Bytes'),
|
||||
// alias RawAddress -> Address
|
||||
Type._alias('RawAddress', 'Address'),
|
||||
// alias Lookup::Source to Address (_could_ be AccountId on certain chains)
|
||||
Type._alias('Lookup::Source', 'Address'),
|
||||
// alias Lookup::Target to AccountId (always the case)
|
||||
Type._alias('Lookup::Target', 'AccountId'),
|
||||
// alias for grandpa, as used in polkadot
|
||||
Type._alias('grandpa::AuthorityId', 'AuthorityId'),
|
||||
// specific for SessionIndex (could make this session::, but be conservative)
|
||||
Type._alias('session::SessionIndex', 'SessionIndex'),
|
||||
// HACK duplication between contracts & primitives, however contracts prefixed with exec
|
||||
Type._alias('exec::StorageKey', 'ContractStorageKey'),
|
||||
// flattens tuples with one value, `(AccountId)` -> `AccountId`
|
||||
Type._flattenSingleTuple(),
|
||||
// converts ::Type to Type, <T as Trait<I>>::Proposal -> ::Proposal
|
||||
Type._removeColonPrefix()
|
||||
];
|
||||
|
||||
return mappings.reduce((result, fn): string => {
|
||||
return Type._mappings.reduce((result, fn): string => {
|
||||
return fn(result);
|
||||
}, value).trim();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user