@rhinestone/sdk 2.0.0 → 2.2.0

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 (62) hide show
  1. package/dist/src/accounts/adapters/hca.d.ts.map +1 -1
  2. package/dist/src/accounts/adapters/hca.js +4 -1
  3. package/dist/src/actions/ecdsa.d.ts +1 -1
  4. package/dist/src/actions/ecdsa.d.ts.map +1 -1
  5. package/dist/src/actions/ecdsa.js +4 -57
  6. package/dist/src/actions/ownable.d.ts +6 -0
  7. package/dist/src/actions/ownable.d.ts.map +1 -0
  8. package/dist/src/actions/ownable.js +63 -0
  9. package/dist/src/actions/passkeys.d.ts.map +1 -1
  10. package/dist/src/actions/passkeys.js +4 -64
  11. package/dist/src/actions/recovery.d.ts +67 -0
  12. package/dist/src/actions/recovery.d.ts.map +1 -0
  13. package/dist/src/actions/recovery.js +134 -0
  14. package/dist/src/actions/runtime.d.ts +5 -0
  15. package/dist/src/actions/runtime.d.ts.map +1 -1
  16. package/dist/src/actions/runtime.js +25 -1
  17. package/dist/src/actions/webauthn.d.ts +6 -0
  18. package/dist/src/actions/webauthn.d.ts.map +1 -0
  19. package/dist/src/actions/webauthn.js +67 -0
  20. package/dist/src/api/account.d.ts.map +1 -1
  21. package/dist/src/api/account.js +8 -2
  22. package/dist/src/api/compose.d.ts.map +1 -1
  23. package/dist/src/api/compose.js +6 -0
  24. package/dist/src/api/signer-selection.d.ts +13 -0
  25. package/dist/src/api/signer-selection.d.ts.map +1 -1
  26. package/dist/src/api/signer-selection.js +50 -0
  27. package/dist/src/clients/orchestrator/auth.d.ts +2 -1
  28. package/dist/src/clients/orchestrator/auth.d.ts.map +1 -1
  29. package/dist/src/clients/orchestrator/client.d.ts.map +1 -1
  30. package/dist/src/clients/orchestrator/client.js +1 -1
  31. package/dist/src/clients/orchestrator/public.d.ts +31 -6
  32. package/dist/src/clients/orchestrator/public.d.ts.map +1 -1
  33. package/dist/src/clients/orchestrator/types.d.ts +2 -2
  34. package/dist/src/clients/orchestrator/types.d.ts.map +1 -1
  35. package/dist/src/config/account.d.ts +32 -7
  36. package/dist/src/config/account.d.ts.map +1 -1
  37. package/dist/src/config/input.d.ts +7 -1
  38. package/dist/src/config/input.d.ts.map +1 -1
  39. package/dist/src/config/resolve.d.ts.map +1 -1
  40. package/dist/src/config/resolve.js +27 -1
  41. package/dist/src/config/resolved.d.ts +2 -1
  42. package/dist/src/config/resolved.d.ts.map +1 -1
  43. package/dist/src/errors/execution.d.ts +8 -1
  44. package/dist/src/errors/execution.d.ts.map +1 -1
  45. package/dist/src/errors/execution.js +9 -1
  46. package/dist/src/errors/index.d.ts +2 -2
  47. package/dist/src/errors/index.d.ts.map +1 -1
  48. package/dist/src/errors/index.js +2 -2
  49. package/dist/src/index.d.ts +2 -2
  50. package/dist/src/index.d.ts.map +1 -1
  51. package/dist/src/modules/read-core.d.ts +23 -0
  52. package/dist/src/modules/read-core.d.ts.map +1 -1
  53. package/dist/src/modules/read-core.js +58 -1
  54. package/dist/src/modules/validators/social-recovery.d.ts +16 -0
  55. package/dist/src/modules/validators/social-recovery.d.ts.map +1 -0
  56. package/dist/src/modules/validators/social-recovery.js +17 -0
  57. package/dist/src/transactions/intents/compatibility.d.ts +2 -1
  58. package/dist/src/transactions/intents/compatibility.d.ts.map +1 -1
  59. package/dist/src/transactions/intents/compatibility.js +3 -0
  60. package/dist/src/transactions/intents/types.d.ts +3 -2
  61. package/dist/src/transactions/intents/types.d.ts.map +1 -1
  62. package/package.json +5 -1
@@ -1 +1 @@
1
- {"version":3,"file":"hca.d.ts","sourceRoot":"","sources":["../../../../accounts/adapters/hca.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAIhD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAGnD,eAAO,MAAM,0BAA0B,EACrC,4CAAqD,CAAA;AAwFvD,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,mBAAmB,GAChC,cAAc,CAqChB"}
1
+ {"version":3,"file":"hca.d.ts","sourceRoot":"","sources":["../../../../accounts/adapters/hca.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAIhD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAGnD,eAAO,MAAM,0BAA0B,EACrC,4CAAqD,CAAA;AA2FvD,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,mBAAmB,GAChC,cAAc,CAqChB"}
@@ -38,8 +38,11 @@ function hcaMaterial(input) {
38
38
  throw new Error('Expected HCA account');
39
39
  if (input.eoa)
40
40
  return { address: input.eoa.address };
41
+ // HCA derives its address from the ENS owner alone and has no module
42
+ // installation, so recovery, sessions, and extra modules can never be
43
+ // installed. `recovery` resolves into `modules`, so it is rejected here too.
41
44
  if (input.sessions.enabled || input.modules.length > 0) {
42
- throw new Error('HCA accounts cannot install sessions or additional modules');
45
+ throw new Error('HCA accounts cannot install recovery, sessions, or additional modules');
43
46
  }
44
47
  if (!input.owner || input.owner.kind !== 'ens') {
45
48
  throw new Error('HCA accounts require ENS owners');
@@ -1,4 +1,4 @@
1
- import { type Address } from 'viem';
1
+ import type { Address } from 'viem';
2
2
  import type { CalldataInput, LazyCallInput } from '../config/account.js';
3
3
  /**
4
4
  * Enable ECDSA authentication
@@ -1 +1 @@
1
- {"version":3,"file":"ecdsa.d.ts","sourceRoot":"","sources":["../../../actions/ecdsa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,MAAM,CAAA;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAUrE;;;;;GAKG;AACH,iBAAS,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,SAAS,SAAI,GAAG,aAAa,CAO/D;AAED;;;GAGG;AACH,iBAAS,OAAO,IAAI,aAAa,CAOhC;AAED;;;;GAIG;AACH,iBAAS,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAkB/C;AAED;;;;;GAKG;AACH,iBAAS,WAAW,CAClB,SAAS,EAAE,OAAO,EAClB,aAAa,EAAE,OAAO,GACrB,aAAa,CAqBf;AAED;;;;GAIG;AACH,iBAAS,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,CAoB5D;AAED,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA"}
1
+ {"version":3,"file":"ecdsa.d.ts","sourceRoot":"","sources":["../../../actions/ecdsa.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAerE;;;;;GAKG;AACH,iBAAS,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,SAAS,SAAI,GAAG,aAAa,CAO/D;AAED;;;GAGG;AACH,iBAAS,OAAO,IAAI,aAAa,CAOhC;AAED;;;;GAIG;AACH,iBAAS,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAE/C;AAED;;;;;GAKG;AACH,iBAAS,WAAW,CAClB,SAAS,EAAE,OAAO,EAClB,aAAa,EAAE,OAAO,GACrB,aAAa,CAEf;AAED;;;;GAIG;AACH,iBAAS,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,CAE5D;AAED,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA"}
@@ -1,5 +1,5 @@
1
- import { encodeFunctionData } from 'viem';
2
1
  import { OWNABLE_VALIDATOR_ADDRESS, resolveOwnableAddresses, } from '../modules/validators/ownable.js';
2
+ import { addOwnableOwner, changeOwnableThreshold, removeOwnableOwner, } from './ownable.js';
3
3
  import { resolveModuleUninstallation, resolveValidatorInstallation, } from './runtime.js';
4
4
  /**
5
5
  * Enable ECDSA authentication
@@ -33,23 +33,7 @@ function disable() {
33
33
  * @returns Call to add the owner
34
34
  */
35
35
  function addOwner(owner) {
36
- return {
37
- to: OWNABLE_VALIDATOR_ADDRESS,
38
- value: 0n,
39
- data: encodeFunctionData({
40
- abi: [
41
- {
42
- inputs: [{ internalType: 'address', name: 'owner', type: 'address' }],
43
- name: 'addOwner',
44
- outputs: [],
45
- stateMutability: 'nonpayable',
46
- type: 'function',
47
- },
48
- ],
49
- functionName: 'addOwner',
50
- args: [owner],
51
- }),
52
- };
36
+ return addOwnableOwner(OWNABLE_VALIDATOR_ADDRESS, owner);
53
37
  }
54
38
  /**
55
39
  * Remove an ECDSA owner
@@ -58,26 +42,7 @@ function addOwner(owner) {
58
42
  * @returns Call to remove the owner
59
43
  */
60
44
  function removeOwner(prevOwner, ownerToRemove) {
61
- return {
62
- to: OWNABLE_VALIDATOR_ADDRESS,
63
- value: 0n,
64
- data: encodeFunctionData({
65
- abi: [
66
- {
67
- inputs: [
68
- { internalType: 'address', name: 'prevOwner', type: 'address' },
69
- { internalType: 'address', name: 'owner', type: 'address' },
70
- ],
71
- name: 'removeOwner',
72
- outputs: [],
73
- stateMutability: 'nonpayable',
74
- type: 'function',
75
- },
76
- ],
77
- functionName: 'removeOwner',
78
- args: [prevOwner, ownerToRemove],
79
- }),
80
- };
45
+ return removeOwnableOwner(OWNABLE_VALIDATOR_ADDRESS, prevOwner, ownerToRemove);
81
46
  }
82
47
  /**
83
48
  * Change an account's signer threshold (ECDSA)
@@ -85,24 +50,6 @@ function removeOwner(prevOwner, ownerToRemove) {
85
50
  * @returns Call to change the threshold
86
51
  */
87
52
  function changeThreshold(newThreshold) {
88
- return {
89
- to: OWNABLE_VALIDATOR_ADDRESS,
90
- value: 0n,
91
- data: encodeFunctionData({
92
- abi: [
93
- {
94
- inputs: [
95
- { internalType: 'uint256', name: '_threshold', type: 'uint256' },
96
- ],
97
- name: 'setThreshold',
98
- outputs: [],
99
- stateMutability: 'nonpayable',
100
- type: 'function',
101
- },
102
- ],
103
- functionName: 'setThreshold',
104
- args: [BigInt(newThreshold)],
105
- }),
106
- };
53
+ return changeOwnableThreshold(OWNABLE_VALIDATOR_ADDRESS, newThreshold);
107
54
  }
108
55
  export { addOwner, removeOwner, changeThreshold, disable, enable };
@@ -0,0 +1,6 @@
1
+ import { type Address } from 'viem';
2
+ import type { CalldataInput } from '../config/account.js';
3
+ export declare function addOwnableOwner(validator: Address, owner: Address): CalldataInput;
4
+ export declare function removeOwnableOwner(validator: Address, prevOwner: Address, ownerToRemove: Address): CalldataInput;
5
+ export declare function changeOwnableThreshold(validator: Address, newThreshold: number): CalldataInput;
6
+ //# sourceMappingURL=ownable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownable.d.ts","sourceRoot":"","sources":["../../../actions/ownable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,MAAM,CAAA;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEtD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,OAAO,GACb,aAAa,CAkBf;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,OAAO,EAClB,SAAS,EAAE,OAAO,EAClB,aAAa,EAAE,OAAO,GACrB,aAAa,CAqBf;AAED,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,OAAO,EAClB,YAAY,EAAE,MAAM,GACnB,aAAa,CAoBf"}
@@ -0,0 +1,63 @@
1
+ import { encodeFunctionData } from 'viem';
2
+ export function addOwnableOwner(validator, owner) {
3
+ return {
4
+ to: validator,
5
+ value: 0n,
6
+ data: encodeFunctionData({
7
+ abi: [
8
+ {
9
+ inputs: [{ internalType: 'address', name: 'owner', type: 'address' }],
10
+ name: 'addOwner',
11
+ outputs: [],
12
+ stateMutability: 'nonpayable',
13
+ type: 'function',
14
+ },
15
+ ],
16
+ functionName: 'addOwner',
17
+ args: [owner],
18
+ }),
19
+ };
20
+ }
21
+ export function removeOwnableOwner(validator, prevOwner, ownerToRemove) {
22
+ return {
23
+ to: validator,
24
+ value: 0n,
25
+ data: encodeFunctionData({
26
+ abi: [
27
+ {
28
+ inputs: [
29
+ { internalType: 'address', name: 'prevOwner', type: 'address' },
30
+ { internalType: 'address', name: 'owner', type: 'address' },
31
+ ],
32
+ name: 'removeOwner',
33
+ outputs: [],
34
+ stateMutability: 'nonpayable',
35
+ type: 'function',
36
+ },
37
+ ],
38
+ functionName: 'removeOwner',
39
+ args: [prevOwner, ownerToRemove],
40
+ }),
41
+ };
42
+ }
43
+ export function changeOwnableThreshold(validator, newThreshold) {
44
+ return {
45
+ to: validator,
46
+ value: 0n,
47
+ data: encodeFunctionData({
48
+ abi: [
49
+ {
50
+ inputs: [
51
+ { internalType: 'uint256', name: '_threshold', type: 'uint256' },
52
+ ],
53
+ name: 'setThreshold',
54
+ outputs: [],
55
+ stateMutability: 'nonpayable',
56
+ type: 'function',
57
+ },
58
+ ],
59
+ functionName: 'setThreshold',
60
+ args: [BigInt(newThreshold)],
61
+ }),
62
+ };
63
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"passkeys.d.ts","sourceRoot":"","sources":["../../../actions/passkeys.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACrE,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,gCAAgC,CAAA;AAMvC;;;;;GAKG;AACH,iBAAS,MAAM,CAAC,UAAU,EAAE,kBAAkB,GAAG,aAAa,CAU7D;AAED;;;GAGG;AACH,iBAAS,OAAO,IAAI,aAAa,CAgBhC;AAED;;;;;;GAMG;AACH,iBAAS,QAAQ,CACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,uBAAuB,EAAE,OAAO,GAC/B,aAAa,CAyBf;AAED;;;;;GAKG;AACH,iBAAS,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAqBpE;AAED;;;;GAIG;AACH,iBAAS,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,CAoB5D;AAED,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA"}
1
+ {"version":3,"file":"passkeys.d.ts","sourceRoot":"","sources":["../../../actions/passkeys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACrE,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,gCAAgC,CAAA;AAWvC;;;;;GAKG;AACH,iBAAS,MAAM,CAAC,UAAU,EAAE,kBAAkB,GAAG,aAAa,CAU7D;AAED;;;GAGG;AACH,iBAAS,OAAO,IAAI,aAAa,CAgBhC;AAED;;;;;;GAMG;AACH,iBAAS,QAAQ,CACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,uBAAuB,EAAE,OAAO,GAC/B,aAAa,CAOf;AAED;;;;;GAKG;AACH,iBAAS,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAEpE;AAED;;;;GAIG;AACH,iBAAS,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,CAE5D;AAED,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA"}
@@ -1,6 +1,6 @@
1
- import { encodeFunctionData } from 'viem';
2
1
  import { resolveWebauthnCredentials, WEBAUTHN_VALIDATOR_ADDRESS, } from '../modules/validators/webauthn.js';
3
2
  import { resolveModuleInstallation, resolveModuleUninstallation, } from './runtime.js';
3
+ import { addWebauthnCredential, changeWebauthnThreshold, removeWebauthnCredential, } from './webauthn.js';
4
4
  /**
5
5
  * Enable passkeys authentication
6
6
  * @param pubKey Public key for the passkey
@@ -46,30 +46,7 @@ function disable() {
46
46
  * @returns Call to add the passkey owner
47
47
  */
48
48
  function addOwner(pubKeyX, pubKeyY, requireUserVerification) {
49
- return {
50
- to: WEBAUTHN_VALIDATOR_ADDRESS,
51
- value: 0n,
52
- data: encodeFunctionData({
53
- abi: [
54
- {
55
- inputs: [
56
- { name: 'pubKeyX', type: 'uint256' },
57
- { name: 'pubKeyY', type: 'uint256' },
58
- {
59
- name: 'requireUserVerification',
60
- type: 'bool',
61
- },
62
- ],
63
- name: 'addCredential',
64
- outputs: [],
65
- stateMutability: 'nonpayable',
66
- type: 'function',
67
- },
68
- ],
69
- functionName: 'addCredential',
70
- args: [pubKeyX, pubKeyY, requireUserVerification],
71
- }),
72
- };
49
+ return addWebauthnCredential(WEBAUTHN_VALIDATOR_ADDRESS, pubKeyX, pubKeyY, requireUserVerification);
73
50
  }
74
51
  /**
75
52
  * Remove a passkey owner
@@ -78,26 +55,7 @@ function addOwner(pubKeyX, pubKeyY, requireUserVerification) {
78
55
  * @returns Call to remove the passkey owner
79
56
  */
80
57
  function removeOwner(pubKeyX, pubKeyY) {
81
- return {
82
- to: WEBAUTHN_VALIDATOR_ADDRESS,
83
- value: 0n,
84
- data: encodeFunctionData({
85
- abi: [
86
- {
87
- inputs: [
88
- { name: 'pubKeyX', type: 'uint256' },
89
- { name: 'pubKeyY', type: 'uint256' },
90
- ],
91
- name: 'removeCredential',
92
- outputs: [],
93
- stateMutability: 'nonpayable',
94
- type: 'function',
95
- },
96
- ],
97
- functionName: 'removeCredential',
98
- args: [pubKeyX, pubKeyY],
99
- }),
100
- };
58
+ return removeWebauthnCredential(WEBAUTHN_VALIDATOR_ADDRESS, pubKeyX, pubKeyY);
101
59
  }
102
60
  /**
103
61
  * Change an account's signer threshold (passkey)
@@ -105,24 +63,6 @@ function removeOwner(pubKeyX, pubKeyY) {
105
63
  * @returns Call to change the threshold
106
64
  */
107
65
  function changeThreshold(newThreshold) {
108
- return {
109
- to: WEBAUTHN_VALIDATOR_ADDRESS,
110
- value: 0n,
111
- data: encodeFunctionData({
112
- abi: [
113
- {
114
- inputs: [
115
- { internalType: 'uint256', name: '_threshold', type: 'uint256' },
116
- ],
117
- name: 'setThreshold',
118
- outputs: [],
119
- stateMutability: 'nonpayable',
120
- type: 'function',
121
- },
122
- ],
123
- functionName: 'setThreshold',
124
- args: [BigInt(newThreshold)],
125
- }),
126
- };
66
+ return changeWebauthnThreshold(WEBAUTHN_VALIDATOR_ADDRESS, newThreshold);
127
67
  }
128
68
  export { addOwner, removeOwner, changeThreshold, disable, enable };
@@ -0,0 +1,67 @@
1
+ import { type Account } from 'viem';
2
+ import type { CalldataInput, CallResolveContext, LazyCallInput, OwnableValidatorConfig, WebauthnValidatorConfig } from '../config/account.js';
3
+ interface PasskeyCredential {
4
+ pubKeyX: bigint;
5
+ pubKeyY: bigint;
6
+ }
7
+ export interface RecoverEcdsaOwnershipOptions extends CallResolveContext {
8
+ /**
9
+ * Target owner set. Existing owners not listed here are removed. If supplied,
10
+ * `module` must match the account's configured owner validator.
11
+ */
12
+ newOwners: OwnableValidatorConfig;
13
+ }
14
+ export interface RecoverPasskeyOwnershipOptions extends CallResolveContext {
15
+ /**
16
+ * The account's complete current credential set, not just the ones being
17
+ * replaced. Credentials absent from `newOwners` are removed, and those
18
+ * already present here are not added again — passing a partial set makes the
19
+ * recovery re-add an installed credential, which reverts with
20
+ * `CredentialAlreadyExists`.
21
+ *
22
+ * This has to be supplied because the validator stores credentials by hashed
23
+ * id, so their coordinates cannot be read back onchain.
24
+ */
25
+ currentCredentials: readonly PasskeyCredential[];
26
+ /**
27
+ * Target passkey owner set. If supplied, `module` must match the account's
28
+ * configured owner validator.
29
+ */
30
+ newOwners: WebauthnValidatorConfig;
31
+ }
32
+ /**
33
+ * Set up social recovery.
34
+ *
35
+ * @param guardians Guardians permitted to recover the account
36
+ * @param threshold Guardian signatures required to recover
37
+ * @returns Calls to install the social recovery validator
38
+ */
39
+ declare function enable(guardians: Account[], threshold?: number): LazyCallInput;
40
+ /**
41
+ * Build the calls that rotate an account's ECDSA ownership.
42
+ *
43
+ * Send each returned call as its own UserOperation, in order: the social
44
+ * recovery validator authorizes a single `execute` per UserOperation, so
45
+ * batching them is rejected onchain.
46
+ *
47
+ * Ownership is only fully rotated once every call has landed. Until the
48
+ * removals execute the previous owners stay valid alongside the new ones.
49
+ *
50
+ * @returns Calls to recover ownership, in the order they must be sent
51
+ */
52
+ declare function recoverEcdsaOwnership(options: RecoverEcdsaOwnershipOptions): Promise<CalldataInput[]>;
53
+ /**
54
+ * Build the calls that rotate an account's passkey ownership.
55
+ *
56
+ * Send each returned call as its own UserOperation, in order: the social
57
+ * recovery validator authorizes a single `execute` per UserOperation, so
58
+ * batching them is rejected onchain.
59
+ *
60
+ * Ownership is only fully rotated once every call has landed. Until the
61
+ * removals execute the previous credentials stay valid alongside the new ones.
62
+ *
63
+ * @returns Calls to recover ownership, in the order they must be sent
64
+ */
65
+ declare function recoverPasskeyOwnership(options: RecoverPasskeyOwnershipOptions): Promise<CalldataInput[]>;
66
+ export { enable, recoverEcdsaOwnership, recoverPasskeyOwnership };
67
+ //# sourceMappingURL=recovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../../actions/recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAgC,MAAM,MAAM,CAAA;AACjE,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,mBAAmB,CAAA;AA0B1B,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,4BAA6B,SAAQ,kBAAkB;IACtE;;;OAGG;IACH,SAAS,EAAE,sBAAsB,CAAA;CAClC;AAED,MAAM,WAAW,8BAA+B,SAAQ,kBAAkB;IACxE;;;;;;;;;OASG;IACH,kBAAkB,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAChD;;;OAGG;IACH,SAAS,EAAE,uBAAuB,CAAA;CACnC;AAED;;;;;;GAMG;AACH,iBAAS,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,SAAS,SAAI,GAAG,aAAa,CAUlE;AAED;;;;;;;;;;;GAWG;AACH,iBAAe,qBAAqB,CAClC,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,aAAa,EAAE,CAAC,CA4D1B;AAED;;;;;;;;;;;GAWG;AACH,iBAAe,uBAAuB,CACpC,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,aAAa,EAAE,CAAC,CAwE1B;AAMD,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,CAAA"}
@@ -0,0 +1,134 @@
1
+ import { isAddressEqual } from 'viem';
2
+ import { OWNABLE_VALIDATOR_ADDRESS } from '../modules/validators/ownable.js';
3
+ import { resolveSocialRecoveryValidator } from '../modules/validators/social-recovery.js';
4
+ import { parseWebauthnPublicKey, WEBAUTHN_VALIDATOR_ADDRESS, } from '../modules/validators/webauthn.js';
5
+ import { addOwnableOwner, changeOwnableThreshold, removeOwnableOwner, } from './ownable.js';
6
+ import { readOwnershipFor, readThresholdFor, resolveValidatorInstallation, } from './runtime.js';
7
+ import { addWebauthnCredential, changeWebauthnThreshold, removeWebauthnCredential, } from './webauthn.js';
8
+ /** Sentinel head of the validator's owner linked list. */
9
+ const SENTINEL_OWNER = '0x0000000000000000000000000000000000000001';
10
+ /**
11
+ * Set up social recovery.
12
+ *
13
+ * @param guardians Guardians permitted to recover the account
14
+ * @param threshold Guardian signatures required to recover
15
+ * @returns Calls to install the social recovery validator
16
+ */
17
+ function enable(guardians, threshold = 1) {
18
+ const module = resolveSocialRecoveryValidator({
19
+ guardians: guardians.map((guardian) => guardian.address),
20
+ threshold,
21
+ });
22
+ return {
23
+ async resolve(context) {
24
+ return resolveValidatorInstallation(context, module);
25
+ },
26
+ };
27
+ }
28
+ /**
29
+ * Build the calls that rotate an account's ECDSA ownership.
30
+ *
31
+ * Send each returned call as its own UserOperation, in order: the social
32
+ * recovery validator authorizes a single `execute` per UserOperation, so
33
+ * batching them is rejected onchain.
34
+ *
35
+ * Ownership is only fully rotated once every call has landed. Until the
36
+ * removals execute the previous owners stay valid alongside the new ones.
37
+ *
38
+ * @returns Calls to recover ownership, in the order they must be sent
39
+ */
40
+ async function recoverEcdsaOwnership(options) {
41
+ const configuredValidator = options.config.owners?.type === 'ecdsa'
42
+ ? (options.config.owners.module ?? OWNABLE_VALIDATOR_ADDRESS)
43
+ : undefined;
44
+ const requestedValidator = options.newOwners.module;
45
+ if (configuredValidator &&
46
+ requestedValidator &&
47
+ !isAddressEqual(configuredValidator, requestedValidator)) {
48
+ throw new Error('Recovery owner validator must match the configured owner validator');
49
+ }
50
+ const validator = configuredValidator ?? requestedValidator ?? OWNABLE_VALIDATOR_ADDRESS;
51
+ const existing = await readOwnershipFor(options, options.accountAddress, validator);
52
+ const newOwners = options.newOwners.accounts
53
+ .map((account) => account.address.toLowerCase())
54
+ .sort();
55
+ const newThreshold = options.newOwners.threshold ?? 1;
56
+ const ownersToAdd = newOwners.filter((owner) => !existing.owners.includes(owner));
57
+ const ownersToRemove = existing.owners.filter((owner) => !newOwners.includes(owner));
58
+ const calls = [];
59
+ // Additions run first so the owner count already covers the new threshold:
60
+ // `setThreshold` reverts while `ownerCount < threshold`. Removals run last
61
+ // for the same reason, since `removeOwner` reverts once the count would drop
62
+ // to the threshold.
63
+ let currentOwners = [...existing.owners];
64
+ for (const owner of ownersToAdd) {
65
+ calls.push(addOwnableOwner(validator, owner));
66
+ // The validator pushes new owners onto the front of the linked list.
67
+ currentOwners.unshift(owner);
68
+ }
69
+ if (existing.threshold !== newThreshold) {
70
+ calls.push(changeOwnableThreshold(validator, newThreshold));
71
+ }
72
+ for (const owner of ownersToRemove) {
73
+ const index = currentOwners.indexOf(owner);
74
+ const prevOwner = index <= 0 ? SENTINEL_OWNER : currentOwners[index - 1];
75
+ calls.push(removeOwnableOwner(validator, prevOwner, owner));
76
+ currentOwners = currentOwners.filter((entry) => entry !== owner);
77
+ }
78
+ return calls;
79
+ }
80
+ /**
81
+ * Build the calls that rotate an account's passkey ownership.
82
+ *
83
+ * Send each returned call as its own UserOperation, in order: the social
84
+ * recovery validator authorizes a single `execute` per UserOperation, so
85
+ * batching them is rejected onchain.
86
+ *
87
+ * Ownership is only fully rotated once every call has landed. Until the
88
+ * removals execute the previous credentials stay valid alongside the new ones.
89
+ *
90
+ * @returns Calls to recover ownership, in the order they must be sent
91
+ */
92
+ async function recoverPasskeyOwnership(options) {
93
+ const configuredValidator = options.config.owners?.type === 'passkey'
94
+ ? (options.config.owners.module ?? WEBAUTHN_VALIDATOR_ADDRESS)
95
+ : undefined;
96
+ const requestedValidator = options.newOwners.module;
97
+ if (configuredValidator &&
98
+ requestedValidator &&
99
+ !isAddressEqual(configuredValidator, requestedValidator)) {
100
+ throw new Error('Recovery owner validator must match the configured owner validator');
101
+ }
102
+ const validator = configuredValidator ?? requestedValidator ?? WEBAUTHN_VALIDATOR_ADDRESS;
103
+ const existingThreshold = await readThresholdFor(options, options.accountAddress, validator);
104
+ const newCredentials = options.newOwners.accounts.map((account) => {
105
+ // Must go through the shared parser: uncompressed SEC1 keys are 65 bytes
106
+ // with an 0x04 prefix, and slicing from byte 0 shifts both coordinates.
107
+ const { x, y } = parseWebauthnPublicKey(account.publicKey);
108
+ return { pubKeyX: x, pubKeyY: y, requireUV: false };
109
+ });
110
+ const newThreshold = options.newOwners.threshold ?? 1;
111
+ const currentKeys = options.currentCredentials.map(credentialKey);
112
+ const newKeys = newCredentials.map(credentialKey);
113
+ const credentialsToAdd = newCredentials.filter((credential) => !currentKeys.includes(credentialKey(credential)));
114
+ const credentialsToRemove = options.currentCredentials.filter((credential) => !newKeys.includes(credentialKey(credential)));
115
+ const calls = [];
116
+ // Additions run first so the credential count already covers the new
117
+ // threshold: `setThreshold` reverts while `credentials < threshold`, and
118
+ // `removeCredential` reverts once the count would reach the threshold.
119
+ // Rotating the sole credential of a 1-of-1 account is impossible otherwise.
120
+ for (const credential of credentialsToAdd) {
121
+ calls.push(addWebauthnCredential(validator, credential.pubKeyX, credential.pubKeyY, credential.requireUV));
122
+ }
123
+ if (existingThreshold !== newThreshold) {
124
+ calls.push(changeWebauthnThreshold(validator, newThreshold));
125
+ }
126
+ for (const credential of credentialsToRemove) {
127
+ calls.push(removeWebauthnCredential(validator, credential.pubKeyX, credential.pubKeyY));
128
+ }
129
+ return calls;
130
+ }
131
+ function credentialKey(credential) {
132
+ return `${credential.pubKeyX}-${credential.pubKeyY}`;
133
+ }
134
+ export { enable, recoverEcdsaOwnership, recoverPasskeyOwnership };
@@ -1,5 +1,10 @@
1
1
  import type { CalldataInput, CallResolveContext, Session } from '../config/account.js';
2
2
  import type { ResolvedModule } from '../modules/types.js';
3
+ export declare function readOwnershipFor(context: CallResolveContext, account: `0x${string}`, validator: `0x${string}`): Promise<{
4
+ readonly owners: readonly `0x${string}`[];
5
+ threshold: number;
6
+ }>;
7
+ export declare function readThresholdFor(context: CallResolveContext, account: `0x${string}`, validator: `0x${string}`): Promise<number>;
3
8
  export declare function resolveValidatorInstallation(context: CallResolveContext, module: ResolvedModule): Promise<CalldataInput[]>;
4
9
  export declare function resolveModuleInstallation(context: CallResolveContext, module: ResolvedModule): Promise<CalldataInput[]>;
5
10
  export declare function resolveModuleUninstallation(context: CallResolveContext, module: ResolvedModule): Promise<CalldataInput[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../actions/runtime.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,OAAO,EACR,MAAM,mBAAmB,CAAA;AAQ1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAyEtD,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,aAAa,EAAE,CAAC,CA4C1B;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,aAAa,EAAE,CAAC,CAM1B;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,aAAa,EAAE,CAAC,CA2B1B;AAED,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAA;IACpC,QAAQ,CAAC,OAAO,EAAE,KAAK,MAAM,EAAE,CAAA;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAA;CACxB,GAAG,OAAO,CAAC,aAAa,CAAC,CAwBzB"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../actions/runtime.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,OAAO,EACR,MAAM,mBAAmB,CAAA;AAU1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAyEtD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,KAAK,MAAM,EAAE,EACtB,SAAS,EAAE,KAAK,MAAM,EAAE,GACvB,OAAO,CAAC;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,MAAM,EAAE,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAW3E;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,KAAK,MAAM,EAAE,EACtB,SAAS,EAAE,KAAK,MAAM,EAAE,GACvB,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,aAAa,EAAE,CAAC,CA4C1B;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,aAAa,EAAE,CAAC,CAM1B;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,aAAa,EAAE,CAAC,CA2B1B;AAED,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAA;IACpC,QAAQ,CAAC,OAAO,EAAE,KAAK,MAAM,EAAE,CAAA;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAA;CACxB,GAAG,OAAO,CAAC,aAAa,CAAC,CAwBzB"}
@@ -5,7 +5,7 @@ import { createAccountAdapter } from '../accounts/registry.js';
5
5
  import { materializeRpcReader } from '../clients/rpc/compatibility.js';
6
6
  import { resolveStandaloneAccountConfig } from '../config/resolve.js';
7
7
  import { assertAccountOwnersConfigured } from '../config/validate.js';
8
- import { encodeAccountModuleDeInitData, readInstalledModules, readValidatorInitialized, } from '../modules/read-core.js';
8
+ import { encodeAccountModuleDeInitData, readInstalledModules, readValidatorInitialized, readValidatorOwnership, readValidatorThreshold, } from '../modules/read-core.js';
9
9
  import { OWNABLE_VALIDATOR_ADDRESS } from '../modules/validators/ownable.js';
10
10
  import { SESSION_LOCK_TAG } from '../modules/validators/smart-sessions/authorization.js';
11
11
  import { encodeDisableSessionCall } from '../modules/validators/smart-sessions/calls.js';
@@ -59,6 +59,30 @@ function defaultValidatorConfigured(context, validator) {
59
59
  context.construction.setup.validators.some((module) => module.address.toLowerCase() === validator.toLowerCase() &&
60
60
  size(module.initData) > 0));
61
61
  }
62
+ export async function readOwnershipFor(context, account, validator) {
63
+ const reader = materializeRpcReader({
64
+ chain: context.chain,
65
+ provider: context.config.provider,
66
+ });
67
+ return readValidatorOwnership({
68
+ rpc: reader.rpc,
69
+ chain: reader.chain,
70
+ account,
71
+ validator,
72
+ });
73
+ }
74
+ export async function readThresholdFor(context, account, validator) {
75
+ const reader = materializeRpcReader({
76
+ chain: context.chain,
77
+ provider: context.config.provider,
78
+ });
79
+ return readValidatorThreshold({
80
+ rpc: reader.rpc,
81
+ chain: reader.chain,
82
+ account,
83
+ validator,
84
+ });
85
+ }
62
86
  export async function resolveValidatorInstallation(context, module) {
63
87
  const runtime = actionContext(context);
64
88
  if (runtime.construction.account.kind === 'nexus') {
@@ -0,0 +1,6 @@
1
+ import { type Address } from 'viem';
2
+ import type { CalldataInput } from '../config/account.js';
3
+ export declare function addWebauthnCredential(validator: Address, pubKeyX: bigint, pubKeyY: bigint, requireUserVerification: boolean): CalldataInput;
4
+ export declare function removeWebauthnCredential(validator: Address, pubKeyX: bigint, pubKeyY: bigint): CalldataInput;
5
+ export declare function changeWebauthnThreshold(validator: Address, newThreshold: number): CalldataInput;
6
+ //# sourceMappingURL=webauthn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webauthn.d.ts","sourceRoot":"","sources":["../../../actions/webauthn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,MAAM,CAAA;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEtD,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,OAAO,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,uBAAuB,EAAE,OAAO,GAC/B,aAAa,CAsBf;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,OAAO,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,aAAa,CAqBf;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,OAAO,EAClB,YAAY,EAAE,MAAM,GACnB,aAAa,CAoBf"}
@@ -0,0 +1,67 @@
1
+ import { encodeFunctionData } from 'viem';
2
+ export function addWebauthnCredential(validator, pubKeyX, pubKeyY, requireUserVerification) {
3
+ return {
4
+ to: validator,
5
+ value: 0n,
6
+ data: encodeFunctionData({
7
+ abi: [
8
+ {
9
+ inputs: [
10
+ { name: 'pubKeyX', type: 'uint256' },
11
+ { name: 'pubKeyY', type: 'uint256' },
12
+ { name: 'requireUserVerification', type: 'bool' },
13
+ ],
14
+ name: 'addCredential',
15
+ outputs: [],
16
+ stateMutability: 'nonpayable',
17
+ type: 'function',
18
+ },
19
+ ],
20
+ functionName: 'addCredential',
21
+ args: [pubKeyX, pubKeyY, requireUserVerification],
22
+ }),
23
+ };
24
+ }
25
+ export function removeWebauthnCredential(validator, pubKeyX, pubKeyY) {
26
+ return {
27
+ to: validator,
28
+ value: 0n,
29
+ data: encodeFunctionData({
30
+ abi: [
31
+ {
32
+ inputs: [
33
+ { name: 'pubKeyX', type: 'uint256' },
34
+ { name: 'pubKeyY', type: 'uint256' },
35
+ ],
36
+ name: 'removeCredential',
37
+ outputs: [],
38
+ stateMutability: 'nonpayable',
39
+ type: 'function',
40
+ },
41
+ ],
42
+ functionName: 'removeCredential',
43
+ args: [pubKeyX, pubKeyY],
44
+ }),
45
+ };
46
+ }
47
+ export function changeWebauthnThreshold(validator, newThreshold) {
48
+ return {
49
+ to: validator,
50
+ value: 0n,
51
+ data: encodeFunctionData({
52
+ abi: [
53
+ {
54
+ inputs: [
55
+ { internalType: 'uint256', name: '_threshold', type: 'uint256' },
56
+ ],
57
+ name: 'setThreshold',
58
+ outputs: [],
59
+ stateMutability: 'nonpayable',
60
+ type: 'function',
61
+ },
62
+ ],
63
+ functionName: 'setThreshold',
64
+ args: [BigInt(newThreshold)],
65
+ }),
66
+ };
67
+ }