2019-05-15 01:25:46 +03:00
|
|
|
"use strict"
|
|
|
|
|
|
|
|
import { ethers } from "ethers";
|
|
|
|
|
2019-10-19 14:02:48 +03:00
|
|
|
// @TODO: Keep a per-NonceManager pool of sent but unmined transactions for
|
|
|
|
// rebroadcasting, in case we overrun the transaction pool
|
|
|
|
|
2019-05-15 01:25:46 +03:00
|
|
|
export class NonceManager extends ethers.Signer {
|
|
|
|
readonly signer: ethers.Signer;
|
|
|
|
|
2019-10-19 14:02:48 +03:00
|
|
|
_initialPromise: Promise<number>;
|
|
|
|
_deltaCount: number;
|
2019-05-15 01:25:46 +03:00
|
|
|
|
|
|
|
constructor(signer: ethers.Signer) {
|
|
|
|
super();
|
2019-10-19 14:02:48 +03:00
|
|
|
this._deltaCount = 0;
|
2019-05-15 01:25:46 +03:00
|
|
|
ethers.utils.defineReadOnly(this, "signer", signer);
|
2021-03-08 02:12:39 +03:00
|
|
|
ethers.utils.defineReadOnly(this, "provider", signer.provider || null);
|
2020-04-04 04:33:56 +03:00
|
|
|
}
|
|
|
|
|
2019-05-15 01:25:46 +03:00
|
|
|
connect(provider: ethers.providers.Provider): NonceManager {
|
|
|
|
return new NonceManager(this.signer.connect(provider));
|
|
|
|
}
|
|
|
|
|
|
|
|
getAddress(): Promise<string> {
|
|
|
|
return this.signer.getAddress();
|
|
|
|
}
|
|
|
|
|
|
|
|
getTransactionCount(blockTag?: ethers.providers.BlockTag): Promise<number> {
|
|
|
|
if (blockTag === "pending") {
|
2019-10-19 14:02:48 +03:00
|
|
|
if (!this._initialPromise) {
|
|
|
|
this._initialPromise = this.signer.getTransactionCount("pending");
|
2019-05-15 01:25:46 +03:00
|
|
|
}
|
2019-10-19 14:02:48 +03:00
|
|
|
const deltaCount = this._deltaCount;
|
|
|
|
return this._initialPromise.then((initial) => (initial + deltaCount));
|
2019-05-15 01:25:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return this.signer.getTransactionCount(blockTag);
|
|
|
|
}
|
|
|
|
|
|
|
|
setTransactionCount(transactionCount: ethers.BigNumberish | Promise<ethers.BigNumberish>): void {
|
2019-10-19 14:02:48 +03:00
|
|
|
this._initialPromise = Promise.resolve(transactionCount).then((nonce) => {
|
2019-05-15 01:25:46 +03:00
|
|
|
return ethers.BigNumber.from(nonce).toNumber();
|
|
|
|
});
|
2019-10-19 14:02:48 +03:00
|
|
|
this._deltaCount = 0;
|
2019-05-15 01:25:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
incrementTransactionCount(count?: number): void {
|
2019-10-19 14:02:48 +03:00
|
|
|
this._deltaCount += (count ? count: 1);
|
2019-05-15 01:25:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
signMessage(message: ethers.Bytes | string): Promise<string> {
|
|
|
|
return this.signer.signMessage(message);;
|
|
|
|
}
|
|
|
|
|
2020-06-01 11:46:37 +03:00
|
|
|
signTransaction(transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>): Promise<string> {
|
2019-05-15 01:25:46 +03:00
|
|
|
return this.signer.signTransaction(transaction);
|
|
|
|
}
|
|
|
|
|
2020-06-01 11:46:37 +03:00
|
|
|
sendTransaction(transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>): Promise<ethers.providers.TransactionResponse> {
|
2019-05-15 01:25:46 +03:00
|
|
|
if (transaction.nonce == null) {
|
|
|
|
transaction = ethers.utils.shallowCopy(transaction);
|
2019-10-19 14:02:48 +03:00
|
|
|
transaction.nonce = this.getTransactionCount("pending");
|
|
|
|
this.incrementTransactionCount();
|
|
|
|
} else {
|
|
|
|
this.setTransactionCount(transaction.nonce);
|
2019-05-15 01:25:46 +03:00
|
|
|
}
|
|
|
|
|
2019-10-19 14:02:48 +03:00
|
|
|
return this.signer.sendTransaction(transaction).then((tx) => {
|
|
|
|
return tx;
|
|
|
|
});
|
2019-05-15 01:25:46 +03:00
|
|
|
}
|
|
|
|
}
|