@@ -3,6 +3,7 @@ package sender
3
3
import (
4
4
"context"
5
5
"crypto/ecdsa"
6
+ "errors"
6
7
"fmt"
7
8
"math/big"
8
9
"os"
@@ -13,7 +14,6 @@ import (
13
14
"github.com/ethereum/go-ethereum"
14
15
"github.com/ethereum/go-ethereum/accounts/abi/bind"
15
16
"github.com/ethereum/go-ethereum/common"
16
- "github.com/ethereum/go-ethereum/common/math"
17
17
"github.com/ethereum/go-ethereum/core/types"
18
18
"github.com/ethereum/go-ethereum/log"
19
19
cmap "github.com/orcaman/concurrent-map/v2"
@@ -28,33 +28,26 @@ var (
28
28
nonceIncorrectRetrys = 3
29
29
unconfirmedTxsCheckInternal = 2 * time .Second
30
30
chainHeadFetchInterval = 3 * time .Second
31
- errTimeoutInMempool = fmt .Errorf ("transaction in mempool for too long" )
32
- DefaultConfig = & Config {
33
- ConfirmationDepth : 0 ,
34
- MaxRetrys : 0 ,
35
- MaxWaitingTime : 5 * time .Minute ,
36
- GasGrowthRate : 50 ,
37
- MaxGasFee : math .MaxUint64 ,
38
- MaxBlobFee : math .MaxUint64 ,
39
- }
31
+ errTimeoutInMempool = errors .New ("transaction in mempool for too long" )
32
+ errToManyPendings = errors .New ("too many pending transactions" )
40
33
)
41
34
42
35
// Config represents the configuration of the transaction sender.
43
36
type Config struct {
44
37
// The minimum block confirmations to wait to confirm a transaction.
45
- ConfirmationDepth uint64
38
+ ConfirmationDepth uint64 `default:"0"`
46
39
// The maximum retry times when sending transactions.
47
- MaxRetrys uint64
40
+ MaxRetrys uint64 `default:"0"`
48
41
// The maximum waiting time for the inclusion of transactions.
49
- MaxWaitingTime time.Duration
50
-
42
+ MaxWaitingTime time.Duration `default:"5m"`
51
43
// The gas limit for transactions.
52
- GasLimit uint64
44
+ GasLimit uint64 `default:"0"`
53
45
// The gas rate to increase the gas price, 20 means 20% gas growth rate.
54
- GasGrowthRate uint64
46
+ GasGrowthRate uint64 `default:"50"`
55
47
// The maximum gas fee can be used when sending transactions.
56
- MaxGasFee uint64
57
- MaxBlobFee uint64
48
+ MaxGasFee uint64 `default:"0xffffffffffffffff"` // Use `math.MaxUint64` as default value
49
+ // The maximum blob gas fee can be used when sending transactions.
50
+ MaxBlobFee uint64 `default:"0xffffffffffffffff"` // Use `math.MaxUint64` as default value
58
51
}
59
52
60
53
// TxToConfirm represents a transaction which is waiting for its confirmation.
@@ -149,6 +142,7 @@ func NewSender(ctx context.Context, cfg *Config, client *rpc.EthClient, priv *ec
149
142
return sender , nil
150
143
}
151
144
145
+ // CLose closes the sender.
152
146
func (s * Sender ) Close () {
153
147
close (s .stopCh )
154
148
s .wg .Wait ()
@@ -205,13 +199,19 @@ func (s *Sender) SendRawTransaction(
205
199
data []byte ,
206
200
sidecar * types.BlobTxSidecar ,
207
201
) (string , error ) {
202
+ // If there are too many pending transactions to be confirmed, return an error here.
208
203
if s .unconfirmedTxs .Count () >= unconfirmedTxsCap {
209
- return "" , fmt .Errorf ("too many pending transactions" )
204
+ return "" , errToManyPendings
205
+ }
206
+ if nonce == 0 {
207
+ nonce = s .nonce
210
208
}
211
209
212
210
var (
213
211
originalTx types.TxData
214
212
opts = s .GetOpts ()
213
+ gasLimit = s .GasLimit
214
+ err error
215
215
)
216
216
if sidecar != nil {
217
217
opts .Value = value
@@ -222,28 +222,26 @@ func (s *Sender) SendRawTransaction(
222
222
if err != nil {
223
223
return "" , err
224
224
}
225
- blobTx .Nonce = setDefault ( nonce , s . nonce )
225
+ blobTx .Nonce = nonce
226
226
originalTx = blobTx
227
227
} else {
228
- gasLimit := s .GasLimit
229
228
if gasLimit == 0 {
230
- var err error
231
- gasLimit , err = s .client .EstimateGas (s .ctx , ethereum.CallMsg {
229
+ if gasLimit , err = s .client .EstimateGas (s .ctx , ethereum.CallMsg {
232
230
From : opts .From ,
233
231
To : target ,
234
232
Value : value ,
235
233
Data : data ,
236
234
GasTipCap : opts .GasTipCap ,
237
235
GasFeeCap : opts .GasFeeCap ,
238
- })
239
- if err != nil {
236
+ }); err != nil {
240
237
return "" , err
241
238
}
242
239
}
240
+
243
241
originalTx = & types.DynamicFeeTx {
244
242
ChainID : s .client .ChainID ,
245
243
To : target ,
246
- Nonce : setDefault ( nonce , s . nonce ) ,
244
+ Nonce : nonce ,
247
245
GasFeeCap : opts .GasFeeCap ,
248
246
GasTipCap : opts .GasTipCap ,
249
247
Gas : gasLimit ,
@@ -252,12 +250,11 @@ func (s *Sender) SendRawTransaction(
252
250
}
253
251
}
254
252
255
- txToConfirm := & TxToConfirm {
256
- originalTx : originalTx ,
257
- }
253
+ txToConfirm := & TxToConfirm {originalTx : originalTx }
258
254
259
255
if err := s .send (txToConfirm , false ); err != nil && ! strings .Contains (err .Error (), "replacement transaction" ) {
260
- log .Error ("Failed to send transaction" ,
256
+ log .Error (
257
+ "Failed to send transaction" ,
261
258
"txId" , txToConfirm .ID ,
262
259
"nonce" , nonce ,
263
260
"err" , err ,
@@ -276,18 +273,15 @@ func (s *Sender) SendRawTransaction(
276
273
// SendTransaction sends a transaction to the given Ethereum node.
277
274
func (s * Sender ) SendTransaction (tx * types.Transaction ) (string , error ) {
278
275
if s .unconfirmedTxs .Count () >= unconfirmedTxsCap {
279
- return "" , fmt . Errorf ( "too many pending transactions" )
276
+ return "" , errToManyPendings
280
277
}
281
278
282
279
txData , err := s .buildTxData (tx )
283
280
if err != nil {
284
281
return "" , err
285
282
}
286
283
287
- txToConfirm := & TxToConfirm {
288
- originalTx : txData ,
289
- CurrentTx : tx ,
290
- }
284
+ txToConfirm := & TxToConfirm {originalTx : txData , CurrentTx : tx }
291
285
292
286
if err = s .send (txToConfirm , true ); err != nil && ! strings .Contains (err .Error (), "replacement transaction" ) {
293
287
log .Error (
0 commit comments