@@ -8,7 +8,7 @@ import { thirdwebClient } from "../../utils/sdk";
8
8
* The "last used nonce" stores the last nonce submitted onchain.
9
9
* Example: "25"
10
10
*/
11
- const lastUsedNonceKey = ( chainId : number , walletAddress : Address ) =>
11
+ export const lastUsedNonceKey = ( chainId : number , walletAddress : Address ) =>
12
12
`nonce:${ chainId } :${ normalizeAddress ( walletAddress ) } ` ;
13
13
14
14
/**
@@ -122,3 +122,36 @@ export const deleteAllNonces = async () => {
122
122
await redis . del ( keys ) ;
123
123
}
124
124
} ;
125
+
126
+ /**
127
+ * Resync the nonce i.e., max of transactionCount +1 and lastUsedNonce.
128
+ * @param chainId
129
+ * @param walletAddress
130
+ */
131
+ export const rebaseNonce = async ( chainId : number , walletAddress : Address ) => {
132
+ const rpcRequest = getRpcClient ( {
133
+ client : thirdwebClient ,
134
+ chain : await getChain ( chainId ) ,
135
+ } ) ;
136
+
137
+ // The next unused nonce = transactionCount.
138
+ const transactionCount = await eth_getTransactionCount ( rpcRequest , {
139
+ address : walletAddress ,
140
+ } ) ;
141
+
142
+ // Lua script to set nonce as max(transactionCount, redis.get(lastUsedNonceKey))
143
+ const script = `
144
+ local transactionCount = tonumber(ARGV[1])
145
+ local lastUsedNonce = tonumber(redis.call('get', KEYS[1]))
146
+ local nextNonce = math.max(transactionCount, lastUsedNonce)
147
+ redis.call('set', KEYS[1], nextNonce)
148
+ return nextNonce
149
+ ` ;
150
+ const nextNonce = await redis . eval (
151
+ script ,
152
+ 1 ,
153
+ lastUsedNonceKey ( chainId , normalizeAddress ( walletAddress ) ) ,
154
+ transactionCount . toString ( ) ,
155
+ ) ;
156
+ return nextNonce ;
157
+ } ;
0 commit comments