@account-kit/smart-contracts 4.25.0 → 4.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/esm/src/ma-v2/actions/deferralActions.d.ts +0 -5
  2. package/dist/esm/src/ma-v2/actions/deferralActions.js +0 -20
  3. package/dist/esm/src/ma-v2/actions/deferralActions.js.map +1 -1
  4. package/dist/esm/src/ma-v2/index.d.ts +2 -1
  5. package/dist/esm/src/ma-v2/index.js +2 -1
  6. package/dist/esm/src/ma-v2/index.js.map +1 -1
  7. package/dist/esm/src/ma-v2/permissionBuilder.d.ts +1 -0
  8. package/dist/esm/src/ma-v2/permissionBuilder.js +27 -20
  9. package/dist/esm/src/ma-v2/permissionBuilder.js.map +1 -1
  10. package/dist/esm/src/ma-v2/permissionBuilderErrors.d.ts +99 -0
  11. package/dist/esm/src/ma-v2/permissionBuilderErrors.js +176 -0
  12. package/dist/esm/src/ma-v2/permissionBuilderErrors.js.map +1 -0
  13. package/dist/esm/src/ma-v2/utils.d.ts +15 -0
  14. package/dist/esm/src/ma-v2/utils.js +20 -1
  15. package/dist/esm/src/ma-v2/utils.js.map +1 -1
  16. package/dist/types/src/ma-v2/actions/deferralActions.d.ts +0 -5
  17. package/dist/types/src/ma-v2/actions/deferralActions.d.ts.map +1 -1
  18. package/dist/types/src/ma-v2/index.d.ts +2 -1
  19. package/dist/types/src/ma-v2/index.d.ts.map +1 -1
  20. package/dist/types/src/ma-v2/permissionBuilder.d.ts +1 -0
  21. package/dist/types/src/ma-v2/permissionBuilder.d.ts.map +1 -1
  22. package/dist/types/src/ma-v2/permissionBuilderErrors.d.ts +100 -0
  23. package/dist/types/src/ma-v2/permissionBuilderErrors.d.ts.map +1 -0
  24. package/dist/types/src/ma-v2/utils.d.ts +15 -0
  25. package/dist/types/src/ma-v2/utils.d.ts.map +1 -1
  26. package/package.json +5 -5
  27. package/src/ma-v2/actions/deferralActions.ts +0 -31
  28. package/src/ma-v2/index.ts +2 -1
  29. package/src/ma-v2/permissionBuilder.ts +41 -53
  30. package/src/ma-v2/permissionBuilderErrors.ts +153 -0
  31. package/src/ma-v2/utils.ts +30 -0
@@ -51,11 +51,6 @@ export type CreateDeferredActionTypedDataParams = {
51
51
  nonce: bigint;
52
52
  };
53
53
 
54
- export type BuildDeferredActionDigestParams = {
55
- fullPreSignatureDeferredActionDigest: Hex;
56
- sig: Hex;
57
- };
58
-
59
54
  export type BuildPreSignatureDeferredActionDigestParams = {
60
55
  typedData: DeferredActionTypedData;
61
56
  };
@@ -77,7 +72,6 @@ export type DeferralActions = {
77
72
  createDeferredActionTypedDataObject: (
78
73
  args: CreateDeferredActionTypedDataParams
79
74
  ) => Promise<DeferredActionReturnData>;
80
- buildDeferredActionDigest: (args: BuildDeferredActionDigestParams) => Hex;
81
75
  buildPreSignatureDeferredActionDigest: (
82
76
  args: BuildPreSignatureDeferredActionDigestParams
83
77
  ) => Hex;
@@ -135,30 +129,6 @@ export const deferralActions: (
135
129
  };
136
130
  };
137
131
 
138
- /**
139
- * Creates the digest which must be prepended to the userOp signature.
140
- *
141
- * Assumption: The client this extends is used to sign the typed data.
142
- *
143
- * @param {object} args The argument object containing the following:
144
- * @param {Hex} args.fullPreSignatureDeferredActionDigest The The data to append the signature and length to
145
- * @param {Hex} args.sig The signature to include in the digest
146
- * @returns {Hex} The encoded digest to be prepended to the userOp signature
147
- */
148
- const buildDeferredActionDigest = ({
149
- fullPreSignatureDeferredActionDigest,
150
- sig,
151
- }: BuildDeferredActionDigestParams): Hex => {
152
- const sigLength = size(sig);
153
-
154
- const encodedData = concatHex([
155
- fullPreSignatureDeferredActionDigest,
156
- toHex(sigLength, { size: 4 }),
157
- sig,
158
- ]);
159
- return encodedData;
160
- };
161
-
162
132
  const buildPreSignatureDeferredActionDigest = ({
163
133
  typedData,
164
134
  }: BuildPreSignatureDeferredActionDigestParams): Hex => {
@@ -270,7 +240,6 @@ export const deferralActions: (
270
240
 
271
241
  return {
272
242
  createDeferredActionTypedDataObject,
273
- buildDeferredActionDigest,
274
243
  buildPreSignatureDeferredActionDigest,
275
244
  buildUserOperationWithDeferredAction,
276
245
  getEntityIdAndNonce,
@@ -24,6 +24,7 @@ export type * from "./actions/deferralActions.js";
24
24
  export { deferralActions } from "./actions/deferralActions.js";
25
25
  export type * from "./permissionBuilder.js";
26
26
  export { PermissionBuilder, PermissionType } from "./permissionBuilder.js";
27
+ export * from "./permissionBuilderErrors.js";
27
28
 
28
29
  export {
29
30
  getDefaultAllowlistModuleAddress,
@@ -33,7 +34,7 @@ export {
33
34
  getDefaultTimeRangeModuleAddress,
34
35
  getDefaultWebauthnValidationModuleAddress,
35
36
  } from "./modules/utils.js";
36
- export { buildFullNonceKey } from "./utils.js";
37
+ export { buildFullNonceKey, buildDeferredActionDigest } from "./utils.js";
37
38
  export { allowlistModuleAbi } from "./modules/allowlist-module/abis/allowlistModuleAbi.js";
38
39
  export { AllowlistModule } from "./modules/allowlist-module/module.js";
39
40
  export { nativeTokenLimitModuleAbi } from "./modules/native-token-limit-module/abis/nativeTokenLimitModuleAbi.js";
@@ -1,4 +1,4 @@
1
- import { toHex, zeroAddress, type Address, type Hex } from "viem";
1
+ import { maxUint48, toHex, zeroAddress, type Address, type Hex } from "viem";
2
2
  import {
3
3
  HookType,
4
4
  type HookConfig,
@@ -23,6 +23,19 @@ import {
23
23
  import { SingleSignerValidationModule } from "./modules/single-signer-validation/module.js";
24
24
  import { AllowlistModule } from "./modules/allowlist-module/module.js";
25
25
  import { TimeRangeModule } from "./modules/time-range-module/module.js";
26
+ import {
27
+ AccountAddressAsTargetError,
28
+ DeadlineOverLimitError,
29
+ DuplicateTargetAddressError,
30
+ ExpiredDeadlineError,
31
+ MultipleGasLimitError,
32
+ MultipleNativeTokenTransferError,
33
+ NoFunctionsProvidedError,
34
+ RootPermissionOnlyError,
35
+ UnsupportedPermissionTypeError,
36
+ ValidationConfigUnsetError,
37
+ ZeroAddressError,
38
+ } from "./permissionBuilderErrors.js";
26
39
 
27
40
  // We use this to offset the ERC20 spend limit entityId
28
41
  const HALF_UINT32 = 2147483647;
@@ -257,9 +270,7 @@ export class PermissionBuilder {
257
270
  // Check 1: If we're adding root, we can't have any other permissions
258
271
  if (permission.type === PermissionType.ROOT) {
259
272
  if (this.permissions.length !== 0) {
260
- throw new Error(
261
- "PERMISSION: ROOT: Cannot add ROOT permission with other permissions"
262
- );
273
+ throw new RootPermissionOnlyError(permission);
263
274
  }
264
275
  this.permissions.push(permission);
265
276
  // Set isGlobal to true
@@ -272,9 +283,7 @@ export class PermissionBuilder {
272
283
  // NOTE: Technically this could be replaced by checking permissions[0] since it should not be possible
273
284
  // to have >1 permission with root among them
274
285
  if (this.permissions.find((p) => p.type === PermissionType.ROOT)) {
275
- throw new Error(
276
- `PERMISSION: ${permission.type} => Cannot add permissions with ROOT enabled`
277
- );
286
+ throw new RootPermissionOnlyError(permission);
278
287
  }
279
288
 
280
289
  // Check 3: If the permission is either CONTRACT_ACCESS or FUNCTIONS_ON_CONTRACT, ensure it doesn't collide with another like it.
@@ -284,9 +293,7 @@ export class PermissionBuilder {
284
293
  ) {
285
294
  // Check 3.1: address must not be the account address, or the user should use the ACCOUNT_FUNCTIONS permission
286
295
  if (permission.data.address === this.client.account.address) {
287
- throw new Error(
288
- `PERMISSION: ${permission.type} => Account address as target, use ACCOUNT_FUNCTIONS for account address`
289
- );
296
+ throw new AccountAddressAsTargetError(permission);
290
297
  }
291
298
 
292
299
  // Check 3.2: there must not be an existing permission with this address as a target
@@ -302,20 +309,19 @@ export class PermissionBuilder {
302
309
  );
303
310
 
304
311
  if (existingPermissionWithSameAddress) {
305
- throw new Error(
306
- `PERMISSION: ${permission.type} => Address ${targetAddress} already has a permission. Cannot add multiple CONTRACT_ACCESS or FUNCTIONS_ON_CONTRACT permissions for the same target address.`
307
- );
312
+ throw new DuplicateTargetAddressError(permission, targetAddress);
308
313
  }
309
314
  }
310
315
 
311
316
  // Check 4: If the permission is ACCOUNT_FUNCTIONS, add selectors
312
317
  if (permission.type === PermissionType.ACCOUNT_FUNCTIONS) {
318
+ if (permission.data.functions.length === 0) {
319
+ throw new NoFunctionsProvidedError(permission);
320
+ }
313
321
  this.selectors = [...this.selectors, ...permission.data.functions];
314
- return this;
315
322
  }
316
323
 
317
324
  this.permissions.push(permission);
318
-
319
325
  return this;
320
326
  }
321
327
 
@@ -336,16 +342,16 @@ export class PermissionBuilder {
336
342
  // Add time range module hook via expiry
337
343
  if (this.deadline !== 0) {
338
344
  if (this.deadline < Date.now() / 1000) {
339
- throw new Error(
340
- `PERMISSION: compileDeferred(): deadline ${
341
- this.deadline
342
- } cannot be before now (${Date.now() / 1000})`
343
- );
345
+ throw new ExpiredDeadlineError(this.deadline, Date.now() / 1000);
346
+ }
347
+ if (this.deadline > maxUint48) {
348
+ throw new DeadlineOverLimitError(this.deadline);
344
349
  }
350
+
345
351
  this.hooks.push(
346
352
  TimeRangeModule.buildHook(
347
353
  {
348
- entityId: this.validationConfig.entityId, // will be timerange entityId
354
+ entityId: this.validationConfig.entityId,
349
355
  validUntil: this.deadline,
350
356
  validAfter: 0,
351
357
  },
@@ -420,9 +426,7 @@ export class PermissionBuilder {
420
426
  this.validationConfig.isGlobal === false &&
421
427
  this.selectors.length === 0
422
428
  ) {
423
- throw new Error(
424
- "Validation config unset, use permissionBuilder.configure(...)"
425
- );
429
+ throw new ValidationConfigUnsetError();
426
430
  }
427
431
  }
428
432
 
@@ -441,9 +445,7 @@ export class PermissionBuilder {
441
445
  case PermissionType.NATIVE_TOKEN_TRANSFER:
442
446
  // Should never be added twice, check is on addPermission(s) too
443
447
  if (rawHooks[HookIdentifier.NATIVE_TOKEN_TRANSFER] !== undefined) {
444
- throw new Error(
445
- "PERMISSION: NATIVE_TOKEN_TRANSFER => Must have at most ONE native token transfer permission"
446
- );
448
+ throw new MultipleNativeTokenTransferError(permission);
447
449
  }
448
450
  rawHooks[HookIdentifier.NATIVE_TOKEN_TRANSFER] = {
449
451
  hookConfig: {
@@ -464,9 +466,7 @@ export class PermissionBuilder {
464
466
  break;
465
467
  case PermissionType.ERC20_TOKEN_TRANSFER:
466
468
  if (permission.data.address === zeroAddress) {
467
- throw new Error(
468
- "PERMISSION: ERC20_TOKEN_TRANSFER => Zero address provided"
469
- );
469
+ throw new ZeroAddressError(permission);
470
470
  }
471
471
  rawHooks[HookIdentifier.ERC20_TOKEN_TRANSFER] = {
472
472
  hookConfig: {
@@ -522,9 +522,7 @@ export class PermissionBuilder {
522
522
  case PermissionType.GAS_LIMIT:
523
523
  // Should only ever be added once, check is also on addPermission(s)
524
524
  if (rawHooks[HookIdentifier.GAS_LIMIT] !== undefined) {
525
- throw new Error(
526
- "PERMISSION: GAS_LIMIT => Must have at most ONE gas limit permission"
527
- );
525
+ throw new MultipleGasLimitError(permission);
528
526
  }
529
527
  rawHooks[HookIdentifier.GAS_LIMIT] = {
530
528
  hookConfig: {
@@ -544,9 +542,7 @@ export class PermissionBuilder {
544
542
  break;
545
543
  case PermissionType.CONTRACT_ACCESS:
546
544
  if (permission.data.address === zeroAddress) {
547
- throw new Error(
548
- "PERMISSION: CONTRACT_ACCESS => Zero address provided"
549
- );
545
+ throw new ZeroAddressError(permission);
550
546
  }
551
547
  rawHooks[HookIdentifier.PREVAL_ALLOWLIST] = {
552
548
  hookConfig: {
@@ -574,17 +570,11 @@ export class PermissionBuilder {
574
570
  };
575
571
  break;
576
572
  case PermissionType.ACCOUNT_FUNCTIONS:
577
- if (permission.data.functions.length === 0) {
578
- throw new Error(
579
- "PERMISSION: ACCOUNT_FUNCTION => No functions provided"
580
- ); // should be in add perm
581
- }
573
+ // This is handled in add permissions
582
574
  break;
583
575
  case PermissionType.FUNCTIONS_ON_ALL_CONTRACTS:
584
576
  if (permission.data.functions.length === 0) {
585
- throw new Error(
586
- "PERMISSION: FUNCTIONS_ON_ALL_CONTRACTS => No functions provided"
587
- );
577
+ throw new NoFunctionsProvidedError(permission);
588
578
  }
589
579
  rawHooks[HookIdentifier.PREVAL_ALLOWLIST] = {
590
580
  hookConfig: {
@@ -613,14 +603,10 @@ export class PermissionBuilder {
613
603
  break;
614
604
  case PermissionType.FUNCTIONS_ON_CONTRACT:
615
605
  if (permission.data.functions.length === 0) {
616
- throw new Error(
617
- "PERMISSION: FUNCTIONS_ON_CONTRACT => No functions provided"
618
- );
606
+ throw new NoFunctionsProvidedError(permission);
619
607
  }
620
608
  if (permission.data.address === zeroAddress) {
621
- throw new Error(
622
- "PERMISSION: FUNCTIONS_ON_CONTRACT => Zero address provided"
623
- );
609
+ throw new ZeroAddressError(permission);
624
610
  }
625
611
  rawHooks[HookIdentifier.PREVAL_ALLOWLIST] = {
626
612
  hookConfig: {
@@ -651,9 +637,7 @@ export class PermissionBuilder {
651
637
  // Root permission handled in addPermission
652
638
  break;
653
639
  default:
654
- throw new Error(
655
- `Unsupported permission type: ${(permission as any).type}`
656
- );
640
+ assertNever(permission);
657
641
  }
658
642
 
659
643
  // isGlobal guaranteed to be false since it's only set with root permissions,
@@ -714,3 +698,7 @@ export class PermissionBuilder {
714
698
  }
715
699
  }
716
700
  }
701
+
702
+ export function assertNever(_valid: never): never {
703
+ throw new UnsupportedPermissionTypeError();
704
+ }
@@ -0,0 +1,153 @@
1
+ import { BaseError, type Address } from "@aa-sdk/core";
2
+ import type { Permission } from "./permissionBuilder";
3
+
4
+ export class RootPermissionOnlyError extends BaseError {
5
+ override name = "PermissionBuilder: RootPermissionOnlyError";
6
+
7
+ /**
8
+ * Constructor for initializing an error message indicating that an account could not be found to execute the specified action.
9
+ *
10
+ * @param {Permission} permission The permission trying to be added atop the root permission
11
+ */
12
+ constructor(permission: Permission) {
13
+ super(`Adding ${permission}: Cannot add permissions with ROOT permission`);
14
+ }
15
+ }
16
+
17
+ export class AccountAddressAsTargetError extends BaseError {
18
+ override name = "PermissionBuilder: AccountAddressAsTargetError";
19
+
20
+ /**
21
+ * Constructor for initializing an error message indicating that account address is used as target.
22
+ *
23
+ * @param {Permission} permission The permission with account address as target
24
+ */
25
+ constructor(permission: Permission) {
26
+ super(
27
+ `${permission.type}: Account address as target, use ACCOUNT_FUNCTIONS for account address`
28
+ );
29
+ }
30
+ }
31
+
32
+ export class DuplicateTargetAddressError extends BaseError {
33
+ override name = "PermissionBuilder: DuplicateTargetAddressError";
34
+
35
+ /**
36
+ * Constructor for initializing an error message indicating duplicate target address in permissions.
37
+ *
38
+ * @param {Permission} permission The permission with duplicate target address
39
+ * @param {Address} targetAddress The duplicate target address
40
+ */
41
+ constructor(permission: Permission, targetAddress: Address) {
42
+ super(
43
+ `${permission.type}: Address ${targetAddress} already has a permission. Cannot add multiple CONTRACT_ACCESS or FUNCTIONS_ON_CONTRACT permissions for the same target address.`
44
+ );
45
+ }
46
+ }
47
+
48
+ export class NoFunctionsProvidedError extends BaseError {
49
+ override name = "PermissionBuilder: NoFunctionsProvidedError";
50
+
51
+ /**
52
+ * Constructor for initializing an error message indicating no functions were provided.
53
+ *
54
+ * @param {Permission} permission The permission missing functions
55
+ */
56
+ constructor(permission: Permission) {
57
+ super(`${permission.type}: No functions provided`);
58
+ }
59
+ }
60
+
61
+ export class ExpiredDeadlineError extends BaseError {
62
+ override name = "PermissionBuilder: ExpiredDeadlineError";
63
+
64
+ /**
65
+ * Constructor for initializing an error message indicating the deadline has expired.
66
+ *
67
+ * @param {number} deadline The expired deadline timestamp
68
+ * @param {number} currentTime The current timestamp
69
+ */
70
+ constructor(deadline: number, currentTime: number) {
71
+ super(
72
+ `compileDeferred(): deadline ${deadline} cannot be before now (${currentTime})`
73
+ );
74
+ }
75
+ }
76
+
77
+ export class DeadlineOverLimitError extends BaseError {
78
+ override name = "PermissionBuilder: DeadlineOverLimitError";
79
+
80
+ /**
81
+ * Constructor for initializing an error message indicating the deadline has expired.
82
+ *
83
+ * @param {number} deadline The expired deadline timestamp
84
+ */
85
+ constructor(deadline: number) {
86
+ super(
87
+ `compileDeferred(): deadline ${deadline} cannot be > max uint48 (2^48 - 1)`
88
+ );
89
+ }
90
+ }
91
+
92
+ export class ValidationConfigUnsetError extends BaseError {
93
+ override name = "PermissionBuilder: ValidationConfigUnsetError";
94
+
95
+ /**
96
+ * Constructor for initializing an error message indicating the validation config is unset.
97
+ */
98
+ constructor() {
99
+ super("Validation config unset, use permissionBuilder.configure(...)");
100
+ }
101
+ }
102
+
103
+ export class MultipleNativeTokenTransferError extends BaseError {
104
+ override name = "PermissionBuilder: MultipleNativeTokenTransferError";
105
+
106
+ /**
107
+ * Constructor for initializing an error message indicating multiple native token transfer permissions.
108
+ *
109
+ * @param {Permission} permission The duplicate native token transfer permission
110
+ */
111
+ constructor(permission: Permission) {
112
+ super(
113
+ `${permission.type}: Must have at most ONE native token transfer permission`
114
+ );
115
+ }
116
+ }
117
+
118
+ export class ZeroAddressError extends BaseError {
119
+ override name = "PermissionBuilder: ZeroAddressError";
120
+
121
+ /**
122
+ * Constructor for initializing an error message indicating zero address was provided.
123
+ *
124
+ * @param {Permission} permission The permission with zero address
125
+ */
126
+ constructor(permission: Permission) {
127
+ super(`${permission.type}: Zero address provided`);
128
+ }
129
+ }
130
+
131
+ export class MultipleGasLimitError extends BaseError {
132
+ override name = "PermissionBuilder: MultipleGasLimitError";
133
+
134
+ /**
135
+ * Constructor for initializing an error message indicating multiple gas limit permissions.
136
+ *
137
+ * @param {Permission} permission The duplicate gas limit permission
138
+ */
139
+ constructor(permission: Permission) {
140
+ super(`${permission.type}: Must have at most ONE gas limit permission`);
141
+ }
142
+ }
143
+
144
+ export class UnsupportedPermissionTypeError extends BaseError {
145
+ override name = "PermissionBuilder: UnsupportedPermissionTypeError";
146
+
147
+ /**
148
+ * Constructor for initializing an error message indicating an unsupported permission type.
149
+ */
150
+ constructor() {
151
+ super(`Unsupported permission type`);
152
+ }
153
+ }
@@ -8,6 +8,8 @@ import {
8
8
  type Address,
9
9
  type Transport,
10
10
  parseAbi,
11
+ size,
12
+ concatHex,
11
13
  } from "viem";
12
14
  import {
13
15
  arbitrum,
@@ -278,3 +280,31 @@ export const parseDeferredAction = (
278
280
  hasAssociatedExecHooks: deferredAction[3] === "1",
279
281
  };
280
282
  };
283
+ export type BuildDeferredActionDigestParams = {
284
+ fullPreSignatureDeferredActionDigest: Hex;
285
+ sig: Hex;
286
+ };
287
+
288
+ /**
289
+ * Creates the digest which must be prepended to the userOp signature.
290
+ *
291
+ * Assumption: The client this extends is used to sign the typed data.
292
+ *
293
+ * @param {object} args The argument object containing the following:
294
+ * @param {Hex} args.fullPreSignatureDeferredActionDigest The The data to append the signature and length to
295
+ * @param {Hex} args.sig The signature to include in the digest
296
+ * @returns {Hex} The encoded digest to be prepended to the userOp signature
297
+ */
298
+ export const buildDeferredActionDigest = ({
299
+ fullPreSignatureDeferredActionDigest,
300
+ sig,
301
+ }: BuildDeferredActionDigestParams): Hex => {
302
+ const sigLength = size(sig);
303
+
304
+ const encodedData = concatHex([
305
+ fullPreSignatureDeferredActionDigest,
306
+ toHex(sigLength, { size: 4 }),
307
+ sig,
308
+ ]);
309
+ return encodedData;
310
+ };