@@ -63,6 +63,7 @@ export interface EstimateBatchGasOptions {
6363 publicClient : PublicClient ;
6464 account : Address ;
6565 executions : Execution [ ] ;
66+ authorizationList ?: SignAuthorizationReturnType [ ] ;
6667}
6768
6869/**
@@ -71,7 +72,7 @@ export interface EstimateBatchGasOptions {
7172 * Use this to get cost estimate before prompting user for confirmation.
7273 */
7374export async function estimateBatchGas ( options : EstimateBatchGasOptions ) : Promise < GasEstimate > {
74- const { publicClient, account, executions } = options ;
75+ const { publicClient, account, executions, authorizationList } = options ;
7576
7677 const executeBatchData = encodeExecuteBatchData ( executions ) ;
7778
@@ -83,6 +84,7 @@ export async function estimateBatchGas(options: EstimateBatchGasOptions): Promis
8384 account,
8485 to : account ,
8586 data : executeBatchData ,
87+ authorizationList,
8688 } ) ,
8789 ] ) ;
8890
@@ -113,6 +115,8 @@ export interface ExecuteBatchOptions {
113115 pendingMessage : string ;
114116 /** Optional gas params from estimation */
115117 gas ?: GasEstimate ;
118+ /** Optional pre-created authorization list (skips internal creation if provided) */
119+ authorizationList ?: SignAuthorizationReturnType [ ] ;
116120}
117121
118122/**
@@ -133,12 +137,74 @@ export async function checkERC7702Delegation(
133137 return code . toLowerCase ( ) === expectedCode . toLowerCase ( ) ;
134138}
135139
140+ /**
141+ * Options for creating an authorization list
142+ */
143+ export interface CreateAuthorizationListOptions {
144+ walletClient : WalletClient ;
145+ publicClient : PublicClient ;
146+ environmentConfig : EnvironmentConfig ;
147+ }
148+
149+ /**
150+ * Create an authorization list for EIP-7702 delegation if needed
151+ *
152+ * Returns undefined if the account is already delegated.
153+ * Use this to create the auth list before gas estimation to get accurate estimates.
154+ */
155+ export async function createAuthorizationList (
156+ options : CreateAuthorizationListOptions ,
157+ ) : Promise < SignAuthorizationReturnType [ ] | undefined > {
158+ const { walletClient, publicClient, environmentConfig } = options ;
159+
160+ const account = walletClient . account ;
161+ if ( ! account ) {
162+ throw new Error ( "Wallet client must have an account" ) ;
163+ }
164+
165+ // Check if already delegated
166+ const isDelegated = await checkERC7702Delegation (
167+ publicClient ,
168+ account . address ,
169+ environmentConfig . erc7702DelegatorAddress as Address ,
170+ ) ;
171+
172+ if ( isDelegated ) {
173+ return undefined ;
174+ }
175+
176+ // Create authorization
177+ const transactionNonce = await publicClient . getTransactionCount ( {
178+ address : account . address ,
179+ blockTag : "pending" ,
180+ } ) ;
181+
182+ const chainId = await publicClient . getChainId ( ) ;
183+ const authorizationNonce = transactionNonce + 1 ;
184+
185+ const signedAuthorization = await walletClient . signAuthorization ( {
186+ account,
187+ contractAddress : environmentConfig . erc7702DelegatorAddress as Address ,
188+ chainId : chainId ,
189+ nonce : Number ( authorizationNonce ) ,
190+ } ) ;
191+
192+ return [ signedAuthorization ] ;
193+ }
194+
136195/**
137196 * Execute batch of operations via EIP-7702 delegator
138197 */
139198export async function executeBatch ( options : ExecuteBatchOptions , logger : Logger = noopLogger ) : Promise < Hex > {
140- const { walletClient, publicClient, environmentConfig, executions, pendingMessage, gas } =
141- options ;
199+ const {
200+ walletClient,
201+ publicClient,
202+ environmentConfig,
203+ executions,
204+ pendingMessage,
205+ gas,
206+ authorizationList : providedAuthList ,
207+ } = options ;
142208
143209 const account = walletClient . account ;
144210 if ( ! account ) {
@@ -152,35 +218,37 @@ export async function executeBatch(options: ExecuteBatchOptions, logger: Logger
152218
153219 const executeBatchData = encodeExecuteBatchData ( executions ) ;
154220
155- // Check if account is delegated
156- const isDelegated = await checkERC7702Delegation (
157- publicClient ,
158- account . address ,
159- environmentConfig . erc7702DelegatorAddress as Address ,
160- ) ;
161-
162- // 4. Create authorization if needed
163- let authorizationList : Array < SignAuthorizationReturnType > = [ ] ;
164-
165- if ( ! isDelegated ) {
166- const transactionNonce = await publicClient . getTransactionCount ( {
167- address : account . address ,
168- blockTag : "pending" ,
169- } ) ;
221+ // Use provided authorization list or create one if needed
222+ let authorizationList : Array < SignAuthorizationReturnType > = providedAuthList || [ ] ;
223+ if ( authorizationList . length === 0 ) {
224+ // Check if account is delegated
225+ const isDelegated = await checkERC7702Delegation (
226+ publicClient ,
227+ account . address ,
228+ environmentConfig . erc7702DelegatorAddress as Address ,
229+ ) ;
230+
231+ // Create authorization if needed
232+ if ( ! isDelegated ) {
233+ const transactionNonce = await publicClient . getTransactionCount ( {
234+ address : account . address ,
235+ blockTag : "pending" ,
236+ } ) ;
170237
171- const chainId = await publicClient . getChainId ( ) ;
172- const authorizationNonce = transactionNonce + 1 ;
238+ const chainId = await publicClient . getChainId ( ) ;
239+ const authorizationNonce = transactionNonce + 1 ;
173240
174- logger . debug ( "Using wallet client signing for EIP-7702 authorization" ) ;
241+ logger . debug ( "Using wallet client signing for EIP-7702 authorization" ) ;
175242
176- const signedAuthorization = await walletClient . signAuthorization ( {
177- account : account . address ,
178- contractAddress : environmentConfig . erc7702DelegatorAddress as Address ,
179- chainId : chainId ,
180- nonce : Number ( authorizationNonce ) ,
181- } ) ;
243+ const signedAuthorization = await walletClient . signAuthorization ( {
244+ account,
245+ contractAddress : environmentConfig . erc7702DelegatorAddress as Address ,
246+ chainId : chainId ,
247+ nonce : Number ( authorizationNonce ) ,
248+ } ) ;
182249
183- authorizationList = [ signedAuthorization ] ;
250+ authorizationList = [ signedAuthorization ] ;
251+ }
184252 }
185253
186254 // 5. Show pending message
@@ -201,6 +269,9 @@ export async function executeBatch(options: ExecuteBatchOptions, logger: Logger
201269 }
202270
203271 // Add gas params if provided
272+ if ( gas ?. gasLimit ) {
273+ txRequest . gas = gas . gasLimit ;
274+ }
204275 if ( gas ?. maxFeePerGas ) {
205276 txRequest . maxFeePerGas = gas . maxFeePerGas ;
206277 }
0 commit comments