1- import { Transport , Chain , Client , RpcSchema } from "viem" ;
1+ import { Transport , Chain , Client , RpcSchema , EstimateFeesPerGasReturnType } from "viem" ;
22import {
33 BundlerClient ,
44 BundlerClientConfig ,
@@ -7,31 +7,26 @@ import {
77} from "viem/account-abstraction" ;
88import { defaultClientConfig } from "./common" ;
99import { getPaymaster } from "./getPaymaster" ;
10-
11- const knownChainFees = new Set ( [
12- // anvil hardcodes fee returned by `eth_maxPriorityFeePerGas`
13- // so we have to override it here
14- // https://github.com/foundry-rs/foundry/pull/8081#issuecomment-2402002485
15- 31337 ,
16- // rhodolite
17- 17420 ,
18- // garnet
19- 17069 ,
20- // redstone
21- 690 ,
22- ] ) ;
10+ import { getAction } from "viem/utils" ;
11+ import { estimateFeesPerGas } from "viem/actions" ;
2312
2413export function createBundlerClient <
2514 transport extends Transport ,
26- chain extends Chain | undefined = undefined ,
27- account extends SmartAccount | undefined = undefined ,
28- client extends Client | undefined = undefined ,
15+ chain extends Chain = Chain ,
16+ account extends SmartAccount = SmartAccount ,
17+ client extends Client = Client ,
2918 rpcSchema extends RpcSchema | undefined = undefined ,
3019> (
3120 config : BundlerClientConfig < transport , chain , account , client , rpcSchema > ,
3221) : BundlerClient < transport , chain , account , client , rpcSchema > {
33- const chain = config . chain ?? config . client ?. chain ;
22+ // our generics above enforce this, but `BundlerClientConfig` makes it optional again
23+ const client = config . client ;
24+ if ( ! client ) throw new Error ( "No `client` provided to `createBundlerClient`." ) ;
25+
26+ const chain = config . chain ?? client . chain ;
3427 const paymaster = chain ? getPaymaster ( chain ) : undefined ;
28+
29+ // TODO: lift this out to make `createBundlerClient` configurable?
3530 return viem_createBundlerClient ( {
3631 ...defaultClientConfig ,
3732 paymaster : paymaster
@@ -42,17 +37,29 @@ export function createBundlerClient<
4237 } ) ,
4338 }
4439 : undefined ,
45- // TODO: figure out why viem isn't falling back to `chain.fees.estimateFeesPerGas` when this isn't set
4640 userOperation : {
47- estimateFeesPerGas :
48- // TODO: move this to gas estimator transport?
49- chain && knownChainFees . has ( chain . id )
50- ? async ( ) => ( {
51- maxFeePerGas : 100_000n ,
52- maxPriorityFeePerGas : 0n ,
53- } )
54- : undefined ,
41+ estimateFeesPerGas : createFeeEstimator ( client ) ,
5542 } ,
5643 ...config ,
5744 } ) ;
5845}
46+
47+ function createFeeEstimator ( client : Client ) : undefined | ( ( ) => Promise < EstimateFeesPerGasReturnType < "eip1559" > > ) {
48+ if ( ! client . chain ) return ;
49+
50+ // anvil hardcodes fee returned by `eth_maxPriorityFeePerGas`
51+ // so we override it here to mimick our chains
52+ // https://github.com/foundry-rs/foundry/pull/8081#issuecomment-2402002485
53+ // TODO: move this to user op executor transport?
54+ if ( client . chain . id === 31337 ) {
55+ return async ( ) => ( { maxFeePerGas : 100_000n , maxPriorityFeePerGas : 0n } ) ;
56+ }
57+
58+ // do our own fee calculation for redstone, garnet, rhodolite chains
59+ // because viem sets fees way too high by default
60+ // https://github.com/wevm/viem/blob/253b1072ad9fe36a0e0491e173c85a6d69209ada/src/account-abstraction/actions/bundler/prepareUserOperation.ts#L436-L457
61+ if ( [ 690 , 17069 , 17420 ] . includes ( client . chain . id ) ) {
62+ // TODO: move to fee ref or similar approach
63+ return ( ) => getAction ( client , estimateFeesPerGas , "estimateFeesPerGas" ) ( { chain : client . chain } ) ;
64+ }
65+ }
0 commit comments