diff --git a/.changeset/fluffy-moles-march.md b/.changeset/fluffy-moles-march.md new file mode 100644 index 0000000000..1e7bb14fa0 --- /dev/null +++ b/.changeset/fluffy-moles-march.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/common": patch +--- + +- Remove need for tx queue in `createContract` diff --git a/packages/common/package.json b/packages/common/package.json index c867c87c2a..37b1d7404b 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -62,7 +62,6 @@ "chalk": "^5.2.0", "debug": "^4.3.4", "execa": "^7.0.0", - "p-queue": "^7.3.4", "p-retry": "^5.1.2", "prettier": "^2.8.4", "prettier-plugin-solidity": "^1.1.2", diff --git a/packages/common/src/createContract.ts b/packages/common/src/createContract.ts index b22483f0f0..55be0305be 100644 --- a/packages/common/src/createContract.ts +++ b/packages/common/src/createContract.ts @@ -5,7 +5,6 @@ import { Chain, GetContractParameters, GetContractReturnType, - Hex, PublicClient, SimulateContractParameters, Transport, @@ -13,7 +12,6 @@ import { WriteContractParameters, getContract, } from "viem"; -import pQueue from "p-queue"; import pRetry from "p-retry"; import { createNonceManager } from "./createNonceManager"; import { debug as parentDebug } from "./debug"; @@ -62,11 +60,6 @@ export function createContract< address: walletClient.account.address, }); - // Concurrency of one means transactions will be queued and inserted into the mem pool synchronously and in order. - // Although increasing this will allow for more parallel requests/transactions and nonce errors will get automatically retried, - // we can't guarantee local nonce accurancy due to needing async operations (simulate) before incrementing the nonce. - const queue = new pQueue({ concurrency: 1 }); - // Replace write calls with our own proxy. Implemented ~the same as viem, but adds better handling of nonces (via queue + retries). contract.write = new Proxy( {}, @@ -80,34 +73,31 @@ export function createContract< } >getFunctionParameters(parameters as any); - async function write(): Promise { - if (!nonceManager.hasNonce()) { - await nonceManager.resetNonce(); - } - - // Temporarily override base fee for our default anvil config - // TODO: remove once https://github.com/wagmi-dev/viem/pull/963 is fixed - // TODO: more specific mud foundry check? or can we safely assume anvil+mud will be block fee zero for now? - if ( - walletClient.chain.id === 31337 && - options.maxFeePerGas == null && - options.maxPriorityFeePerGas == null - ) { - options.maxFeePerGas = 0n; - options.maxPriorityFeePerGas = 0n; - } + // Temporarily override base fee for our default anvil config + // TODO: replace with https://github.com/wagmi-dev/viem/pull/1006 once merged + // TODO: more specific mud foundry check? or can we safely assume anvil+mud will be block fee zero for now? + if ( + walletClient.chain.id === 31337 && + options.maxFeePerGas == null && + options.maxPriorityFeePerGas == null + ) { + debug("assuming zero base fee for anvil chain"); + options.maxFeePerGas = 0n; + options.maxPriorityFeePerGas = 0n; + } + async function prepareWrite(): Promise< + WriteContractParameters + > { if (options.gas) { - const nonce = nonceManager.nextNonce(); - debug("gas provided, skipping simulate and calling write function with nonce", nonce, options); - return await walletClient.writeContract({ + debug("gas provided, skipping simulate", functionName, args, options); + return { address, abi, functionName, args, - nonce, ...options, - } as unknown as WriteContractParameters); + } as unknown as WriteContractParameters; } debug("simulating write", functionName, args, options); @@ -120,29 +110,37 @@ export function createContract< account: options.account ?? walletClient.account, } as unknown as SimulateContractParameters); - const nonce = nonceManager.nextNonce(); - debug("calling write function with nonce", nonce, request); - return await walletClient.writeContract({ - nonce, - ...request, - } as unknown as WriteContractParameters); + return request as unknown as WriteContractParameters; } - return await queue.add( - () => - pRetry(write, { - retries: 3, - onFailedAttempt: async (error) => { - // On nonce errors, reset the nonce and retry - if (nonceManager.shouldResetNonce(error)) { - debug("got nonce error, retrying", error); - await nonceManager.resetNonce(); - return; - } - throw error; - }, - }), - { throwOnTimeout: true } + const preparedWrite = await prepareWrite(); + + return await pRetry( + async () => { + if (!nonceManager.hasNonce()) { + await nonceManager.resetNonce(); + } + + const nonce = nonceManager.nextNonce(); + debug("calling write function with nonce", nonce, preparedWrite); + return await walletClient.writeContract({ + nonce, + ...preparedWrite, + }); + }, + { + retries: 3, + onFailedAttempt: async (error) => { + // On nonce errors, reset the nonce and retry + if (nonceManager.shouldResetNonce(error)) { + debug("got nonce error, retrying", error); + await nonceManager.resetNonce(); + return; + } + // TODO: prepareWrite again if there are gas errors? + throw error; + }, + } ); }; }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f2810cf1b..c7c8b5e85e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -238,9 +238,6 @@ importers: execa: specifier: ^7.0.0 version: 7.0.0 - p-queue: - specifier: ^7.3.4 - version: 7.3.4 p-retry: specifier: ^5.1.2 version: 5.1.2 @@ -8976,14 +8973,6 @@ packages: aggregate-error: 3.1.0 dev: true - /p-queue@7.3.4: - resolution: {integrity: sha512-esox8CWt0j9EZECFvkFl2WNPat8LN4t7WWeXq73D9ha0V96qPRufApZi4ZhPwXAln1uVVal429HVVKPa2X0yQg==} - engines: {node: '>=12'} - dependencies: - eventemitter3: 4.0.7 - p-timeout: 5.1.0 - dev: false - /p-retry@5.1.2: resolution: {integrity: sha512-couX95waDu98NfNZV+i/iLt+fdVxmI7CbrrdC2uDWfPdUAApyxT4wmDlyOtR5KtTDmkDO0zDScDjDou9YHhd9g==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -8992,11 +8981,6 @@ packages: retry: 0.13.1 dev: false - /p-timeout@5.1.0: - resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==} - engines: {node: '>=12'} - dev: false - /p-try@1.0.0: resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} engines: {node: '>=4'}