11const { NonceManager } = require ( "@ethersproject/experimental" ) ;
2+ const { parseTransaction } = require ( "ethers/lib/utils" ) ;
23
34class ExtendedNonceManager extends NonceManager {
45 constructor ( signer ) {
@@ -9,8 +10,23 @@ class ExtendedNonceManager extends NonceManager {
910 Object . keys ( this . signedTransactions ) . map ( async ( txHash ) => {
1011 const nodeTx = await this . signer . provider . getTransaction ( txHash ) ;
1112 if ( ! nodeTx ) {
12- this . signer . provider . sendTransaction ( this . signedTransactions [ txHash ] ) ;
13- return ;
13+ const txCount = await this . signer . getTransactionCount ( "pending" ) ;
14+ const parsedTransaction = parseTransaction ( this . signedTransactions [ txHash ] ) ;
15+ if ( parsedTransaction . nonce < txCount ) {
16+ // It's not been mined, but it's been replaced by another tx.
17+ // Resend, with a new nonce
18+ delete this . signedTransactions [ txHash ] ;
19+ this . sendTransaction ( {
20+ from : parsedTransaction . from ,
21+ to : parsedTransaction . to ,
22+ value : parsedTransaction . value ,
23+ data : parsedTransaction . data ,
24+ } ) ;
25+ } else {
26+ // No reason to think it's been replaced, so rebroadcast.
27+ this . signer . provider . sendTransaction ( this . signedTransactions [ txHash ] ) ;
28+ return ;
29+ }
1430 }
1531 if ( nodeTx . blockNumber ) {
1632 // It's been mined, so forget it.
@@ -22,29 +38,18 @@ class ExtendedNonceManager extends NonceManager {
2238 }
2339
2440 async sendTransaction ( transactionRequest ) {
25- // What nonce are we going to attach to this?
26- // Definitely not any we've sent and are pending
27- // const pendingNonces = Object.keys(this.signedTransactions).map((txhash) => this.signedTransactions[txhash].nonce);
28-
29- // At least whatever the endpoint says, or whatever we've already sent if higher
30- let nonce = await this . signer . getTransactionCount ( ) ;
31-
32- // Note the order we did the above two lines in - if a tx is mined between these two lines,
33- // and got removed by the `on block` handler above, by doing it in this order we won't be tripped up
34- // And we'll skip any nonces we've already used
35- while (
36- Object . keys ( this . signedTransactions )
37- . map ( ( txhash ) => this . signedTransactions [ txhash ] . nonce )
38- . includes ( nonce )
39- ) {
40- nonce += 1 ;
41+ try {
42+ const populatedTransaction = await this . populateTransaction ( transactionRequest ) ;
43+ const signedTransaction = await this . signTransaction ( populatedTransaction ) ;
44+ const response = super . sendTransaction ( transactionRequest ) ;
45+ const tx = await response ;
46+ this . signedTransactions [ tx . hash ] = signedTransaction ;
47+ return response ;
48+ } catch ( e ) {
49+ const txCount = await this . signer . getTransactionCount ( "pending" ) ;
50+ this . setTransactionCount ( txCount ) ;
51+ return this . sendTransaction ( transactionRequest ) ;
4152 }
42- transactionRequest . nonce = nonce ; // eslint-disable-line no-param-reassign
43- this . nonce = nonce + 1 ;
44- const response = super . sendTransaction ( transactionRequest ) ;
45- const tx = await response ;
46- this . signedTransactions [ tx . hash ] = transactionRequest ;
47- return response ;
4853 }
4954}
5055
0 commit comments