@@ -2,25 +2,28 @@ import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
2
2
import {
3
3
FillUserOpParams ,
4
4
FillUserOpResponse ,
5
- SendUserOpWithSigantureParams ,
6
- SendUserOpWithSigantureResponse ,
5
+ SendUserOpWithSignatureParams ,
6
+ SendUserOpWithSignatureResponse ,
7
7
UserOpBuilder
8
8
} from './UserOpBuilder'
9
9
import {
10
10
Address ,
11
11
Chain ,
12
12
createPublicClient ,
13
- GetStorageAtReturnType ,
14
13
Hex ,
15
14
http ,
15
+ pad ,
16
16
parseAbi ,
17
17
PublicClient ,
18
- trim
18
+ trim ,
19
+ zeroAddress
19
20
} from 'viem'
20
21
import { signerToSafeSmartAccount } from 'permissionless/accounts'
21
22
import {
22
23
createSmartAccountClient ,
23
24
ENTRYPOINT_ADDRESS_V07 ,
25
+ getAccountNonce ,
26
+ getPackedUserOperation ,
24
27
getUserOperationHash
25
28
} from 'permissionless'
26
29
import {
@@ -31,6 +34,7 @@ import { bundlerUrl, paymasterUrl, publicClientUrl } from '@/utils/SmartAccountU
31
34
32
35
import { getChainById } from '@/utils/ChainUtil'
33
36
import { SAFE_FALLBACK_HANDLER_STORAGE_SLOT } from '@/consts/smartAccounts'
37
+ import { formatSignature } from './SmartSessionUserOpBuilder'
34
38
35
39
const ERC_7579_LAUNCHPAD_ADDRESS : Address = '0xEBe001b3D534B9B6E2500FB78E67a1A137f561CE'
36
40
@@ -93,15 +97,33 @@ export class SafeUserOpBuilder implements UserOpBuilder {
93
97
chain : this . chain ,
94
98
bundlerTransport,
95
99
middleware : {
96
- sponsorUserOperation : paymasterClient . sponsorUserOperation , // optional
100
+ sponsorUserOperation :
101
+ params . capabilities . paymasterService && paymasterClient . sponsorUserOperation , // optional
97
102
gasPrice : async ( ) => ( await pimlicoBundlerClient . getUserOperationGasPrice ( ) ) . fast // if using pimlico bundler
98
103
}
99
104
} )
100
105
const account = smartAccountClient . account
101
106
107
+ const validatorAddress = ( params . capabilities . permissions ?. context . slice ( 0 , 42 ) ||
108
+ zeroAddress ) as Address
109
+ let nonce : bigint = await getAccountNonce ( this . publicClient , {
110
+ sender : this . accountAddress ,
111
+ entryPoint : ENTRYPOINT_ADDRESS_V07 ,
112
+ key : BigInt (
113
+ pad ( validatorAddress , {
114
+ dir : 'right' ,
115
+ size : 24
116
+ } ) || 0
117
+ )
118
+ } )
119
+
102
120
const userOp = await smartAccountClient . prepareUserOperationRequest ( {
103
121
userOperation : {
104
- callData : await account . encodeCallData ( params . calls )
122
+ nonce : nonce ,
123
+ callData : await account . encodeCallData ( params . calls ) ,
124
+ callGasLimit : BigInt ( '0x1E8480' ) ,
125
+ verificationGasLimit : BigInt ( '0x1E8480' ) ,
126
+ preVerificationGas : BigInt ( '0x1E8480' )
105
127
} ,
106
128
account : account
107
129
} )
@@ -115,10 +137,48 @@ export class SafeUserOpBuilder implements UserOpBuilder {
115
137
hash
116
138
}
117
139
}
118
- sendUserOpWithSignature (
119
- params : SendUserOpWithSigantureParams
120
- ) : Promise < SendUserOpWithSigantureResponse > {
121
- throw new Error ( 'Method not implemented.' )
140
+ async sendUserOpWithSignature (
141
+ params : SendUserOpWithSignatureParams
142
+ ) : Promise < SendUserOpWithSignatureResponse > {
143
+ const { userOp, permissionsContext } = params
144
+ if ( permissionsContext ) {
145
+ const formattedSignature = await formatSignature ( this . publicClient , {
146
+ signature : userOp . signature ,
147
+ permissionsContext,
148
+ accountAddress : userOp . sender
149
+ } )
150
+ userOp . signature = formattedSignature
151
+ }
152
+ const bundlerTransport = http ( bundlerUrl ( { chain : this . chain } ) , {
153
+ timeout : 30000
154
+ } )
155
+ const pimlicoBundlerClient = createPimlicoBundlerClient ( {
156
+ chain : this . chain ,
157
+ transport : bundlerTransport ,
158
+ entryPoint : ENTRYPOINT_ADDRESS_V07
159
+ } )
160
+
161
+ const userOpHash = await pimlicoBundlerClient . sendUserOperation ( {
162
+ userOperation : {
163
+ ...userOp ,
164
+ callData : userOp . callData ,
165
+ callGasLimit : BigInt ( userOp . callGasLimit ) ,
166
+ nonce : BigInt ( userOp . nonce ) ,
167
+ preVerificationGas : BigInt ( userOp . preVerificationGas ) ,
168
+ verificationGasLimit : BigInt ( userOp . verificationGasLimit ) ,
169
+ sender : userOp . sender ,
170
+ signature : userOp . signature ,
171
+ maxFeePerGas : BigInt ( userOp . maxFeePerGas ) ,
172
+ maxPriorityFeePerGas : BigInt ( userOp . maxPriorityFeePerGas )
173
+ }
174
+ } )
175
+ const receipt = await pimlicoBundlerClient . waitForUserOperationReceipt ( {
176
+ hash : userOpHash
177
+ } )
178
+
179
+ return {
180
+ receipt : receipt . receipt . transactionHash
181
+ }
122
182
}
123
183
124
184
private async getVersion ( ) : Promise < string > {
0 commit comments