@@ -20,7 +20,7 @@ import {
2020 noopMiddleware ,
2121 resolveProperties ,
2222} from "@aa-sdk/core" ;
23- import { fromHex , isHex , type Hex } from "viem" ;
23+ import { fromHex , isHex , toHex , type Hex } from "viem" ;
2424import type { AlchemySmartAccountClient } from "../client/smartAccountClient.js" ;
2525import type { AlchemyTransport } from "../alchemyTransport.js" ;
2626import { alchemyFeeEstimator } from "./feeEstimator.js" ;
@@ -62,7 +62,10 @@ interface AlchemyGasAndPaymasterAndDataMiddlewareParams {
6262
6363export type PolicyToken = {
6464 address : string ;
65+ maxTokenAmount : bigint ;
6566 approvalMode : ApprovalMode ;
67+ erc20Name : string ;
68+ version : string ;
6669} ;
6770
6871export enum ApprovalMode {
@@ -205,6 +208,81 @@ export function alchemyGasAndPaymasterAndDataMiddleware(
205208 : { } ) ,
206209 } ) ;
207210
211+ let erc20Context = undefined ;
212+ if (
213+ policyToken !== undefined &&
214+ policyToken . approvalMode === ApprovalMode . PERMIT
215+ ) {
216+ // get a paymaster address
217+ let paymasterAddress = "0x" ;
218+ const paymasterData = await (
219+ client as AlchemySmartAccountClient
220+ ) . request ( {
221+ method : "pm_getPaymasterStubData" ,
222+ params : [
223+ userOp ,
224+ account . getEntryPoint ( ) . address ,
225+ toHex ( client . chain . id ) ,
226+ {
227+ policyId : Array . isArray ( policyId ) ? policyId [ 0 ] : policyId ,
228+ } ,
229+ ] ,
230+ } ) ;
231+ // todo: make a eth_estimateUserOperationGas to avoid client pass
232+ // maxAmountToken
233+ paymasterAddress = paymasterData . paymaster
234+ ? paymasterData . paymaster
235+ : paymasterData . paymasterAndData
236+ ? paymasterData . paymasterAndData . slice ( 0 , 42 )
237+ : "0x" ;
238+ const typed_permit_data = {
239+ types : {
240+ Permit : [
241+ {
242+ name : "owner" ,
243+ type : "address" ,
244+ } ,
245+ {
246+ name : "spender" ,
247+ type : "address" ,
248+ } ,
249+ {
250+ name : "value" ,
251+ type : "uint256" ,
252+ } ,
253+ {
254+ name : "nonce" ,
255+ type : "uint256" ,
256+ } ,
257+ {
258+ name : "deadline" ,
259+ type : "uint256" ,
260+ } ,
261+ ] ,
262+ } ,
263+ primaryType : "Permit" ,
264+ domain : {
265+ name : policyToken . erc20Name ,
266+ version : policyToken . version ,
267+ chainId : client . chain . id ,
268+ verifyingContract : policyToken . address as Hex ,
269+ } ,
270+ message : {
271+ owner : account . address as Hex ,
272+ spender : paymasterAddress as Hex ,
273+ value : policyToken . maxTokenAmount ,
274+ nonce : ( await account . getAccountNonce ( ) ) + BigInt ( 1 ) ,
275+ deadline : BigInt ( 0xffffffffffffffffffffffffffffffff ) ,
276+ } ,
277+ } as const ;
278+
279+ erc20Context = {
280+ tokenAddress : policyToken . address ,
281+ permit : account . signTypedData ( typed_permit_data ) ,
282+ maxTokenAmount : policyToken . maxTokenAmount ,
283+ } ;
284+ }
285+
208286 const result = await ( client as AlchemySmartAccountClient ) . request ( {
209287 method : "alchemy_requestGasAndPaymasterAndData" ,
210288 params : [
@@ -214,11 +292,9 @@ export function alchemyGasAndPaymasterAndDataMiddleware(
214292 userOperation : userOp ,
215293 dummySignature : await account . getDummySignature ( ) ,
216294 overrides,
217- ...( policyToken
295+ ...( erc20Context
218296 ? {
219- erc20Context : {
220- tokenAddress : policyToken . address ,
221- } ,
297+ erc20Context : erc20Context ,
222298 }
223299 : { } ) ,
224300 } ,
0 commit comments