signer-noncemanager.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import { defineProperties } from "../utils/index.js";
  2. import { AbstractSigner } from "./abstract-signer.js";
  3. /**
  4. * A **NonceManager** wraps another [[Signer]] and automatically manages
  5. * the nonce, ensuring serialized and sequential nonces are used during
  6. * transaction.
  7. */
  8. export class NonceManager extends AbstractSigner {
  9. /**
  10. * The Signer being managed.
  11. */
  12. signer;
  13. #noncePromise;
  14. #delta;
  15. /**
  16. * Creates a new **NonceManager** to manage %%signer%%.
  17. */
  18. constructor(signer) {
  19. super(signer.provider);
  20. defineProperties(this, { signer });
  21. this.#noncePromise = null;
  22. this.#delta = 0;
  23. }
  24. async getAddress() {
  25. return this.signer.getAddress();
  26. }
  27. connect(provider) {
  28. return new NonceManager(this.signer.connect(provider));
  29. }
  30. async getNonce(blockTag) {
  31. if (blockTag === "pending") {
  32. if (this.#noncePromise == null) {
  33. this.#noncePromise = super.getNonce("pending");
  34. }
  35. const delta = this.#delta;
  36. return (await this.#noncePromise) + delta;
  37. }
  38. return super.getNonce(blockTag);
  39. }
  40. /**
  41. * Manually increment the nonce. This may be useful when managng
  42. * offline transactions.
  43. */
  44. increment() {
  45. this.#delta++;
  46. }
  47. /**
  48. * Resets the nonce, causing the **NonceManager** to reload the current
  49. * nonce from the blockchain on the next transaction.
  50. */
  51. reset() {
  52. this.#delta = 0;
  53. this.#noncePromise = null;
  54. }
  55. async sendTransaction(tx) {
  56. const noncePromise = this.getNonce("pending");
  57. this.increment();
  58. tx = await this.signer.populateTransaction(tx);
  59. tx.nonce = await noncePromise;
  60. // @TODO: Maybe handle interesting/recoverable errors?
  61. // Like don't increment if the tx was certainly not sent
  62. return await this.signer.sendTransaction(tx);
  63. }
  64. signTransaction(tx) {
  65. return this.signer.signTransaction(tx);
  66. }
  67. signMessage(message) {
  68. return this.signer.signMessage(message);
  69. }
  70. signTypedData(domain, types, value) {
  71. return this.signer.signTypedData(domain, types, value);
  72. }
  73. }
  74. //# sourceMappingURL=signer-noncemanager.js.map