sender.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import BN = require('bn.js');
  2. import { ApiPromise } from '@polkadot/api';
  3. import { Index } from '@polkadot/types/interfaces';
  4. import { SubmittableExtrinsic } from '@polkadot/api/types';
  5. import { KeyringPair } from '@polkadot/keyring/types';
  6. export class Sender {
  7. private readonly api: ApiPromise;
  8. private static nonceMap: Map<string, BN> = new Map();
  9. constructor(api: ApiPromise) {
  10. this.api = api;
  11. }
  12. private async getNonce(address: string): Promise<BN> {
  13. let oncahinNonce: BN = new BN(0);
  14. if (!Sender.nonceMap.get(address)) {
  15. oncahinNonce = await this.api.query.system.accountNonce<Index>(address);
  16. }
  17. let nonce: BN | undefined = Sender.nonceMap.get(address);
  18. if (!nonce) {
  19. nonce = oncahinNonce;
  20. }
  21. const nextNonce: BN = nonce.addn(1);
  22. Sender.nonceMap.set(address, nextNonce);
  23. return nonce;
  24. }
  25. private clearNonce(address: string): void {
  26. Sender.nonceMap.delete(address);
  27. }
  28. public async signAndSend(
  29. tx: SubmittableExtrinsic<'promise'>,
  30. account: KeyringPair,
  31. expectFailure = false
  32. ): Promise<void> {
  33. return new Promise(async (resolve, reject) => {
  34. const nonce: BN = await this.getNonce(account.address);
  35. const signedTx = tx.sign(account, { nonce });
  36. await signedTx
  37. .send(async result => {
  38. if (result.status.isFinalized === true && result.events !== undefined) {
  39. result.events.forEach(event => {
  40. if (event.event.method === 'ExtrinsicFailed') {
  41. if (expectFailure) {
  42. resolve();
  43. } else {
  44. reject(new Error('Extrinsic failed unexpectedly'));
  45. }
  46. }
  47. });
  48. resolve();
  49. }
  50. if (result.status.isFuture) {
  51. console.log('nonce ' + nonce + ' for account ' + account.address + ' is in future');
  52. this.clearNonce(account.address);
  53. reject(new Error('Extrinsic nonce is in future'));
  54. }
  55. })
  56. .catch(error => {
  57. reject(error);
  58. });
  59. });
  60. }
  61. }