@@ -40,7 +40,7 @@ type Client interface {
40
40
// - error - if failed to calculate it.
41
41
GetAccountAddress (ctx context.Context , owner common.Address , index decimal.Decimal ) (common.Address , error )
42
42
43
- // NewUserOp builds a new UserOperation and fills all the fields.
43
+ // NewUserOp builds and signs a new UserOperation and fills all the fields.
44
44
//
45
45
// NOTE: only `executeBatch` is supported for now.
46
46
//
@@ -53,8 +53,9 @@ type Client interface {
53
53
// - overrides - are the overrides for the middleware during the user operation creation. Can be nil.
54
54
//
55
55
// Returns:
56
- // - UserOperation - user operation with all fields filled in.
56
+ // - UserOperation - signed user operation with all fields filled in.
57
57
// - error - if failed to build the user operation.
58
+ // TODO: rename to NewSignedUserOp when this pkg is extracted.
58
59
NewUserOp (
59
60
ctx context.Context ,
60
61
sender common.Address ,
@@ -64,6 +65,29 @@ type Client interface {
64
65
overrides * Overrides ,
65
66
) (UserOperation , error )
66
67
68
+ // NewUserOp builds a new UserOperation and fills all the fields.
69
+ //
70
+ // NOTE: only `executeBatch` is supported for now.
71
+ //
72
+ // Parameters:
73
+ // - ctx - is the context of the operation.
74
+ // - smartWallet - is the address of the smart wallet that will execute the user operation.
75
+ // - calls - is the list of calls to be executed in the user operation. Must not be empty.
76
+ // - walletDeploymentOpts - are the options for the smart wallet deployment. Can be nil if the smart wallet is already deployed.
77
+ // - overrides - are the overrides for the middleware during the user operation creation. Can be nil.
78
+ //
79
+ // Returns:
80
+ // - UserOperation - user operation with all fields filled in.
81
+ // - error - if failed to build the user operation.
82
+ // TODO: rename to NewUserOp when this pkg is extracted.
83
+ NewUnsignedUserOp (
84
+ ctx context.Context ,
85
+ sender common.Address ,
86
+ calls smart_wallet.Calls ,
87
+ walletDeploymentOpts * WalletDeploymentOpts ,
88
+ overrides * Overrides ,
89
+ ) (UserOperation , error )
90
+
67
91
// SignUserOp signs the user operation with the provided signer.
68
92
//
69
93
// Parameters:
@@ -261,12 +285,39 @@ func (c *backend) NewUserOp(
261
285
return UserOperation {}, ErrNoSigner
262
286
}
263
287
288
+ ctx = context .WithValue (ctx , ctxKeySigner , signer )
289
+
290
+ op , err := c .NewUnsignedUserOp (ctx , smartWallet , calls , walletDeploymentOpts , overrides )
291
+ if err != nil {
292
+ return UserOperation {}, err
293
+ }
294
+
295
+ // sign
296
+ err = c .sign (ctx , & op )
297
+ if err != nil {
298
+ return UserOperation {}, err
299
+ }
300
+
301
+ b , err := op .MarshalJSON ()
302
+ if err != nil {
303
+ logger .Error ("failed to marshal user operation" , "error" , err )
304
+ } else {
305
+ logger .Debug ("signed successfully" , "userop" , string (b ))
306
+ }
307
+ return op , nil
308
+ }
309
+
310
+ func (c * backend ) NewUnsignedUserOp (
311
+ ctx context.Context ,
312
+ smartWallet common.Address ,
313
+ calls smart_wallet.Calls ,
314
+ walletDeploymentOpts * WalletDeploymentOpts ,
315
+ overrides * Overrides ,
316
+ ) (UserOperation , error ) {
264
317
if len (calls ) == 0 {
265
318
return UserOperation {}, ErrNoCalls
266
319
}
267
320
268
- ctx = context .WithValue (ctx , ctxKeySigner , signer )
269
-
270
321
callData , err := smart_wallet .BuildCallData (* c .smartWallet .Type , calls )
271
322
if err != nil {
272
323
return UserOperation {}, fmt .Errorf ("failed to build call data: %w" , err )
@@ -328,13 +379,13 @@ func (c *backend) NewUserOp(
328
379
return UserOperation {}, err
329
380
}
330
381
331
- // sign before estimating gas limits, so that signature is well-formed.
332
- // If signature is corrupted, this can cause SmartWallet estimation to fail,
333
- // and the bundler will return an error.
334
- err = c .sign (ctx , & op )
382
+ // Use stub signature before estimating gas limits. If signature is corrupted,
383
+ // this can cause SmartWallet estimation to fail, and the bundler will return an error.
384
+ stubSig , err := smart_wallet .GetStubSignature (* c .smartWallet .Type )
335
385
if err != nil {
336
386
return UserOperation {}, err
337
387
}
388
+ op .Signature = stubSig
338
389
339
390
// getGasLimits
340
391
if overridesPresent && overrides .GasLimits != nil {
@@ -353,12 +404,6 @@ func (c *backend) NewUserOp(
353
404
return UserOperation {}, err
354
405
}
355
406
356
- // sign
357
- err = c .sign (ctx , & op )
358
- if err != nil {
359
- return UserOperation {}, err
360
- }
361
-
362
407
b , err := op .MarshalJSON ()
363
408
if err != nil {
364
409
logger .Error ("failed to marshal user operation" , "error" , err )
0 commit comments