diff --git a/.changeset/brave-cooks-carry.md b/.changeset/brave-cooks-carry.md new file mode 100644 index 0000000000..8487d6be84 --- /dev/null +++ b/.changeset/brave-cooks-carry.md @@ -0,0 +1,5 @@ +--- +"viem": patch +--- + +Fixed an issue that caused the nonce to increment prematurely in prepareTransactionRequest, resulting in possible nonce gaps. Now the nonce manager logic is arranged so that gas estimation is performed first, ensuring no wasted nonce if gas estimation fails diff --git a/src/actions/wallet/prepareTransactionRequest.ts b/src/actions/wallet/prepareTransactionRequest.ts index fc12d2fee4..9b67cc9e6a 100644 --- a/src/actions/wallet/prepareTransactionRequest.ts +++ b/src/actions/wallet/prepareTransactionRequest.ts @@ -316,26 +316,6 @@ export async function prepareTransactionRequest< if (parameters.includes('chainId')) request.chainId = await getChainId() - if (parameters.includes('nonce') && typeof nonce === 'undefined' && account) { - if (nonceManager) { - const chainId = await getChainId() - request.nonce = await nonceManager.consume({ - address: account.address, - chainId, - client, - }) - } else { - request.nonce = await getAction( - client, - getTransactionCount, - 'getTransactionCount', - )({ - address: account.address, - blockTag: 'pending', - }) - } - } - if ( (parameters.includes('fees') || parameters.includes('type')) && typeof type === 'undefined' @@ -403,7 +383,7 @@ export async function prepareTransactionRequest< } } - if (parameters.includes('gas') && typeof gas === 'undefined') + if (parameters.includes('gas') && typeof gas === 'undefined') { request.gas = await getAction( client, estimateGas, @@ -414,6 +394,27 @@ export async function prepareTransactionRequest< ? { address: account.address, type: 'json-rpc' } : account, } as EstimateGasParameters) + } + + if (parameters.includes('nonce') && typeof nonce === 'undefined' && account) { + if (nonceManager) { + const chainId = await getChainId() + request.nonce = await nonceManager.consume({ + address: account.address, + chainId, + client, + }) + } else { + request.nonce = await getAction( + client, + getTransactionCount, + 'getTransactionCount', + )({ + address: account.address, + blockTag: 'pending', + }) + } + } assertRequest(request as AssertRequestParameters)