Add paymentInfo to submittables (#1582)
* Add paymentInfo to submittables * Cleanup paymentInfo call * Use 0x42...42 dummy sigs * Re-add paymentInfo to submittable * Add correct signFake interfaces * CHANGELOG
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
- Add support for `BTreeSet` (Thanks to https://github.com/satellitex)
|
||||
- Add support for Metadata v10
|
||||
- Add support for latest Polkadot/Substrate types
|
||||
- Add `paymentInfo` to submittables to calculate fees
|
||||
|
||||
# 0.99.1
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// 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, Hash, Header, Index } from '@polkadot/types/interfaces';
|
||||
import { AccountId, Address, Call, ExtrinsicEra, ExtrinsicStatus, Hash, Header, Index, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
|
||||
import { Callback, Codec, Constructor, IKeyringPair, Registry, SignatureOptions } from '@polkadot/types/types';
|
||||
import { ApiInterfaceRx, ApiTypes, SignerResult } from '../types';
|
||||
import { SignerOptions, SubmittableExtrinsic, SubmittableResultImpl, SubmittableResultResult, SubmittableResultSubscription, SubmittableThis } from './types';
|
||||
import { SignerOptions, SubmittableExtrinsic, SubmittablePaymentResult, SubmittableResultImpl, SubmittableResultResult, SubmittableResultSubscription, SubmittableThis } from './types';
|
||||
|
||||
import { Observable, combineLatest, from, of } from 'rxjs';
|
||||
import { first, map, mapTo, mergeMap, switchMap, tap } from 'rxjs/operators';
|
||||
@@ -49,6 +49,29 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
|
||||
this._ignoreStatusCb = apiType === 'rxjs';
|
||||
}
|
||||
|
||||
// calculate the payment info for this transaction (if signed and submitted)
|
||||
public paymentInfo (account: IKeyringPair | string | AccountId | Address, options?: Partial<SignerOptions>): SubmittablePaymentResult<ApiType> {
|
||||
const [allOptions] = this._makeSignAndSendOptions(options);
|
||||
const address = isKeyringPair(account) ? account.address : account.toString();
|
||||
|
||||
return this._decorateMethod(
|
||||
(): Observable<RuntimeDispatchInfo> =>
|
||||
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, {});
|
||||
|
||||
// add a fake signature to the extrinsic
|
||||
this.signFake(address, signOptions);
|
||||
|
||||
return this._api.rpc.payment.queryInfo(this.toHex());
|
||||
})
|
||||
)
|
||||
)();
|
||||
}
|
||||
|
||||
// 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), {}));
|
||||
|
||||
@@ -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, ExtrinsicStatus, EventRecord, Hash } from '@polkadot/types/interfaces';
|
||||
import { AccountId, Address, ExtrinsicStatus, EventRecord, Hash, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
|
||||
import { AnyNumber, AnyU8a, Callback, IExtrinsic, IExtrinsicEra, IKeyringPair, SignatureOptions } from '@polkadot/types/types';
|
||||
import { ApiTypes } from '../types';
|
||||
|
||||
@@ -24,6 +24,11 @@ export interface SubmittableResultValue {
|
||||
status: ExtrinsicStatus;
|
||||
}
|
||||
|
||||
export type SubmittablePaymentResult<ApiType extends ApiTypes> =
|
||||
ApiType extends 'rxjs'
|
||||
? Observable<RuntimeDispatchInfo>
|
||||
: Promise<RuntimeDispatchInfo>;
|
||||
|
||||
export type SubmittableResultResult<ApiType extends ApiTypes> =
|
||||
ApiType extends 'rxjs'
|
||||
? Observable<SubmittableResultImpl>
|
||||
@@ -47,6 +52,8 @@ export interface SignerOptions {
|
||||
}
|
||||
|
||||
export interface SubmittableExtrinsic<ApiType extends ApiTypes> extends IExtrinsic {
|
||||
paymentInfo (account: IKeyringPair | string | AccountId | Address, options?: Partial<SignerOptions>): SubmittablePaymentResult<ApiType>;
|
||||
|
||||
send(): SubmittableResultResult<ApiType>;
|
||||
|
||||
send(statusCb: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
|
||||
|
||||
@@ -252,11 +252,20 @@ export default class Extrinsic extends Base<ExtrinsicVx | ExtrinsicUnknown> impl
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @describe Adds a fake signature to the extrinsic
|
||||
*/
|
||||
public signFake (signer: Address | Uint8Array | string, options: SignatureOptions): Extrinsic {
|
||||
(this.raw as ExtrinsicVx).signFake(signer, options);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns a hex string representation of the value
|
||||
*/
|
||||
public toHex (): string {
|
||||
return u8aToHex(this.toU8a());
|
||||
public toHex (isBare?: boolean): string {
|
||||
return u8aToHex(this.toU8a(isBare));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,10 +284,12 @@ export default class Extrinsic extends Base<ExtrinsicVx | ExtrinsicUnknown> impl
|
||||
|
||||
/**
|
||||
* @description Encodes the value as a Uint8Array as per the SCALE specifications
|
||||
* @param isBare true when the value has none of the type-specific prefixes (internal)
|
||||
* @param isBare true when the value is not length-prefixed
|
||||
*/
|
||||
public toU8a (isBare?: boolean): Uint8Array {
|
||||
const encoded = u8aConcat(new Uint8Array([this.version]), this.raw.toU8a(isBare));
|
||||
// we do not apply bare to the internal values, rather this only determines out length addition,
|
||||
// where we strip all lengths this creates an un-decodable extrinsic
|
||||
const encoded = u8aConcat(new Uint8Array([this.version]), this.raw.toU8a());
|
||||
|
||||
return isBare
|
||||
? encoded
|
||||
|
||||
@@ -96,4 +96,13 @@ export default class ExtrinsicV1 extends Struct implements IExtrinsicImpl {
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @describe Adds a fake signature to the extrinsic
|
||||
*/
|
||||
public signFake (signer: Address | Uint8Array | string, options: SignatureOptions): ExtrinsicV1 {
|
||||
this.signature.signFake(this.method, signer, options);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,11 +116,10 @@ export default class ExtrinsicSignatureV1 extends Struct implements IExtrinsicSi
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Generate a payload and applies the signature from a keypair
|
||||
* @description Creates a payload from the supplied options
|
||||
*/
|
||||
public sign (method: Call, account: IKeyringPair, { blockHash, era, genesisHash, nonce }: SignatureOptions): IExtrinsicSignature {
|
||||
const signer = createType(this.registry, 'Address', account.publicKey);
|
||||
const payload = new ExtrinsicPayloadV1(this.registry, {
|
||||
public createPayload (method: Call, { blockHash, era, genesisHash, nonce }: SignatureOptions): ExtrinsicPayloadV1 {
|
||||
return new ExtrinsicPayloadV1(this.registry, {
|
||||
blockHash,
|
||||
era: era || IMMORTAL_ERA,
|
||||
genesisHash,
|
||||
@@ -129,11 +128,30 @@ export default class ExtrinsicSignatureV1 extends Struct implements IExtrinsicSi
|
||||
specVersion: 0, // unused for v1, added for compat
|
||||
tip: 0
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Generate a payload and applies the signature from a keypair
|
||||
*/
|
||||
public sign (method: Call, account: IKeyringPair, options: SignatureOptions): IExtrinsicSignature {
|
||||
const signer = createType(this.registry, 'Address', account.publicKey);
|
||||
const payload = this.createPayload(method, options);
|
||||
const signature = createType(this.registry, 'Signature', payload.sign(account));
|
||||
|
||||
return this.injectSignature(signer, signature, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Generate a payload and applies a fake signature
|
||||
*/
|
||||
public signFake (method: Call, address: Address | Uint8Array | string, options: SignatureOptions): IExtrinsicSignature {
|
||||
const signer = createType(this.registry, 'Address', address);
|
||||
const payload = this.createPayload(method, options);
|
||||
const signature = createType(this.registry, 'Signature', new Uint8Array(64).fill(0x42));
|
||||
|
||||
return this.injectSignature(signer, signature, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Encodes the value as a Uint8Array as per the SCALE specifications
|
||||
* @param isBare true when the value has none of the type-specific prefixes (internal)
|
||||
|
||||
@@ -98,4 +98,13 @@ export default class ExtrinsicV2 extends Struct implements IExtrinsicImpl {
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @describe Adds a fake signature to the extrinsic
|
||||
*/
|
||||
public signFake (signer: Address | Uint8Array | string, options: SignatureOptions): ExtrinsicV2 {
|
||||
this.signature.signFake(this.method, signer, options);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,11 +113,10 @@ export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSi
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Generate a payload and applies the signature from a keypair
|
||||
* @description Creates a payload from the supplied options
|
||||
*/
|
||||
public sign (method: Call, account: IKeyringPair, { blockHash, era, genesisHash, nonce, tip }: SignatureOptions): IExtrinsicSignature {
|
||||
const signer = createType(this.registry, 'Address', account.publicKey);
|
||||
const payload = new ExtrinsicPayloadV2(this.registry, {
|
||||
public createPayload (method: Call, { blockHash, era, genesisHash, nonce, tip }: SignatureOptions): ExtrinsicPayloadV2 {
|
||||
return new ExtrinsicPayloadV2(this.registry, {
|
||||
blockHash,
|
||||
era: era || IMMORTAL_ERA,
|
||||
genesisHash,
|
||||
@@ -126,11 +125,30 @@ export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSi
|
||||
specVersion: 0, // unused for v2
|
||||
tip: tip || 0
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Generate a payload and applies the signature from a keypair
|
||||
*/
|
||||
public sign (method: Call, account: IKeyringPair, options: SignatureOptions): IExtrinsicSignature {
|
||||
const signer = createType(this.registry, 'Address', account.publicKey);
|
||||
const payload = this.createPayload(method, options);
|
||||
const signature = createType(this.registry, 'Signature', payload.sign(account));
|
||||
|
||||
return this.injectSignature(signer, signature, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Generate a payload and applies a fake signature
|
||||
*/
|
||||
public signFake (method: Call, address: Address | Uint8Array | string, options: SignatureOptions): IExtrinsicSignature {
|
||||
const signer = createType(this.registry, 'Address', address);
|
||||
const payload = this.createPayload(method, options);
|
||||
const signature = createType(this.registry, 'Signature', new Uint8Array(64).fill(0x42));
|
||||
|
||||
return this.injectSignature(signer, signature, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Encodes the value as a Uint8Array as per the SCALE specifications
|
||||
* @param isBare true when the value has none of the type-specific prefixes (internal)
|
||||
|
||||
@@ -98,4 +98,13 @@ export default class ExtrinsicV3 extends Struct implements IExtrinsicImpl {
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @describe Adds a fake signature to the extrinsic
|
||||
*/
|
||||
public signFake (signer: Address | Uint8Array | string, options: SignatureOptions): ExtrinsicV3 {
|
||||
this.signature.signFake(this.method, signer, options);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,11 +28,10 @@ export default class ExtrinsicSignatureV3 extends ExtrinsicSignatureV2 {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Generate a payload and pplies the signature from a keypair
|
||||
* @description Creates a payload from the supplied options
|
||||
*/
|
||||
public sign (method: Call, account: IKeyringPair, { blockHash, era, genesisHash, nonce, runtimeVersion: { specVersion }, tip }: SignatureOptions): IExtrinsicSignature {
|
||||
const signer = createType(this.registry, 'Address', account.publicKey);
|
||||
const payload = new ExtrinsicPayloadV3(this.registry, {
|
||||
public createPayload (method: Call, { blockHash, era, genesisHash, nonce, runtimeVersion: { specVersion }, tip }: SignatureOptions): ExtrinsicPayloadV3 {
|
||||
return new ExtrinsicPayloadV3(this.registry, {
|
||||
blockHash,
|
||||
era: era || IMMORTAL_ERA,
|
||||
genesisHash,
|
||||
@@ -41,8 +40,27 @@ export default class ExtrinsicSignatureV3 extends ExtrinsicSignatureV2 {
|
||||
specVersion,
|
||||
tip: tip || 0
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Generate a payload and applies the signature from a keypair
|
||||
*/
|
||||
public sign (method: Call, account: IKeyringPair, options: SignatureOptions): IExtrinsicSignature {
|
||||
const signer = createType(this.registry, 'Address', account.publicKey);
|
||||
const payload = this.createPayload(method, options);
|
||||
const signature = createType(this.registry, 'Signature', payload.sign(account));
|
||||
|
||||
return this.injectSignature(signer, signature, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Generate a payload and applies a fake signature
|
||||
*/
|
||||
public signFake (method: Call, address: Address | Uint8Array | string, options: SignatureOptions): IExtrinsicSignature {
|
||||
const signer = createType(this.registry, 'Address', address);
|
||||
const payload = this.createPayload(method, options);
|
||||
const signature = createType(this.registry, 'Signature', new Uint8Array(64).fill(0x42));
|
||||
|
||||
return this.injectSignature(signer, signature, payload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,4 +98,13 @@ export default class ExtrinsicV4 extends Struct implements IExtrinsicImpl {
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @describe Adds a fake signature to the extrinsic
|
||||
*/
|
||||
public signFake (signer: Address | Uint8Array | string, options: SignatureOptions): ExtrinsicV4 {
|
||||
this.signature.signFake(this.method, signer, options);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import { Address, Balance, Call, EcdsaSignature, Ed25519Signature, ExtrinsicEra,
|
||||
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, Registry, SignatureOptions } from '../../../types';
|
||||
import { ExtrinsicSignatureOptions } from '../types';
|
||||
|
||||
import { u8aConcat } from '@polkadot/util';
|
||||
|
||||
import { createType } from '../../../codec/create';
|
||||
import Compact from '../../../codec/Compact';
|
||||
import Struct from '../../../codec/Struct';
|
||||
@@ -120,11 +122,10 @@ export default class ExtrinsicSignatureV4 extends Struct implements IExtrinsicSi
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Generate a payload and applies the signature from a keypair
|
||||
* @description Creates a payload from the supplied options
|
||||
*/
|
||||
public sign (method: Call, account: IKeyringPair, { blockHash, era, genesisHash, nonce, runtimeVersion: { specVersion }, tip }: SignatureOptions): IExtrinsicSignature {
|
||||
const signer = createType(this.registry, 'Address', account.publicKey);
|
||||
const payload = new ExtrinsicPayloadV4(this.registry, {
|
||||
public createPayload (method: Call, { blockHash, era, genesisHash, nonce, runtimeVersion: { specVersion }, tip }: SignatureOptions): ExtrinsicPayloadV4 {
|
||||
return new ExtrinsicPayloadV4(this.registry, {
|
||||
blockHash,
|
||||
era: era || IMMORTAL_ERA,
|
||||
genesisHash,
|
||||
@@ -133,11 +134,30 @@ export default class ExtrinsicSignatureV4 extends Struct implements IExtrinsicSi
|
||||
specVersion,
|
||||
tip: tip || 0
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Generate a payload and applies the signature from a keypair
|
||||
*/
|
||||
public sign (method: Call, account: IKeyringPair, options: SignatureOptions): IExtrinsicSignature {
|
||||
const signer = createType(this.registry, 'Address', account.publicKey);
|
||||
const payload = this.createPayload(method, options);
|
||||
const signature = createType(this.registry, 'MultiSignature', payload.sign(account));
|
||||
|
||||
return this.injectSignature(signer, signature, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Generate a payload and applies a fake signature
|
||||
*/
|
||||
public signFake (method: Call, address: Address | Uint8Array | string, options: SignatureOptions): IExtrinsicSignature {
|
||||
const signer = createType(this.registry, 'Address', address);
|
||||
const payload = this.createPayload(method, options);
|
||||
const signature = createType(this.registry, 'MultiSignature', u8aConcat(new Uint8Array([1]), new Uint8Array(64).fill(0x42)));
|
||||
|
||||
return this.injectSignature(signer, signature, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Encodes the value as a Uint8Array as per the SCALE specifications
|
||||
* @param isBare true when the value has none of the type-specific prefixes (internal)
|
||||
|
||||
@@ -210,6 +210,7 @@ export interface ExtrinsicPayloadValue {
|
||||
export interface IExtrinsicSignature extends ExtrinsicSignatureBase, Codec {
|
||||
addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | string, payload: Uint8Array | string): IExtrinsicSignature;
|
||||
sign (method: Call, account: IKeyringPair, options: SignatureOptions): IExtrinsicSignature;
|
||||
signFake (method: Call, address: Address | Uint8Array | string, options: SignatureOptions): IExtrinsicSignature;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
|
||||
@@ -222,6 +223,7 @@ export interface IExtrinsicEra extends Codec {
|
||||
interface IExtrinsicSignable<T> {
|
||||
addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | string, payload: ExtrinsicPayloadValue | Uint8Array | string): T;
|
||||
sign (account: IKeyringPair, options: SignatureOptions): T;
|
||||
signFake (address: Address | Uint8Array | string, options: SignatureOptions): T;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
|
||||
|
||||
Reference in New Issue
Block a user