Skip to content

Commit

Permalink
fix(entrykit): improve fee handling (#3577)
Browse files Browse the repository at this point in the history
  • Loading branch information
holic authored Feb 6, 2025
1 parent 3d58450 commit 900ac35
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 30 deletions.
5 changes: 5 additions & 0 deletions .changeset/clean-mugs-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@latticexyz/entrykit": patch
---

Improved fee handling for known chains.
61 changes: 34 additions & 27 deletions packages/entrykit/src/createBundlerClient.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Transport, Chain, Client, RpcSchema } from "viem";
import { Transport, Chain, Client, RpcSchema, EstimateFeesPerGasReturnType } from "viem";
import {
BundlerClient,
BundlerClientConfig,
Expand All @@ -7,31 +7,26 @@ import {
} from "viem/account-abstraction";
import { defaultClientConfig } from "./common";
import { getPaymaster } from "./getPaymaster";

const knownChainFees = new Set([
// anvil hardcodes fee returned by `eth_maxPriorityFeePerGas`
// so we have to override it here
// https://github.com/foundry-rs/foundry/pull/8081#issuecomment-2402002485
31337,
// rhodolite
17420,
// garnet
17069,
// redstone
690,
]);
import { getAction } from "viem/utils";
import { estimateFeesPerGas } from "viem/actions";

export function createBundlerClient<
transport extends Transport,
chain extends Chain | undefined = undefined,
account extends SmartAccount | undefined = undefined,
client extends Client | undefined = undefined,
chain extends Chain = Chain,
account extends SmartAccount = SmartAccount,
client extends Client = Client,
rpcSchema extends RpcSchema | undefined = undefined,
>(
config: BundlerClientConfig<transport, chain, account, client, rpcSchema>,
): BundlerClient<transport, chain, account, client, rpcSchema> {
const chain = config.chain ?? config.client?.chain;
// our generics above enforce this, but `BundlerClientConfig` makes it optional again
const client = config.client;
if (!client) throw new Error("No `client` provided to `createBundlerClient`.");

const chain = config.chain ?? client.chain;
const paymaster = chain ? getPaymaster(chain) : undefined;

// TODO: lift this out to make `createBundlerClient` configurable?
return viem_createBundlerClient({
...defaultClientConfig,
paymaster: paymaster
Expand All @@ -42,17 +37,29 @@ export function createBundlerClient<
}),
}
: undefined,
// TODO: figure out why viem isn't falling back to `chain.fees.estimateFeesPerGas` when this isn't set
userOperation: {
estimateFeesPerGas:
// TODO: move this to gas estimator transport?
chain && knownChainFees.has(chain.id)
? async () => ({
maxFeePerGas: 100_000n,
maxPriorityFeePerGas: 0n,
})
: undefined,
estimateFeesPerGas: createFeeEstimator(client),
},
...config,
});
}

function createFeeEstimator(client: Client): undefined | (() => Promise<EstimateFeesPerGasReturnType<"eip1559">>) {
if (!client.chain) return;

// anvil hardcodes fee returned by `eth_maxPriorityFeePerGas`
// so we override it here to mimick our chains
// https://github.com/foundry-rs/foundry/pull/8081#issuecomment-2402002485
// TODO: move this to user op executor transport?
if (client.chain.id === 31337) {
return async () => ({ maxFeePerGas: 100_000n, maxPriorityFeePerGas: 0n });
}

// do our own fee calculation for redstone, garnet, rhodolite chains
// because viem sets fees way too high by default
// https://github.com/wevm/viem/blob/253b1072ad9fe36a0e0491e173c85a6d69209ada/src/account-abstraction/actions/bundler/prepareUserOperation.ts#L436-L457
if ([690, 17069, 17420].includes(client.chain.id)) {
// TODO: move to fee ref or similar approach
return () => getAction(client, estimateFeesPerGas, "estimateFeesPerGas")({ chain: client.chain });
}
}
3 changes: 1 addition & 2 deletions packages/entrykit/src/getSessionClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ export async function getSessionClient({
throw new Error("Session account client had no associated chain.");
}

const bundlerTransport = getBundlerTransport(client.chain);
const bundlerClient = createBundlerClient({
transport: bundlerTransport,
transport: getBundlerTransport(client.chain),
client,
account: sessionAccount,
});
Expand Down
1 change: 1 addition & 0 deletions packages/entrykit/src/onboarding/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export type Step = {
content: (props: { isActive: boolean; isExpanded: boolean }) => ReactNode;
};

// TODO: move to chain config?
export const minGasBalance = parseEther("0.01");

export type RelayChain = {
Expand Down
3 changes: 2 additions & 1 deletion packages/entrykit/src/onboarding/usePrerequisites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ export function getPrequisitesQueryOptions({
isSpender,
hasGasBalance,
hasDelegation,
complete: hasAllowance && isSpender && hasDelegation,
// we intentionally don't enforce an allowance/gas balance here
complete: isSpender && hasDelegation,
};
},
retry: false,
Expand Down

0 comments on commit 900ac35

Please sign in to comment.