@@ -78,7 +78,8 @@ type Sender struct {
78
78
head * types.Header
79
79
client * rpc.EthClient
80
80
81
- Opts * bind.TransactOpts
81
+ nonce uint64
82
+ Opts * bind.TransactOpts
82
83
83
84
unconfirmedTxs cmap.ConcurrentMap [string , * TxToConfirm ]
84
85
txToConfirmCh cmap.ConcurrentMap [string , chan * TxToConfirm ]
@@ -110,6 +111,12 @@ func NewSender(ctx context.Context, cfg *Config, client *rpc.EthClient, priv *ec
110
111
}
111
112
}
112
113
114
+ // Get the nonce
115
+ nonce , err := client .NonceAt (ctx , opts .From , nil )
116
+ if err != nil {
117
+ return nil , err
118
+ }
119
+
113
120
// Get the chain ID
114
121
head , err := client .HeaderByNumber (ctx , nil )
115
122
if err != nil {
@@ -121,13 +128,12 @@ func NewSender(ctx context.Context, cfg *Config, client *rpc.EthClient, priv *ec
121
128
Config : cfg ,
122
129
head : head ,
123
130
client : client ,
131
+ nonce : nonce ,
124
132
Opts : opts ,
125
133
unconfirmedTxs : cmap .New [* TxToConfirm ](),
126
134
txToConfirmCh : cmap .New [chan * TxToConfirm ](),
127
135
stopCh : make (chan struct {}),
128
136
}
129
- // Initialize the nonce
130
- sender .AdjustNonce (nil )
131
137
132
138
// Initialize the gas fee related fields
133
139
if err = sender .updateGasTipGasFee (head ); err != nil {
@@ -177,6 +183,10 @@ func (s *Sender) GetUnconfirmedTx(txID string) *types.Transaction {
177
183
178
184
// SendRawTransaction sends a transaction to the given Ethereum node.
179
185
func (s * Sender ) SendRawTransaction (nonce uint64 , target * common.Address , value * big.Int , data []byte ) (string , error ) {
186
+ if s .unconfirmedTxs .Count () >= unconfirmedTxsCap {
187
+ return "" , fmt .Errorf ("too many pending transactions" )
188
+ }
189
+
180
190
gasLimit := s .GasLimit
181
191
if gasLimit == 0 {
182
192
var err error
@@ -192,16 +202,36 @@ func (s *Sender) SendRawTransaction(nonce uint64, target *common.Address, value
192
202
return "" , err
193
203
}
194
204
}
195
- return s .SendTransaction (types .NewTx (& types.DynamicFeeTx {
196
- ChainID : s .client .ChainID ,
197
- To : target ,
198
- Nonce : nonce ,
199
- GasFeeCap : s .Opts .GasFeeCap ,
200
- GasTipCap : s .Opts .GasTipCap ,
201
- Gas : gasLimit ,
202
- Value : value ,
203
- Data : data ,
204
- }))
205
+
206
+ txID := uuid .New ()
207
+ txToConfirm := & TxToConfirm {
208
+ ID : txID ,
209
+ originalTx : & types.DynamicFeeTx {
210
+ ChainID : s .client .ChainID ,
211
+ To : target ,
212
+ Nonce : nonce ,
213
+ GasFeeCap : s .Opts .GasFeeCap ,
214
+ GasTipCap : s .Opts .GasTipCap ,
215
+ Gas : gasLimit ,
216
+ Value : value ,
217
+ Data : data ,
218
+ },
219
+ }
220
+
221
+ if err := s .send (txToConfirm , false ); err != nil && ! strings .Contains (err .Error (), "replacement transaction" ) {
222
+ log .Error ("Failed to send transaction" ,
223
+ "tx_id" , txID ,
224
+ "nonce" , txToConfirm .CurrentTx .Nonce (),
225
+ "err" , err ,
226
+ )
227
+ return "" , err
228
+ }
229
+
230
+ // Add the transaction to the unconfirmed transactions
231
+ s .unconfirmedTxs .Set (txID , txToConfirm )
232
+ s .txToConfirmCh .Set (txID , make (chan * TxToConfirm , 1 ))
233
+
234
+ return txID , nil
205
235
}
206
236
207
237
// SendTransaction sends a transaction to the given Ethereum node.
@@ -222,7 +252,7 @@ func (s *Sender) SendTransaction(tx *types.Transaction) (string, error) {
222
252
CurrentTx : tx ,
223
253
}
224
254
225
- if err := s .send (txToConfirm ); err != nil && ! strings .Contains (err .Error (), "replacement transaction" ) {
255
+ if err := s .send (txToConfirm , true ); err != nil && ! strings .Contains (err .Error (), "replacement transaction" ) {
226
256
log .Error ("Failed to send transaction" ,
227
257
"tx_id" , txID ,
228
258
"nonce" , txToConfirm .CurrentTx .Nonce (),
@@ -240,12 +270,19 @@ func (s *Sender) SendTransaction(tx *types.Transaction) (string, error) {
240
270
}
241
271
242
272
// send is the internal method to send the given transaction.
243
- func (s * Sender ) send (tx * TxToConfirm ) error {
273
+ func (s * Sender ) send (tx * TxToConfirm , resetNonce bool ) error {
244
274
s .mu .Lock ()
245
275
defer s .mu .Unlock ()
246
276
247
277
originalTx := tx .originalTx
248
278
279
+ if resetNonce {
280
+ // Set the nonce of the transaction.
281
+ if err := s .SetNonce (originalTx , false ); err != nil {
282
+ return err
283
+ }
284
+ }
285
+
249
286
for i := 0 ; i < nonceIncorrectRetrys ; i ++ {
250
287
// Retry when nonce is incorrect
251
288
rawTx , err := s .Opts .Signer (s .Opts .From , types .NewTx (originalTx ))
@@ -258,13 +295,21 @@ func (s *Sender) send(tx *TxToConfirm) error {
258
295
// Check if the error is nonce too low
259
296
if err != nil {
260
297
if strings .Contains (err .Error (), "nonce too low" ) {
261
- s .AdjustNonce (originalTx )
262
- log .Warn ("Nonce is incorrect, retry sending the transaction with new nonce" ,
263
- "tx_id" , tx .ID ,
264
- "nonce" , tx .CurrentTx .Nonce (),
265
- "hash" , rawTx .Hash (),
266
- "err" , err ,
267
- )
298
+ if err := s .SetNonce (originalTx , true ); err != nil {
299
+ log .Error ("Failed to set nonce when appear nonce too low" ,
300
+ "tx_id" , tx .ID ,
301
+ "nonce" , tx .CurrentTx .Nonce (),
302
+ "hash" , rawTx .Hash (),
303
+ "err" , err ,
304
+ )
305
+ } else {
306
+ log .Warn ("Nonce is incorrect, retry sending the transaction with new nonce" ,
307
+ "tx_id" , tx .ID ,
308
+ "nonce" , tx .CurrentTx .Nonce (),
309
+ "hash" , rawTx .Hash (),
310
+ "err" , err ,
311
+ )
312
+ }
268
313
continue
269
314
}
270
315
if strings .Contains (err .Error (), "replacement transaction underpriced" ) {
@@ -287,7 +332,7 @@ func (s *Sender) send(tx *TxToConfirm) error {
287
332
}
288
333
break
289
334
}
290
- s .Opts . Nonce = new (big. Int ). Add ( s . Opts . Nonce , common . Big1 )
335
+ s .nonce ++
291
336
return nil
292
337
}
293
338
@@ -340,7 +385,7 @@ func (s *Sender) resendUnconfirmedTxs() {
340
385
s .releaseUnconfirmedTx (id )
341
386
continue
342
387
}
343
- if err := s .send (unconfirmedTx ); err != nil {
388
+ if err := s .send (unconfirmedTx , true ); err != nil {
344
389
log .Warn (
345
390
"Failed to resend the transaction" ,
346
391
"tx_id" , id ,
@@ -390,7 +435,7 @@ func (s *Sender) checkPendingTransactionsConfirmation() {
390
435
}
391
436
pendingTx .Receipt = receipt
392
437
if receipt .Status != types .ReceiptStatusSuccessful {
393
- pendingTx .Err = fmt .Errorf ("transaction reverted , hash: %s" , receipt .TxHash )
438
+ pendingTx .Err = fmt .Errorf ("transaction status is failed , hash: %s" , receipt .TxHash )
394
439
s .releaseUnconfirmedTx (id )
395
440
continue
396
441
}
0 commit comments