1
1
import assert from "assert" ;
2
2
import { Job , Processor , Worker } from "bullmq" ;
3
- import { ethers } from "ethers" ;
4
3
import superjson from "superjson" ;
5
4
import { Hex , toSerializableTransaction } from "thirdweb" ;
6
5
import { stringify } from "thirdweb/utils" ;
@@ -14,8 +13,11 @@ import { getBlockNumberish } from "../../utils/block";
14
13
import { getChain } from "../../utils/chain" ;
15
14
import { msSince } from "../../utils/date" ;
16
15
import { env } from "../../utils/env" ;
17
- import { prettifyError } from "../../utils/error" ;
18
- import { isEthersErrorCode } from "../../utils/ethers" ;
16
+ import {
17
+ isNonceAlreadyUsedError ,
18
+ isReplacementGasFeeTooLow ,
19
+ prettifyError ,
20
+ } from "../../utils/error" ;
19
21
import { redis } from "../../utils/redis/redis" ;
20
22
import { thirdwebClient } from "../../utils/sdk" ;
21
23
import {
@@ -75,7 +77,11 @@ const handler: Processor<any, void, string> = async (job: Job<string>) => {
75
77
if ( resultTransaction . status === "sent" ) {
76
78
job . log ( `Transaction sent: ${ stringify ( resultTransaction ) } .` ) ;
77
79
await MineTransactionQueue . add ( { queueId : resultTransaction . queueId } ) ;
78
- await _reportUsageSuccess ( resultTransaction ) ;
80
+
81
+ // Report usage only on the first transaction send.
82
+ if ( transaction . status === "queued" ) {
83
+ await _reportUsageSuccess ( resultTransaction ) ;
84
+ }
79
85
} else if ( resultTransaction . status === "errored" ) {
80
86
_reportUsageError ( resultTransaction ) ;
81
87
}
@@ -161,8 +167,7 @@ const _sendTransaction = async (
161
167
transactionHash = sendTransactionResult . transactionHash ;
162
168
job . log ( `Sent transaction: ${ transactionHash } ` ) ;
163
169
} catch ( error : unknown ) {
164
- // NONCE_EXPIRED indicates the nonce was already used onchain. Do not recycle it.
165
- if ( ! isEthersErrorCode ( error , ethers . errors . NONCE_EXPIRED ) ) {
170
+ if ( ! isNonceAlreadyUsedError ( error ) ) {
166
171
job . log ( `Recycling nonce: ${ nonce } ` ) ;
167
172
await recycleNonce ( chainId , from , nonce ) ;
168
173
}
@@ -234,19 +239,14 @@ const _resendTransaction = async (
234
239
) ;
235
240
transactionHash = sendTransactionResult . transactionHash ;
236
241
job . log ( `Sent transaction: ${ transactionHash } ` ) ;
237
- } catch ( error : unknown ) {
238
- // NONCE_EXPIRED indicates that this transaction was already mined.
239
- // This is not an error.
240
- if ( ! isEthersErrorCode ( error , ethers . errors . NONCE_EXPIRED ) ) {
242
+ } catch ( error ) {
243
+ if ( isNonceAlreadyUsedError ( error ) ) {
241
244
job . log (
242
- ` Nonce used. This transaction was likely already mined. Do not resend.` ,
245
+ " Nonce used. This transaction was likely already mined. Do not resend." ,
243
246
) ;
244
247
return null ;
245
248
}
246
- // REPLACEMENT_UNDERPRICED indicates the mempool is already aware of this transaction
247
- // with >= gas fees. Wait for that one to be mined instead.
248
- // This is not an error.
249
- if ( ! isEthersErrorCode ( error , ethers . errors . REPLACEMENT_UNDERPRICED ) ) {
249
+ if ( isReplacementGasFeeTooLow ( error ) ) {
250
250
job . log ( "A pending transaction exists with >= gas fees. Do not resend." ) ;
251
251
return null ;
252
252
}
0 commit comments