123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- import BN from 'bn.js';
- import { ApiPromise } from '@polkadot/api';
- import { Index } from '@polkadot/types/interfaces';
- import { SubmittableExtrinsic } from '@polkadot/api/types';
- import { KeyringPair } from '@polkadot/keyring/types';
- export class Sender {
- private readonly api: ApiPromise;
- private static nonceMap: Map<string, BN> = new Map();
- constructor(api: ApiPromise) {
- this.api = api;
- }
- private async getNonce(address: string): Promise<BN> {
- let oncahinNonce: BN = new BN(0);
- if (!Sender.nonceMap.get(address)) {
- oncahinNonce = await this.api.query.system.accountNonce<Index>(address);
- }
- let nonce: BN | undefined = Sender.nonceMap.get(address);
- if (!nonce) {
- nonce = oncahinNonce;
- }
- const nextNonce: BN = nonce.addn(1);
- Sender.nonceMap.set(address, nextNonce);
- return nonce;
- }
- private clearNonce(address: string): void {
- Sender.nonceMap.delete(address);
- }
- public async signAndSend(
- tx: SubmittableExtrinsic<'promise'>,
- account: KeyringPair,
- expectFailure = false
- ): Promise<void> {
- return new Promise(async (resolve, reject) => {
- const nonce: BN = await this.getNonce(account.address);
- const signedTx = tx.sign(account, { nonce });
- await signedTx
- .send(async result => {
- if (result.status.isFinalized === true && result.events !== undefined) {
- result.events.forEach(event => {
- if (event.event.method === 'ExtrinsicFailed') {
- if (expectFailure) {
- resolve();
- } else {
- reject(new Error('Extrinsic failed unexpectedly'));
- }
- }
- });
- resolve();
- }
- if (result.status.isFuture) {
- console.log('nonce ' + nonce + ' for account ' + account.address + ' is in future');
- this.clearNonce(account.address);
- reject(new Error('Extrinsic nonce is in future'));
- }
- })
- .catch(error => {
- reject(error);
- });
- });
- }
- }
|