diff --git a/.changeset/four-zoos-smile.md b/.changeset/four-zoos-smile.md new file mode 100644 index 0000000000..149a454c77 --- /dev/null +++ b/.changeset/four-zoos-smile.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/entrykit": patch +--- + +Fees for Redstone, Pyrope and Garnet are now cached for 10 seconds instead of fetched before every user operation. diff --git a/packages/entrykit/src/actions/cachedFeesPerGas.ts b/packages/entrykit/src/actions/cachedFeesPerGas.ts new file mode 100644 index 0000000000..cfa059582d --- /dev/null +++ b/packages/entrykit/src/actions/cachedFeesPerGas.ts @@ -0,0 +1,26 @@ +import { Client, EstimateFeesPerGasReturnType } from "viem"; +import { estimateFeesPerGas } from "viem/actions"; + +type CachedFeesPerGasOptions = { + refreshInterval?: number; +}; + +export function cachedFeesPerGas( + client: Client, + options: CachedFeesPerGasOptions = { refreshInterval: 10_000 }, +): () => Promise> { + let fees: EstimateFeesPerGasReturnType<"eip1559"> | null = null; + + async function refreshFees() { + fees = await estimateFeesPerGas(client); + } + + refreshFees(); + setInterval(refreshFees, options.refreshInterval); + + return async () => { + if (fees) return fees; + fees = await estimateFeesPerGas(client); + return fees; + }; +} diff --git a/packages/entrykit/src/createBundlerClient.ts b/packages/entrykit/src/createBundlerClient.ts index f923246762..494b4ba2ee 100644 --- a/packages/entrykit/src/createBundlerClient.ts +++ b/packages/entrykit/src/createBundlerClient.ts @@ -7,8 +7,7 @@ import { } from "viem/account-abstraction"; import { defaultClientConfig } from "./common"; import { getPaymaster } from "./getPaymaster"; -import { getAction } from "viem/utils"; -import { estimateFeesPerGas } from "viem/actions"; +import { cachedFeesPerGas } from "./actions/cachedFeesPerGas"; export function createBundlerClient< transport extends Transport, @@ -56,10 +55,9 @@ function createFeeEstimator(client: Client): undefined | (() => Promise getAction(client, estimateFeesPerGas, "estimateFeesPerGas")({ chain: client.chain }); + return cachedFeesPerGas(client); } } diff --git a/packages/entrykit/src/exports/internal.ts b/packages/entrykit/src/exports/internal.ts index 68451d6b0d..a3b0b6c2db 100644 --- a/packages/entrykit/src/exports/internal.ts +++ b/packages/entrykit/src/exports/internal.ts @@ -11,6 +11,7 @@ export { AccountButton } from "../AccountButton"; export { useAccountModal } from "../useAccountModal"; export { useSessionClientReady as useSessionClient } from "../useSessionClientReady"; export { createWagmiConfig, type CreateWagmiConfigOptions } from "../createWagmiConfig"; +export { withFeeCache } from "../utils/withFeeCache"; // And some additional internal things export * from "../validateSigner"; diff --git a/packages/entrykit/src/getSessionClient.ts b/packages/entrykit/src/getSessionClient.ts index 0776b101c9..bb5cccf346 100644 --- a/packages/entrykit/src/getSessionClient.ts +++ b/packages/entrykit/src/getSessionClient.ts @@ -44,7 +44,6 @@ export async function getSessionClient({ publicClient: client, }), ) - // TODO: add observer once we conditionally fetch receipts while bridge is open .extend(() => ({ userAddress, worldAddress, internal_signer: sessionSigner })); diff --git a/packages/entrykit/src/utils/withFeeCache.ts b/packages/entrykit/src/utils/withFeeCache.ts new file mode 100644 index 0000000000..b5788f0d2d --- /dev/null +++ b/packages/entrykit/src/utils/withFeeCache.ts @@ -0,0 +1,28 @@ +import { Chain, createClient, http } from "viem"; +import { cachedFeesPerGas } from "../actions/cachedFeesPerGas"; + +type WithFeeCacheOptions = { + refreshInterval?: number; +}; + +export function withFeeCache( + chain: chain, + options: WithFeeCacheOptions = { refreshInterval: 10_000 }, +): chain { + if (chain.fees?.estimateFeesPerGas) { + throw new Error("withFeeCache: estimateFeesPerGas already defined in chain config"); + } + + const client = createClient({ + chain, + transport: http(), + }); + + return { + ...chain, + fees: { + ...chain.fees, + estimateFeesPerGas: cachedFeesPerGas(client, options), + }, + }; +}