@@ -29,7 +29,7 @@ import {
29
29
type AddLog ,
30
30
} from '@metamask/logging-controller' ;
31
31
import type { NetworkControllerGetNetworkClientByIdAction } from '@metamask/network-controller' ;
32
- import type { Hex , Json } from '@metamask/utils' ;
32
+ import { hexToNumber , type Hex , type Json } from '@metamask/utils' ;
33
33
// This package purposefully relies on Node's EventEmitter module.
34
34
// eslint-disable-next-line import-x/no-nodejs-modules
35
35
import EventEmitter from 'events' ;
@@ -46,6 +46,8 @@ import type {
46
46
TypedSigningOptions ,
47
47
LegacyStateMessage ,
48
48
StateSIWEMessage ,
49
+ TypedData ,
50
+ Delegation ,
49
51
} from './types' ;
50
52
import { DECODING_API_ERRORS , decodeSignature } from './utils/decoding-api' ;
51
53
import {
@@ -131,12 +133,19 @@ export type GetSignatureState = ControllerGetStateAction<
131
133
SignatureControllerState
132
134
> ;
133
135
136
+ export type SignDelegationAction = {
137
+ type : `SignatureController:signDelegation`;
138
+ handler : SignatureController [ 'signDelegation' ] ;
139
+ } ;
140
+
134
141
export type SignatureStateChange = ControllerStateChangeEvent <
135
142
typeof controllerName ,
136
143
SignatureControllerState
137
144
> ;
138
145
139
- export type SignatureControllerActions = GetSignatureState ;
146
+ export type SignatureControllerActions =
147
+ | GetSignatureState
148
+ | SignDelegationAction ;
140
149
141
150
export type SignatureControllerEvents = SignatureStateChange ;
142
151
@@ -232,6 +241,11 @@ export class SignatureController extends BaseController<
232
241
this . #trace = trace ?? ( ( ( _request , fn ) => fn ?.( ) ) as TraceCallback ) ;
233
242
this . #decodingApiUrl = decodingApiUrl ;
234
243
this . #isDecodeSignatureRequestEnabled = isDecodeSignatureRequestEnabled ;
244
+
245
+ this . messagingSystem . registerActionHandler (
246
+ `${ this . name } :signDelegation` ,
247
+ this . signDelegation . bind ( this ) ,
248
+ ) ;
235
249
}
236
250
237
251
/**
@@ -344,6 +358,7 @@ export class SignatureController extends BaseController<
344
358
* @param version - The version of the signTypedData request.
345
359
* @param signingOptions - Options for signing the typed message.
346
360
* @param options - An options bag for the method.
361
+ * @param options.requireApproval - Whether to require user approval for the signature.
347
362
* @param options.traceContext - The parent context for any new traces.
348
363
* @returns Promise resolving to the raw signature hash generated from the signature request.
349
364
*/
@@ -352,7 +367,7 @@ export class SignatureController extends BaseController<
352
367
request : OriginalRequest ,
353
368
version : string ,
354
369
signingOptions ?: TypedSigningOptions ,
355
- options : { traceContext ?: TraceContext } = { } ,
370
+ options : { requireApproval ?: boolean ; traceContext ?: TraceContext } = { } ,
356
371
) : Promise < string > {
357
372
const chainId = this . #getChainId( request ) ;
358
373
const internalAccounts = this . #getInternalAccounts( ) ;
@@ -374,6 +389,7 @@ export class SignatureController extends BaseController<
374
389
approvalType : ApprovalType . EthSignTypedData ,
375
390
messageParams : normalizedMessageParams ,
376
391
request,
392
+ requireApproval : options . requireApproval ,
377
393
signingOptions,
378
394
traceContext : options . traceContext ,
379
395
type : SignatureRequestType . TypedSign ,
@@ -440,6 +456,75 @@ export class SignatureController extends BaseController<
440
456
this . setTypedMessageInProgress ( signatureRequestId ) ;
441
457
}
442
458
459
+ async signDelegation ( {
460
+ chainId,
461
+ delegation,
462
+ delegationManagerAddress,
463
+ from,
464
+ networkClientId,
465
+ origin,
466
+ requireApproval,
467
+ } : {
468
+ chainId : Hex ;
469
+ delegation : Delegation ;
470
+ delegationManagerAddress : Hex ;
471
+ from : Hex ;
472
+ networkClientId : string ;
473
+ origin ?: string ;
474
+ requireApproval ?: boolean ;
475
+ } ) {
476
+ const EIP712Domain = [
477
+ { name : 'name' , type : 'string' } ,
478
+ { name : 'version' , type : 'string' } ,
479
+ { name : 'chainId' , type : 'uint256' } ,
480
+ { name : 'verifyingContract' , type : 'address' } ,
481
+ ] ;
482
+
483
+ const SIGNABLE_DELEGATION_TYPED_DATA = {
484
+ EIP712Domain,
485
+ Caveat : [
486
+ { name : 'enforcer' , type : 'address' } ,
487
+ { name : 'terms' , type : 'bytes' } ,
488
+ ] ,
489
+ Delegation : [
490
+ { name : 'delegate' , type : 'address' } ,
491
+ { name : 'delegator' , type : 'address' } ,
492
+ { name : 'authority' , type : 'bytes32' } ,
493
+ { name : 'caveats' , type : 'Caveat[]' } ,
494
+ { name : 'salt' , type : 'uint256' } ,
495
+ ] ,
496
+ } ;
497
+
498
+ const data : TypedData = {
499
+ types : SIGNABLE_DELEGATION_TYPED_DATA ,
500
+ primaryType : 'Delegation' ,
501
+ domain : {
502
+ chainId : String ( hexToNumber ( chainId ) ) ,
503
+ name : 'DelegationManager' ,
504
+ version : '1' ,
505
+ verifyingContract : delegationManagerAddress ,
506
+ } ,
507
+ message : { ...delegation , chainId : hexToNumber ( chainId ) } ,
508
+ } ;
509
+
510
+ return await this . newUnsignedTypedMessage (
511
+ {
512
+ data,
513
+ from,
514
+ origin,
515
+ version : SignTypedDataVersion . V4 ,
516
+ } ,
517
+ {
518
+ networkClientId,
519
+ origin,
520
+ params : [ ] ,
521
+ } ,
522
+ SignTypedDataVersion . V4 ,
523
+ undefined ,
524
+ { requireApproval } ,
525
+ ) ;
526
+ }
527
+
443
528
#parseTypedData(
444
529
messageParams : MessageParamsTyped ,
445
530
version ?: SignTypedDataVersion ,
@@ -466,6 +551,7 @@ export class SignatureController extends BaseController<
466
551
type,
467
552
approvalType,
468
553
version,
554
+ requireApproval,
469
555
signingOptions,
470
556
traceContext,
471
557
} : {
@@ -475,6 +561,7 @@ export class SignatureController extends BaseController<
475
561
type : SignatureRequestType ;
476
562
approvalType : ApprovalType ;
477
563
version ?: SignTypedDataVersion ;
564
+ requireApproval ?: boolean ;
478
565
signingOptions ?: TypedSigningOptions ;
479
566
traceContext ?: TraceContext ;
480
567
} ) : Promise < string > {
@@ -505,12 +592,14 @@ export class SignatureController extends BaseController<
505
592
this . #decodePermitSignatureRequest( metadata . id , request , chainId ) ;
506
593
507
594
try {
508
- resultCallbacks = await this . #processApproval( {
509
- approvalType,
510
- metadata,
511
- request,
512
- traceContext,
513
- } ) ;
595
+ if ( requireApproval !== false ) {
596
+ resultCallbacks = await this . #processApproval( {
597
+ approvalType,
598
+ metadata,
599
+ request,
600
+ traceContext,
601
+ } ) ;
602
+ }
514
603
515
604
await this . #approveAndSignRequest( metadata , traceContext ) ;
516
605
} catch ( error ) {
0 commit comments