@alchemy/smart-accounts 0.0.0-alpha.9 → 5.0.0-beta.2

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 (135) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +36 -0
  3. package/dist/esm/index.d.ts +2 -4
  4. package/dist/esm/index.js +2 -4
  5. package/dist/esm/index.js.map +1 -1
  6. package/dist/esm/light-account/accounts/account.d.ts +7 -3
  7. package/dist/esm/light-account/accounts/account.js +20 -10
  8. package/dist/esm/light-account/accounts/account.js.map +1 -1
  9. package/dist/esm/light-account/accounts/base.js +50 -23
  10. package/dist/esm/light-account/accounts/base.js.map +1 -1
  11. package/dist/esm/light-account/accounts/calldataCodec.js +3 -2
  12. package/dist/esm/light-account/accounts/calldataCodec.js.map +1 -1
  13. package/dist/esm/light-account/accounts/multi-owner-account.d.ts +6 -2
  14. package/dist/esm/light-account/accounts/multi-owner-account.js +14 -6
  15. package/dist/esm/light-account/accounts/multi-owner-account.js.map +1 -1
  16. package/dist/esm/light-account/lightAccountStaticImpl.d.ts +3 -1
  17. package/dist/esm/light-account/lightAccountStaticImpl.js +57 -7
  18. package/dist/esm/light-account/lightAccountStaticImpl.js.map +1 -1
  19. package/dist/esm/light-account/predictAddress.d.ts +40 -2
  20. package/dist/esm/light-account/predictAddress.js +83 -3
  21. package/dist/esm/light-account/predictAddress.js.map +1 -1
  22. package/dist/esm/light-account/registry.d.ts +3410 -0
  23. package/dist/esm/light-account/registry.js +33 -1
  24. package/dist/esm/light-account/registry.js.map +1 -1
  25. package/dist/esm/logger.d.ts +1 -1
  26. package/dist/esm/logger.js +1 -1
  27. package/dist/esm/logger.js.map +1 -1
  28. package/dist/esm/ma-v1/accounts/multi-owner-account.d.ts +6 -2
  29. package/dist/esm/ma-v1/accounts/multi-owner-account.js +18 -7
  30. package/dist/esm/ma-v1/accounts/multi-owner-account.js.map +1 -1
  31. package/dist/esm/ma-v1/predictAddress.d.ts +20 -1
  32. package/dist/esm/ma-v1/predictAddress.js +38 -2
  33. package/dist/esm/ma-v1/predictAddress.js.map +1 -1
  34. package/dist/esm/ma-v2/accounts/account.d.ts +8 -5
  35. package/dist/esm/ma-v2/accounts/account.js +23 -42
  36. package/dist/esm/ma-v2/accounts/account.js.map +1 -1
  37. package/dist/esm/ma-v2/accounts/base.d.ts +2 -2
  38. package/dist/esm/ma-v2/accounts/base.js +12 -59
  39. package/dist/esm/ma-v2/accounts/base.js.map +1 -1
  40. package/dist/esm/ma-v2/mav2StaticImpl.d.ts +1 -15
  41. package/dist/esm/ma-v2/mav2StaticImpl.js +0 -33
  42. package/dist/esm/ma-v2/mav2StaticImpl.js.map +1 -1
  43. package/dist/esm/ma-v2/modules/time-range-module/module.js +3 -2
  44. package/dist/esm/ma-v2/modules/time-range-module/module.js.map +1 -1
  45. package/dist/esm/ma-v2/predictAddress.d.ts +22 -6
  46. package/dist/esm/ma-v2/predictAddress.js +46 -12
  47. package/dist/esm/ma-v2/predictAddress.js.map +1 -1
  48. package/dist/esm/ma-v2/utils/account.d.ts +0 -3
  49. package/dist/esm/ma-v2/utils/account.js +0 -3
  50. package/dist/esm/ma-v2/utils/account.js.map +1 -1
  51. package/dist/esm/ma-v2/utils/signature.d.ts +1 -16
  52. package/dist/esm/ma-v2/utils/signature.js +1 -38
  53. package/dist/esm/ma-v2/utils/signature.js.map +1 -1
  54. package/dist/esm/utils.d.ts +24 -11
  55. package/dist/esm/utils.js +67 -21
  56. package/dist/esm/utils.js.map +1 -1
  57. package/dist/esm/version.d.ts +1 -1
  58. package/dist/esm/version.js +1 -1
  59. package/dist/esm/version.js.map +1 -1
  60. package/dist/types/index.d.ts +2 -4
  61. package/dist/types/index.d.ts.map +1 -1
  62. package/dist/types/light-account/accounts/account.d.ts +7 -3
  63. package/dist/types/light-account/accounts/account.d.ts.map +1 -1
  64. package/dist/types/light-account/accounts/base.d.ts.map +1 -1
  65. package/dist/types/light-account/accounts/calldataCodec.d.ts.map +1 -1
  66. package/dist/types/light-account/accounts/multi-owner-account.d.ts +6 -2
  67. package/dist/types/light-account/accounts/multi-owner-account.d.ts.map +1 -1
  68. package/dist/types/light-account/lightAccountStaticImpl.d.ts +3 -1
  69. package/dist/types/light-account/lightAccountStaticImpl.d.ts.map +1 -1
  70. package/dist/types/light-account/predictAddress.d.ts +40 -2
  71. package/dist/types/light-account/predictAddress.d.ts.map +1 -1
  72. package/dist/types/light-account/registry.d.ts +3410 -0
  73. package/dist/types/light-account/registry.d.ts.map +1 -1
  74. package/dist/types/logger.d.ts +1 -1
  75. package/dist/types/logger.d.ts.map +1 -1
  76. package/dist/types/ma-v1/accounts/multi-owner-account.d.ts +6 -2
  77. package/dist/types/ma-v1/accounts/multi-owner-account.d.ts.map +1 -1
  78. package/dist/types/ma-v1/predictAddress.d.ts +20 -1
  79. package/dist/types/ma-v1/predictAddress.d.ts.map +1 -1
  80. package/dist/types/ma-v2/accounts/account.d.ts +8 -5
  81. package/dist/types/ma-v2/accounts/account.d.ts.map +1 -1
  82. package/dist/types/ma-v2/accounts/base.d.ts +2 -2
  83. package/dist/types/ma-v2/accounts/base.d.ts.map +1 -1
  84. package/dist/types/ma-v2/mav2StaticImpl.d.ts +1 -15
  85. package/dist/types/ma-v2/mav2StaticImpl.d.ts.map +1 -1
  86. package/dist/types/ma-v2/modules/time-range-module/module.d.ts.map +1 -1
  87. package/dist/types/ma-v2/predictAddress.d.ts +22 -6
  88. package/dist/types/ma-v2/predictAddress.d.ts.map +1 -1
  89. package/dist/types/ma-v2/utils/account.d.ts +0 -3
  90. package/dist/types/ma-v2/utils/account.d.ts.map +1 -1
  91. package/dist/types/ma-v2/utils/signature.d.ts +1 -16
  92. package/dist/types/ma-v2/utils/signature.d.ts.map +1 -1
  93. package/dist/types/utils.d.ts +24 -11
  94. package/dist/types/utils.d.ts.map +1 -1
  95. package/dist/types/version.d.ts +1 -1
  96. package/dist/types/version.d.ts.map +1 -1
  97. package/package.json +9 -8
  98. package/src/index.ts +0 -6
  99. package/src/light-account/accounts/account.ts +30 -16
  100. package/src/light-account/accounts/base.ts +62 -23
  101. package/src/light-account/accounts/calldataCodec.ts +3 -2
  102. package/src/light-account/accounts/multi-owner-account.ts +22 -9
  103. package/src/light-account/lightAccountStaticImpl.ts +84 -11
  104. package/src/light-account/predictAddress.ts +124 -3
  105. package/src/light-account/registry.ts +44 -0
  106. package/src/logger.ts +2 -2
  107. package/src/ma-v1/accounts/multi-owner-account.ts +26 -11
  108. package/src/ma-v1/predictAddress.ts +60 -3
  109. package/src/ma-v2/accounts/account.ts +39 -52
  110. package/src/ma-v2/accounts/base.ts +11 -84
  111. package/src/ma-v2/mav2StaticImpl.ts +1 -52
  112. package/src/ma-v2/modules/time-range-module/module.ts +3 -2
  113. package/src/ma-v2/predictAddress.ts +68 -30
  114. package/src/ma-v2/utils/account.ts +0 -3
  115. package/src/ma-v2/utils/signature.ts +2 -57
  116. package/src/utils.ts +111 -27
  117. package/src/version.ts +1 -1
  118. package/dist/esm/ma-v2/abis/webAuthnFactoryAbi.d.ts +0 -330
  119. package/dist/esm/ma-v2/abis/webAuthnFactoryAbi.js +0 -260
  120. package/dist/esm/ma-v2/abis/webAuthnFactoryAbi.js.map +0 -1
  121. package/dist/esm/ma-v2/modules/webauthn-validation/abis/webauthnValidationAbi.d.ts +0 -287
  122. package/dist/esm/ma-v2/modules/webauthn-validation/abis/webauthnValidationAbi.js +0 -374
  123. package/dist/esm/ma-v2/modules/webauthn-validation/abis/webauthnValidationAbi.js.map +0 -1
  124. package/dist/esm/ma-v2/modules/webauthn-validation/module.d.ts +0 -11
  125. package/dist/esm/ma-v2/modules/webauthn-validation/module.js +0 -16
  126. package/dist/esm/ma-v2/modules/webauthn-validation/module.js.map +0 -1
  127. package/dist/types/ma-v2/abis/webAuthnFactoryAbi.d.ts +0 -331
  128. package/dist/types/ma-v2/abis/webAuthnFactoryAbi.d.ts.map +0 -1
  129. package/dist/types/ma-v2/modules/webauthn-validation/abis/webauthnValidationAbi.d.ts +0 -288
  130. package/dist/types/ma-v2/modules/webauthn-validation/abis/webauthnValidationAbi.d.ts.map +0 -1
  131. package/dist/types/ma-v2/modules/webauthn-validation/module.d.ts +0 -12
  132. package/dist/types/ma-v2/modules/webauthn-validation/module.d.ts.map +0 -1
  133. package/src/ma-v2/abis/webAuthnFactoryAbi.ts +0 -259
  134. package/src/ma-v2/modules/webauthn-validation/abis/webauthnValidationAbi.ts +0 -373
  135. package/src/ma-v2/modules/webauthn-validation/module.ts +0 -28
@@ -1,5 +1,4 @@
1
1
  import {
2
- concat,
3
2
  concatHex,
4
3
  encodeFunctionData,
5
4
  fromHex,
@@ -18,6 +17,7 @@ import {
18
17
  } from "viem";
19
18
  import {
20
19
  getUserOperationHash,
20
+ getUserOperationTypedData,
21
21
  toSmartAccount,
22
22
  type SmartAccountImplementation,
23
23
  } from "viem/account-abstraction";
@@ -28,7 +28,7 @@ import type {
28
28
  LightAccountVersion,
29
29
  } from "../registry.js";
30
30
  import { EIP1967_PROXY_IMPL_STORAGE_SLOT } from "../utils.js";
31
- import { AccountVersionRegistry } from "../registry.js";
31
+ import { AccountVersionRegistry, isLightAccountVersion2 } from "../registry.js";
32
32
  import {
33
33
  encodeCallsLA as encodeCalls,
34
34
  decodeCallsLA as decodeCalls,
@@ -203,6 +203,8 @@ export async function toLightAccountBase<
203
203
  data: get1271Wrapper(messageHash, "1"),
204
204
  };
205
205
  case "v2.0.0":
206
+ case "v2.1.0":
207
+ case "v2.2.0":
206
208
  return {
207
209
  type: "eth_signTypedData_v4",
208
210
  data: get1271Wrapper(messageHash, "2"),
@@ -215,8 +217,10 @@ export async function toLightAccountBase<
215
217
  };
216
218
 
217
219
  const formatSignature = async (signature: Hex): Promise<Hex> => {
218
- return version === "v2.0.0"
219
- ? concat([SignaturePrefix.EOA, signature])
220
+ return isLightAccountVersion2(
221
+ version as LightAccountVersion<"LightAccount">,
222
+ )
223
+ ? concatHex([SignaturePrefix.EOA, signature])
220
224
  : signature;
221
225
  };
222
226
 
@@ -251,7 +255,9 @@ export async function toLightAccountBase<
251
255
  case "v1.1.0":
252
256
  return signature;
253
257
  case "v2.0.0":
254
- return concat([SignaturePrefix.EOA, signature]);
258
+ case "v2.1.0":
259
+ case "v2.2.0":
260
+ return concatHex([SignaturePrefix.EOA, signature]);
255
261
  default:
256
262
  throw new BaseError(`Unknown version ${type} of ${String(version)}`);
257
263
  }
@@ -307,26 +313,59 @@ export async function toLightAccountBase<
307
313
 
308
314
  async signUserOperation(parameters) {
309
315
  const { chainId = client.chain.id, ...userOperation } = parameters;
310
- const userOpHash = getUserOperationHash({
311
- chainId,
312
- entryPointAddress: entryPoint.address,
313
- entryPointVersion: entryPoint.version,
314
- userOperation: {
315
- ...userOperation,
316
- sender: accountAddress,
317
- },
318
- });
319
-
320
- const signMessageAction = getAction(client, signMessage, "signMessage");
316
+ let signature: Hex;
321
317
 
322
- const signature = await signMessageAction({
323
- account: owner,
324
- message: { raw: userOpHash },
325
- });
318
+ switch (version) {
319
+ case "v1.0.1":
320
+ case "v1.0.2":
321
+ case "v1.1.0":
322
+ case "v2.0.0":
323
+ const userOpHash = getUserOperationHash({
324
+ chainId,
325
+ entryPointAddress: entryPoint.address,
326
+ entryPointVersion: entryPoint.version,
327
+ userOperation: {
328
+ ...userOperation,
329
+ sender: accountAddress,
330
+ },
331
+ });
332
+
333
+ const signMessageAction = getAction(
334
+ client,
335
+ signMessage,
336
+ "signMessage",
337
+ );
338
+
339
+ signature = await signMessageAction({
340
+ account: owner,
341
+ message: { raw: userOpHash },
342
+ });
343
+ break;
344
+ case "v2.1.0":
345
+ case "v2.2.0":
346
+ const signTypedDataAction = getAction(
347
+ client,
348
+ signTypedData,
349
+ "signTypedData",
350
+ );
351
+
352
+ signature = await signTypedDataAction({
353
+ account: owner,
354
+ ...getUserOperationTypedData({
355
+ chainId,
356
+ entryPointAddress: entryPoint.address,
357
+ userOperation: {
358
+ ...userOperation,
359
+ sender: accountAddress,
360
+ },
361
+ }),
362
+ });
363
+ break;
364
+ default:
365
+ throw new BaseError(`Unknown version ${type} of ${String(version)}`);
366
+ }
326
367
 
327
- return version === "v2.0.0"
328
- ? concatHex([SignaturePrefix.EOA, signature])
329
- : signature;
368
+ return formatSignature(signature);
330
369
  },
331
370
 
332
371
  extend: {
@@ -6,6 +6,7 @@ import {
6
6
  type Hex,
7
7
  } from "viem";
8
8
  import { LightAccountAbi_v1 } from "../abis/LightAccountAbi_v1.js";
9
+ import { BaseError } from "@alchemy/common";
9
10
 
10
11
  // Conveniently, all variants of LA up to v2.0.0 use the same function signatures for `execute` and `executeBatch`.
11
12
 
@@ -59,7 +60,7 @@ export function decodeCallsLA(data: Hex, accountAddress: Address): Call[] {
59
60
  const [targets, values, datas] = decoded.args;
60
61
 
61
62
  if (targets.length !== values.length || targets.length !== datas.length) {
62
- throw new Error("Invalid arguments for executeBatch");
63
+ throw new BaseError("Invalid arguments for executeBatch");
63
64
  }
64
65
 
65
66
  return targets.map((to, index) => ({
@@ -73,7 +74,7 @@ export function decodeCallsLA(data: Hex, accountAddress: Address): Call[] {
73
74
  const [targets, datas] = decoded.args;
74
75
 
75
76
  if (targets.length !== datas.length) {
76
- throw new Error("Invalid arguments for executeBatch");
77
+ throw new BaseError("Invalid arguments for executeBatch");
77
78
  }
78
79
 
79
80
  return targets.map((to, index) => ({
@@ -13,7 +13,10 @@ import {
13
13
  import { readContract } from "viem/actions";
14
14
  import { MultiOwnerLightAccountAbi } from "../abis/MultiOwnerLightAccountAbi.js";
15
15
  import { MultiOwnerLightAccountFactoryAbi } from "../abis/MultiOwnerLightAccountFactoryAbi.js";
16
- import { predictMultiOwnerLightAccountAddress } from "../predictAddress.js";
16
+ import {
17
+ getMultiOwnerLightAccountAddressFromFactoryData,
18
+ predictMultiOwnerLightAccountAddress,
19
+ } from "../predictAddress.js";
17
20
  import { toLightAccountBase, type LightAccountBase } from "./base.js";
18
21
  import { BaseError, lowerAddress } from "@alchemy/common";
19
22
  import { getAction } from "viem/utils";
@@ -33,11 +36,12 @@ export type MultiOwnerLightAccount = LightAccountBase<
33
36
  export type ToMultiOwnerLightAccountParams = {
34
37
  client: Client<Transport, Chain, JsonRpcAccount | LocalAccount | undefined>;
35
38
  owners: [OneOf<JsonRpcAccount | LocalAccount>, ...{ address: Address }[]];
36
- salt?: bigint;
37
39
  accountAddress?: Address;
38
40
  factory?: Address;
39
- factoryData?: Hex;
40
- };
41
+ } & (
42
+ | { salt?: bigint; factoryData?: never }
43
+ | { salt?: never; factoryData?: Hex }
44
+ );
41
45
 
42
46
  /**
43
47
  * Creates a multi-owner light account.
@@ -68,11 +72,20 @@ export async function toMultiOwnerLightAccount({
68
72
 
69
73
  const accountAddress =
70
74
  accountAddress_ ??
71
- predictMultiOwnerLightAccountAddress({
72
- factoryAddress: factory,
73
- salt,
74
- ownerAddresses: sortedOwners,
75
- });
75
+ (factoryData_
76
+ ? await getMultiOwnerLightAccountAddressFromFactoryData({
77
+ client,
78
+ factoryAddress: factory,
79
+ factoryData: factoryData_,
80
+ entryPoint:
81
+ AccountVersionRegistry["MultiOwnerLightAccount"]["v2.0.0"]
82
+ .entryPoint,
83
+ })
84
+ : predictMultiOwnerLightAccountAddress({
85
+ factoryAddress: factory,
86
+ salt,
87
+ ownerAddresses: sortedOwners,
88
+ }));
76
89
 
77
90
  const getFactoryArgs = async () => {
78
91
  const factoryData =
@@ -4,6 +4,10 @@ import {
4
4
  entryPoint07Abi,
5
5
  entryPoint06Address,
6
6
  entryPoint07Address,
7
+ entryPoint08Abi,
8
+ entryPoint08Address,
9
+ entryPoint09Abi,
10
+ entryPoint09Address,
7
11
  } from "viem/account-abstraction";
8
12
  import { LightAccountAbi_v1 } from "./abis/LightAccountAbi_v1.js";
9
13
  import { LightAccountFactoryAbi_v1 } from "./abis/LightAccountFactoryAbi_v1.js";
@@ -96,15 +100,6 @@ export const lightAccountStaticImplV1_1_0: LightAccountV1StaticImpl = {
96
100
  },
97
101
  };
98
102
 
99
- // Shared type and fields for all light account v2 implementations
100
- const lightAccountV2Base = {
101
- entryPoint: {
102
- abi: entryPoint07Abi,
103
- address: entryPoint07Address,
104
- version: "0.7",
105
- },
106
- } satisfies Partial<StaticSmartAccountImplementation<false, "0.7">>;
107
-
108
103
  export const lightAccountStaticImplV2_0_0: StaticSmartAccountImplementation<
109
104
  false,
110
105
  "0.7",
@@ -113,7 +108,11 @@ export const lightAccountStaticImplV2_0_0: StaticSmartAccountImplementation<
113
108
  typeof LightAccountAbi_v2,
114
109
  typeof LightAccountFactoryAbi_v2
115
110
  > = {
116
- ...lightAccountV2Base,
111
+ entryPoint: {
112
+ abi: entryPoint07Abi,
113
+ address: entryPoint07Address,
114
+ version: "0.7",
115
+ },
117
116
  accountAbi: LightAccountAbi_v2,
118
117
  accountImplementation: lowerAddress(
119
118
  "0x8E8e658E22B12ada97B402fF0b044D6A325013C7",
@@ -149,7 +148,11 @@ export const multiOwnerLightAccountStaticImplV2_0_0: StaticSmartAccountImplement
149
148
  typeof MultiOwnerLightAccountAbi,
150
149
  typeof MultiOwnerLightAccountFactoryAbi
151
150
  > = {
152
- ...lightAccountV2Base,
151
+ entryPoint: {
152
+ abi: entryPoint07Abi,
153
+ address: entryPoint07Address,
154
+ version: "0.7",
155
+ },
153
156
  accountAbi: MultiOwnerLightAccountAbi,
154
157
  accountImplementation: lowerAddress(
155
158
  "0xd2c27F9eE8E4355f71915ffD5568cB3433b6823D",
@@ -170,3 +173,73 @@ export const multiOwnerLightAccountStaticImplV2_0_0: StaticSmartAccountImplement
170
173
  });
171
174
  },
172
175
  };
176
+
177
+ export const lightAccountStaticImplV2_1_0: StaticSmartAccountImplementation<
178
+ false,
179
+ "0.8",
180
+ LightAccountFactoryArgs,
181
+ typeof entryPoint08Abi,
182
+ typeof LightAccountAbi_v2,
183
+ typeof LightAccountFactoryAbi_v2
184
+ > = {
185
+ entryPoint: {
186
+ abi: entryPoint08Abi,
187
+ address: entryPoint08Address,
188
+ version: "0.8",
189
+ },
190
+ accountAbi: LightAccountAbi_v2,
191
+ accountImplementation: lowerAddress(
192
+ "0x2c53D0bD33A60db8881c7b049Df6fd762A1f059C",
193
+ ),
194
+ factoryAbi: LightAccountFactoryAbi_v2,
195
+ factoryAddress: lowerAddress("0x000000000000B1c70Df4DC2CcF86372714e14154"),
196
+ getFactoryData: (factoryArgs) => {
197
+ return encodeFunctionData({
198
+ abi: LightAccountFactoryAbi_v2,
199
+ functionName: "createAccount",
200
+ args: [factoryArgs.owner, factoryArgs.salt],
201
+ });
202
+ },
203
+ predictAccountAddress: (factoryArgs) => {
204
+ return predictLightAccountAddress({
205
+ salt: factoryArgs.salt,
206
+ ownerAddress: factoryArgs.owner,
207
+ version: "v2.1.0",
208
+ });
209
+ },
210
+ };
211
+
212
+ export const lightAccountStaticImplV2_2_0: StaticSmartAccountImplementation<
213
+ false,
214
+ "0.9",
215
+ LightAccountFactoryArgs,
216
+ typeof entryPoint09Abi,
217
+ typeof LightAccountAbi_v2,
218
+ typeof LightAccountFactoryAbi_v2
219
+ > = {
220
+ entryPoint: {
221
+ abi: entryPoint09Abi,
222
+ address: entryPoint09Address,
223
+ version: "0.9",
224
+ },
225
+ accountAbi: LightAccountAbi_v2,
226
+ accountImplementation: lowerAddress(
227
+ "0x05FF1bF6Ac15d4990Ea77Ae60394629bcB16640d",
228
+ ),
229
+ factoryAbi: LightAccountFactoryAbi_v2,
230
+ factoryAddress: lowerAddress("0x0000000000003805C662f84E42E446C96a446e82"),
231
+ getFactoryData: (factoryArgs) => {
232
+ return encodeFunctionData({
233
+ abi: LightAccountFactoryAbi_v2,
234
+ functionName: "createAccount",
235
+ args: [factoryArgs.owner, factoryArgs.salt],
236
+ });
237
+ },
238
+ predictAccountAddress: (factoryArgs) => {
239
+ return predictLightAccountAddress({
240
+ salt: factoryArgs.salt,
241
+ ownerAddress: factoryArgs.owner,
242
+ version: "v2.2.0",
243
+ });
244
+ },
245
+ };
@@ -1,18 +1,29 @@
1
1
  import {
2
2
  concatHex,
3
+ decodeFunctionData,
3
4
  encodeAbiParameters,
4
5
  encodeDeployData,
5
6
  encodeFunctionData,
6
7
  getContractAddress,
8
+ isAddressEqual,
7
9
  keccak256,
8
10
  toHex,
9
11
  type Address,
12
+ type Client,
10
13
  type Hex,
11
14
  } from "viem";
15
+ import type { EntryPointVersion } from "viem/account-abstraction";
12
16
  import { LightAccountAbi_v1 } from "./abis/LightAccountAbi_v1.js";
17
+ import { LightAccountFactoryAbi_v1 } from "./abis/LightAccountFactoryAbi_v1.js";
18
+ import { LightAccountFactoryAbi_v2 } from "./abis/LightAccountFactoryAbi_v2.js";
19
+ import { MultiOwnerLightAccountFactoryAbi } from "./abis/MultiOwnerLightAccountFactoryAbi.js";
13
20
  import { OZ_ERC1967Proxy_ConstructorAbi } from "./abis/OZ_ERC1967Proxy.js";
14
- import { AccountVersionRegistry } from "./registry.js";
21
+ import {
22
+ AccountVersionRegistry,
23
+ type LightAccountVersion,
24
+ } from "./registry.js";
15
25
  import { BaseError, lowerAddress } from "@alchemy/common";
26
+ import { getSenderFromFactoryData } from "../utils.js";
16
27
 
17
28
  export type PredictLightAccountAddressParams = {
18
29
  version: keyof typeof AccountVersionRegistry.LightAccount;
@@ -73,7 +84,9 @@ export function predictLightAccountAddress({
73
84
  });
74
85
 
75
86
  case "v2.0.0":
76
- // Logic ported from LA factory v2.0.0
87
+ case "v2.1.0":
88
+ case "v2.2.0":
89
+ // Logic ported from LA factory v2
77
90
  const combinedSalt = keccak256(
78
91
  encodeAbiParameters(
79
92
  [{ type: "address" }, { type: "uint256" }],
@@ -89,7 +102,6 @@ export function predictLightAccountAddress({
89
102
  salt: combinedSalt,
90
103
  bytecode: initCode,
91
104
  });
92
-
93
105
  default:
94
106
  assertNeverLightAccountVersion(version);
95
107
  }
@@ -172,3 +184,112 @@ function getLAv2ProxyBytecode(implementationAddress: Address): Hex {
172
184
  function assertNeverLightAccountVersion(version: never): never {
173
185
  throw new BaseError(`Unknown light account version: ${version}`);
174
186
  }
187
+
188
+ export type GetLightAccountAddressFromFactoryDataParams = {
189
+ client: Client;
190
+ factoryAddress: Address;
191
+ factoryData: Hex;
192
+ entryPoint: {
193
+ version: EntryPointVersion;
194
+ address: Address;
195
+ };
196
+ version: LightAccountVersion<"LightAccount">;
197
+ };
198
+
199
+ /**
200
+ * Gets the light account address from factory data.
201
+ * If the factory is a known default, decodes the args and predicts without RPC.
202
+ * Otherwise falls back to calling the entry point's getSenderAddress.
203
+ *
204
+ * @param {GetLightAccountAddressFromFactoryDataParams} params - The parameters
205
+ * @returns {Promise<Address>} The account address
206
+ */
207
+ export async function getLightAccountAddressFromFactoryData({
208
+ client,
209
+ factoryAddress,
210
+ factoryData,
211
+ entryPoint,
212
+ version,
213
+ }: GetLightAccountAddressFromFactoryDataParams): Promise<Address> {
214
+ const defaultFactory =
215
+ AccountVersionRegistry["LightAccount"][version].factoryAddress;
216
+ if (isAddressEqual(factoryAddress, defaultFactory)) {
217
+ const factoryAbi =
218
+ version === "v2.0.0"
219
+ ? LightAccountFactoryAbi_v2
220
+ : LightAccountFactoryAbi_v1;
221
+ try {
222
+ const decoded = decodeFunctionData({
223
+ abi: factoryAbi,
224
+ data: factoryData,
225
+ });
226
+ if (decoded.functionName === "createAccount") {
227
+ const [decodedOwner, decodedSalt] = decoded.args;
228
+ return predictLightAccountAddress({
229
+ factoryAddress,
230
+ salt: decodedSalt,
231
+ ownerAddress: decodedOwner,
232
+ version,
233
+ });
234
+ }
235
+ } catch {
236
+ // Decode failed, fall through to RPC
237
+ }
238
+ }
239
+ return getSenderFromFactoryData(client, {
240
+ factory: factoryAddress,
241
+ factoryData,
242
+ entryPoint,
243
+ });
244
+ }
245
+
246
+ export type GetMultiOwnerLightAccountAddressFromFactoryDataParams = {
247
+ client: Client;
248
+ factoryAddress: Address;
249
+ factoryData: Hex;
250
+ entryPoint: {
251
+ version: EntryPointVersion;
252
+ address: Address;
253
+ };
254
+ };
255
+
256
+ /**
257
+ * Gets the multi-owner light account address from factory data.
258
+ * If the factory is a known default, decodes the args and predicts without RPC.
259
+ * Otherwise falls back to calling the entry point's getSenderAddress.
260
+ *
261
+ * @param {GetMultiOwnerLightAccountAddressFromFactoryDataParams} params - The parameters
262
+ * @returns {Promise<Address>} The account address
263
+ */
264
+ export async function getMultiOwnerLightAccountAddressFromFactoryData({
265
+ client,
266
+ factoryAddress,
267
+ factoryData,
268
+ entryPoint,
269
+ }: GetMultiOwnerLightAccountAddressFromFactoryDataParams): Promise<Address> {
270
+ const defaultFactory =
271
+ AccountVersionRegistry["MultiOwnerLightAccount"]["v2.0.0"].factoryAddress;
272
+ if (isAddressEqual(factoryAddress, defaultFactory)) {
273
+ try {
274
+ const decoded = decodeFunctionData({
275
+ abi: MultiOwnerLightAccountFactoryAbi,
276
+ data: factoryData,
277
+ });
278
+ if (decoded.functionName === "createAccount") {
279
+ const [decodedOwners, decodedSalt] = decoded.args;
280
+ return predictMultiOwnerLightAccountAddress({
281
+ factoryAddress,
282
+ salt: decodedSalt,
283
+ ownerAddresses: [...decodedOwners],
284
+ });
285
+ }
286
+ } catch {
287
+ // Decode failed, fall through to RPC
288
+ }
289
+ }
290
+ return getSenderFromFactoryData(client, {
291
+ factory: factoryAddress,
292
+ factoryData,
293
+ entryPoint,
294
+ });
295
+ }
@@ -5,6 +5,8 @@ import {
5
5
  lightAccountStaticImplV1_0_2,
6
6
  lightAccountStaticImplV1_1_0,
7
7
  lightAccountStaticImplV2_0_0,
8
+ lightAccountStaticImplV2_1_0,
9
+ lightAccountStaticImplV2_2_0,
8
10
  multiOwnerLightAccountStaticImplV2_0_0,
9
11
  } from "./lightAccountStaticImpl.js";
10
12
  import type { StaticSmartAccountImplementation } from "../types.js";
@@ -20,6 +22,8 @@ export const AccountVersionRegistry = {
20
22
  "v1.0.2": lightAccountStaticImplV1_0_2,
21
23
  "v1.1.0": lightAccountStaticImplV1_1_0,
22
24
  "v2.0.0": lightAccountStaticImplV2_0_0,
25
+ "v2.1.0": lightAccountStaticImplV2_1_0,
26
+ "v2.2.0": lightAccountStaticImplV2_2_0,
23
27
  },
24
28
  MultiOwnerLightAccount: {
25
29
  "v2.0.0": multiOwnerLightAccountStaticImplV2_0_0,
@@ -34,6 +38,46 @@ export type LightAccountType = Extract<
34
38
  export type LightAccountVersion<TAccountType extends LightAccountType> =
35
39
  keyof (typeof AccountVersionRegistry)[TAccountType];
36
40
 
41
+ /**
42
+ * Light Account v1 versions
43
+ */
44
+ export const LightAccountV1Versions = [
45
+ "v1.0.1",
46
+ "v1.0.2",
47
+ "v1.1.0",
48
+ ] as const satisfies LightAccountVersion<"LightAccount">[];
49
+
50
+ /**
51
+ * Light Account v2 versions
52
+ */
53
+ export const LightAccountV2Versions = [
54
+ "v2.0.0",
55
+ "v2.1.0",
56
+ "v2.2.0",
57
+ ] as const satisfies LightAccountVersion<"LightAccount">[];
58
+
59
+ /**
60
+ * Type guard to check if a version is a Light Account v1 version
61
+ *
62
+ * @param {LightAccountVersion<"LightAccount">} version - The version to check.
63
+ * @returns {boolean} True if the version is a v1 version.
64
+ */
65
+ export const isLightAccountVersion1 = (
66
+ version: LightAccountVersion<"LightAccount">,
67
+ ): version is (typeof LightAccountV1Versions)[number] =>
68
+ (LightAccountV1Versions as readonly string[]).includes(version);
69
+
70
+ /**
71
+ * Type guard to check if a version is a Light Account v2 version
72
+ *
73
+ * @param {LightAccountVersion<"LightAccount">} version - The version to check.
74
+ * @returns {boolean} True if the version is a v2 version.
75
+ */
76
+ export const isLightAccountVersion2 = (
77
+ version: LightAccountVersion<"LightAccount">,
78
+ ): version is (typeof LightAccountV2Versions)[number] =>
79
+ (LightAccountV2Versions as readonly string[]).includes(version);
80
+
37
81
  export type GetLightAccountType<TAccount extends LightAccountBase> =
38
82
  TAccount["smartAccountType"] extends LightAccountType
39
83
  ? TAccount["smartAccountType"]
package/src/logger.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { createLogger } from "@alchemy/common";
2
- import type { DiagnosticsLogger } from "@alchemy/common";
1
+ import { createLogger } from "@alchemy/common/internal";
2
+ import type { DiagnosticsLogger } from "@alchemy/common/internal";
3
3
  import { VERSION } from "./version.js";
4
4
 
5
5
  export const LOGGER: DiagnosticsLogger = createLogger({
@@ -1,26 +1,30 @@
1
1
  import {
2
+ encodeFunctionData,
2
3
  hexToBigInt,
3
4
  type Address,
4
5
  type Chain,
5
6
  type Client,
7
+ type Hash,
6
8
  type Hex,
7
9
  type JsonRpcAccount,
8
10
  type LocalAccount,
9
11
  type OneOf,
10
12
  type Transport,
11
- encodeFunctionData,
12
- type Hash,
13
13
  type TypedDataDefinition,
14
14
  } from "viem";
15
15
  import { toModularAccountV1Base, type ModularAccountV1Base } from "./base.js";
16
16
  import { lowerAddress, BaseError } from "@alchemy/common";
17
17
  import { DefaultMaV1Address, DefaultMaV1PluginAddress } from "../account.js";
18
18
  import { MultiOwnerModularAccountFactoryAbi } from "../abis/MultiOwnerModularAccountFactory.js";
19
- import { predictMultiOwnerModularAccountV1Address } from "../predictAddress.js";
19
+ import {
20
+ getMultiOwnerModularAccountV1AddressFromFactoryData,
21
+ predictMultiOwnerModularAccountV1Address,
22
+ } from "../predictAddress.js";
20
23
  import { MultiOwnerPluginExecutionFunctionAbi } from "../abis/MultiOwnerPluginExecutionFunction.js";
21
24
  import { readContract } from "viem/actions";
22
25
  import { getAction } from "viem/utils";
23
26
  import { MultiOwnerPluginAbi } from "../abis/MultiOwnerPlugin.js";
27
+ import { entryPoint06Address } from "viem/account-abstraction";
24
28
 
25
29
  export type MultiOwnerModularAccountV1 = ModularAccountV1Base & {
26
30
  encodeUpdateOwners: (
@@ -33,11 +37,12 @@ export type MultiOwnerModularAccountV1 = ModularAccountV1Base & {
33
37
  export type ToMultiOwnerModularAccountV1Params = {
34
38
  client: Client<Transport, Chain, JsonRpcAccount | LocalAccount | undefined>;
35
39
  owners: [OneOf<JsonRpcAccount | LocalAccount>, ...{ address: Address }[]];
36
- salt?: bigint;
37
40
  accountAddress?: Address;
38
41
  factory?: Address;
39
- factoryData?: Hex;
40
- };
42
+ } & (
43
+ | { salt?: bigint; factoryData?: never }
44
+ | { salt?: never; factoryData?: Hex }
45
+ );
41
46
 
42
47
  /**
43
48
  * Creates a multi-owner MAv1 account.
@@ -67,11 +72,21 @@ export async function toMultiOwnerModularAccountV1({
67
72
 
68
73
  const accountAddress =
69
74
  accountAddress_ ??
70
- predictMultiOwnerModularAccountV1Address({
71
- factoryAddress: factory,
72
- salt,
73
- ownerAddresses: sortedOwners,
74
- });
75
+ (factoryData_
76
+ ? await getMultiOwnerModularAccountV1AddressFromFactoryData({
77
+ client,
78
+ factoryAddress: factory,
79
+ factoryData: factoryData_,
80
+ entryPoint: {
81
+ version: "0.6",
82
+ address: entryPoint06Address,
83
+ },
84
+ })
85
+ : predictMultiOwnerModularAccountV1Address({
86
+ factoryAddress: factory,
87
+ salt,
88
+ ownerAddresses: sortedOwners,
89
+ }));
75
90
 
76
91
  const getFactoryArgs = async () => {
77
92
  const factoryData =