@@ -155,7 +155,14 @@ internal async Task<RpcResponseMessage> Request(RpcRequestMessage requestMessage
155155 {
156156 ThirdwebDebug . Log ( "Requesting: " + requestMessage . Method + "..." ) ;
157157
158- if ( requestMessage . Method == "eth_sendTransaction" )
158+ if ( requestMessage . Method == "eth_signTransaction" )
159+ {
160+ var parameters = JsonConvert . DeserializeObject < object [ ] > ( JsonConvert . SerializeObject ( requestMessage . RawParameters ) ) ;
161+ var txInput = JsonConvert . DeserializeObject < TransactionInput > ( JsonConvert . SerializeObject ( parameters [ 0 ] ) ) ;
162+ var partialUserOp = await SignTransactionAsUserOp ( txInput , requestMessage . Id ) ;
163+ return new RpcResponseMessage ( requestMessage . Id , JsonConvert . SerializeObject ( partialUserOp . EncodeUserOperation ( ) ) ) ;
164+ }
165+ else if ( requestMessage . Method == "eth_sendTransaction" )
159166 {
160167 return await CreateUserOpAndSend ( requestMessage ) ;
161168 }
@@ -185,23 +192,13 @@ internal async Task<RpcResponseMessage> Request(RpcRequestMessage requestMessage
185192 }
186193 }
187194
188- private async Task < RpcResponseMessage > CreateUserOpAndSend ( RpcRequestMessage requestMessage )
195+ private async Task < EntryPointContract . UserOperation > SignTransactionAsUserOp ( TransactionInput transactionInput , object requestId = null )
189196 {
190- await new WaitUntil ( ( ) => ! _deploying ) ;
191-
192- await UpdateDeploymentStatus ( ) ;
193- if ( ! _deployed )
194- {
195- _deploying = true ;
196- }
197+ requestId ??= SmartWalletClient . GenerateRpcId ( ) ;
197198
198199 string apiKey = ThirdwebManager . Instance . SDK . session . Options . clientId ;
199200
200- // Deserialize the transaction input from the request message
201-
202- var paramList = JsonConvert . DeserializeObject < List < object > > ( JsonConvert . SerializeObject ( requestMessage . RawParameters ) ) ;
203- var transactionInput = JsonConvert . DeserializeObject < TransactionInput > ( JsonConvert . SerializeObject ( paramList [ 0 ] ) ) ;
204- var dummySig = Constants . DUMMY_SIG ;
201+ // Create the user operation and its safe (hexified) version
205202
206203 var executeFn = new AccountContract . ExecuteFunction
207204 {
@@ -212,35 +209,6 @@ private async Task<RpcResponseMessage> CreateUserOpAndSend(RpcRequestMessage req
212209 } ;
213210 var executeInput = executeFn . CreateTransactionInput ( Accounts [ 0 ] ) ;
214211
215- // Approve ERC20 tokens if any
216-
217- if ( ! string . IsNullOrEmpty ( Config . erc20PaymasterAddress ) && ! _approved && ! _approving )
218- {
219- try
220- {
221- _approving = true ;
222- var tokenContract = ThirdwebManager . Instance . SDK . GetContract ( Config . erc20TokenAddress ) ;
223- var approvedAmount = await tokenContract . ERC20 . AllowanceOf ( Accounts [ 0 ] , Config . erc20PaymasterAddress ) ;
224- if ( BigInteger . Parse ( approvedAmount . value ) == 0 )
225- {
226- ThirdwebDebug . Log ( $ "Approving tokens for ERC20Paymaster spending") ;
227- _deploying = false ;
228- await tokenContract . ERC20 . SetAllowance ( Config . erc20PaymasterAddress , ( BigInteger . Pow ( 2 , 96 ) - 1 ) . ToString ( ) . ToEth ( ) ) ;
229- }
230- _approved = true ;
231- _approving = false ;
232- await UpdateDeploymentStatus ( ) ;
233- }
234- catch ( Exception e )
235- {
236- _approving = false ;
237- _approved = false ;
238- throw new Exception ( $ "Approving tokens for ERC20Paymaster spending failed: { e . Message } ") ;
239- }
240- }
241-
242- // Create the user operation and its safe (hexified) version
243-
244212 var ( initCode , gas ) = await GetInitCode ( ) ;
245213
246214 var gasPrices = await Utils . GetGasPriceAsync ( ThirdwebManager . Instance . SDK . session . ChainId ) ;
@@ -257,16 +225,16 @@ private async Task<RpcResponseMessage> CreateUserOpAndSend(RpcRequestMessage req
257225 MaxFeePerGas = gasPrices . MaxFeePerGas ,
258226 MaxPriorityFeePerGas = gasPrices . MaxPriorityFeePerGas ,
259227 PaymasterAndData = new byte [ ] { } ,
260- Signature = dummySig . HexStringToByteArray ( ) ,
228+ Signature = Constants . DUMMY_SIG . HexStringToByteArray ( ) ,
261229 } ;
262230
263231 // Update paymaster data if any
264232
265- partialUserOp . PaymasterAndData = await GetPaymasterAndData ( requestMessage . Id , partialUserOp . EncodeUserOperation ( ) , apiKey ) ;
233+ partialUserOp . PaymasterAndData = await GetPaymasterAndData ( requestId , partialUserOp . EncodeUserOperation ( ) , apiKey ) ;
266234
267235 // Estimate gas
268236
269- var gasEstimates = await BundlerClient . EthEstimateUserOperationGas ( Config . bundlerUrl , apiKey , requestMessage . Id , partialUserOp . EncodeUserOperation ( ) , Config . entryPointAddress ) ;
237+ var gasEstimates = await BundlerClient . EthEstimateUserOperationGas ( Config . bundlerUrl , apiKey , requestId , partialUserOp . EncodeUserOperation ( ) , Config . entryPointAddress ) ;
270238 partialUserOp . CallGasLimit = 50000 + new HexBigInteger ( gasEstimates . CallGasLimit ) . Value ;
271239 partialUserOp . VerificationGasLimit = string . IsNullOrEmpty ( Config . erc20PaymasterAddress )
272240 ? new HexBigInteger ( gasEstimates . VerificationGas ) . Value
@@ -275,12 +243,63 @@ private async Task<RpcResponseMessage> CreateUserOpAndSend(RpcRequestMessage req
275243
276244 // Update paymaster data if any
277245
278- partialUserOp . PaymasterAndData = await GetPaymasterAndData ( requestMessage . Id , partialUserOp . EncodeUserOperation ( ) , apiKey ) ;
246+ partialUserOp . PaymasterAndData = await GetPaymasterAndData ( requestId , partialUserOp . EncodeUserOperation ( ) , apiKey ) ;
279247
280248 // Hash, sign and encode the user operation
281249
282250 partialUserOp . Signature = await partialUserOp . HashAndSignUserOp ( Config . entryPointAddress ) ;
283251
252+ return partialUserOp ;
253+ }
254+
255+ private async Task < RpcResponseMessage > CreateUserOpAndSend ( RpcRequestMessage requestMessage )
256+ {
257+ await new WaitUntil ( ( ) => ! _deploying ) ;
258+
259+ await UpdateDeploymentStatus ( ) ;
260+ if ( ! _deployed )
261+ {
262+ _deploying = true ;
263+ }
264+
265+ string apiKey = ThirdwebManager . Instance . SDK . session . Options . clientId ;
266+
267+ // Deserialize the transaction input from the request message
268+
269+ var paramList = JsonConvert . DeserializeObject < List < object > > ( JsonConvert . SerializeObject ( requestMessage . RawParameters ) ) ;
270+ var transactionInput = JsonConvert . DeserializeObject < TransactionInput > ( JsonConvert . SerializeObject ( paramList [ 0 ] ) ) ;
271+
272+ // Approve ERC20 tokens if any
273+
274+ if ( ! string . IsNullOrEmpty ( Config . erc20PaymasterAddress ) && ! _approved && ! _approving )
275+ {
276+ try
277+ {
278+ _approving = true ;
279+ var tokenContract = ThirdwebManager . Instance . SDK . GetContract ( Config . erc20TokenAddress ) ;
280+ var approvedAmount = await tokenContract . ERC20 . AllowanceOf ( Accounts [ 0 ] , Config . erc20PaymasterAddress ) ;
281+ if ( BigInteger . Parse ( approvedAmount . value ) == 0 )
282+ {
283+ ThirdwebDebug . Log ( $ "Approving tokens for ERC20Paymaster spending") ;
284+ _deploying = false ;
285+ await tokenContract . ERC20 . SetAllowance ( Config . erc20PaymasterAddress , ( BigInteger . Pow ( 2 , 96 ) - 1 ) . ToString ( ) . ToEth ( ) ) ;
286+ }
287+ _approved = true ;
288+ _approving = false ;
289+ await UpdateDeploymentStatus ( ) ;
290+ }
291+ catch ( Exception e )
292+ {
293+ _approving = false ;
294+ _approved = false ;
295+ throw new Exception ( $ "Approving tokens for ERC20Paymaster spending failed: { e . Message } ") ;
296+ }
297+ }
298+
299+ // Create and sign the user operation
300+
301+ var partialUserOp = await SignTransactionAsUserOp ( transactionInput , requestMessage . Id ) ;
302+
284303 // Send the user operation
285304
286305 ThirdwebDebug . Log ( "Valid UserOp: " + JsonConvert . SerializeObject ( partialUserOp ) ) ;
0 commit comments