@account-kit/smart-contracts 4.33.0 → 4.34.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 (26) hide show
  1. package/dist/esm/src/light-account/accounts/account.js +1 -1
  2. package/dist/esm/src/light-account/accounts/account.js.map +1 -1
  3. package/dist/esm/src/light-account/accounts/multiOwner.js +18 -17
  4. package/dist/esm/src/light-account/accounts/multiOwner.js.map +1 -1
  5. package/dist/esm/src/light-account/accounts/predictAddress.d.ts +8 -2
  6. package/dist/esm/src/light-account/accounts/predictAddress.js +31 -5
  7. package/dist/esm/src/light-account/accounts/predictAddress.js.map +1 -1
  8. package/dist/esm/src/ma-v2/account/modularAccountV2.d.ts +1 -0
  9. package/dist/esm/src/ma-v2/account/modularAccountV2.js +14 -14
  10. package/dist/esm/src/ma-v2/account/modularAccountV2.js.map +1 -1
  11. package/dist/esm/src/ma-v2/account/predictAddress.d.ts +21 -0
  12. package/dist/esm/src/ma-v2/account/predictAddress.js +46 -0
  13. package/dist/esm/src/ma-v2/account/predictAddress.js.map +1 -0
  14. package/dist/types/src/light-account/accounts/multiOwner.d.ts.map +1 -1
  15. package/dist/types/src/light-account/accounts/predictAddress.d.ts +8 -2
  16. package/dist/types/src/light-account/accounts/predictAddress.d.ts.map +1 -1
  17. package/dist/types/src/ma-v2/account/modularAccountV2.d.ts +1 -0
  18. package/dist/types/src/ma-v2/account/modularAccountV2.d.ts.map +1 -1
  19. package/dist/types/src/ma-v2/account/predictAddress.d.ts +22 -0
  20. package/dist/types/src/ma-v2/account/predictAddress.d.ts.map +1 -0
  21. package/package.json +5 -5
  22. package/src/light-account/accounts/account.ts +1 -1
  23. package/src/light-account/accounts/multiOwner.ts +20 -19
  24. package/src/light-account/accounts/predictAddress.ts +56 -9
  25. package/src/ma-v2/account/modularAccountV2.ts +19 -15
  26. package/src/ma-v2/account/predictAddress.ts +123 -0
@@ -59,7 +59,7 @@ export async function createLightAccount({ transport, chain, signer, initCode, v
59
59
  predictLightAccountAddress({
60
60
  factoryAddress,
61
61
  salt,
62
- signerAddress,
62
+ ownerAddress: signerAddress,
63
63
  version,
64
64
  });
65
65
  const account = await createLightAccountBase({
@@ -1 +1 @@
1
- {"version":3,"file":"account.js","sourceRoot":"","sources":["../../../../../src/light-account/accounts/account.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createBundlerClient,\n getEntryPoint,\n type Address,\n type EntryPointDef,\n type SmartAccountSigner,\n} from \"@aa-sdk/core\";\nimport {\n concatHex,\n encodeFunctionData,\n type Chain,\n type Hex,\n type Transport,\n} from \"viem\";\nimport { LightAccountAbi_v1 } from \"../abis/LightAccountAbi_v1.js\";\nimport { LightAccountAbi_v2 } from \"../abis/LightAccountAbi_v2.js\";\nimport { LightAccountFactoryAbi_v1 } from \"../abis/LightAccountFactoryAbi_v1.js\";\nimport { LightAccountFactoryAbi_v2 } from \"../abis/LightAccountFactoryAbi_v2.js\";\nimport type {\n LightAccountEntryPointVersion,\n LightAccountVersion,\n} from \"../types.js\";\nimport {\n AccountVersionRegistry,\n LightAccountUnsupported1271Factories,\n defaultLightAccountVersion,\n getDefaultLightAccountFactoryAddress,\n} from \"../utils.js\";\nimport {\n createLightAccountBase,\n type CreateLightAccountBaseParams,\n type LightAccountBase,\n} from \"./base.js\";\nimport { predictLightAccountAddress } from \"./predictAddress.js\";\n\nexport type LightAccount<\n TSigner extends SmartAccountSigner = SmartAccountSigner,\n TLightAccountVersion extends LightAccountVersion<\"LightAccount\"> = LightAccountVersion<\"LightAccount\">\n> = LightAccountBase<TSigner, \"LightAccount\", TLightAccountVersion> & {\n encodeTransferOwnership: (newOwner: Address) => Hex;\n getOwnerAddress: () => Promise<Address>;\n};\n\n// [!region CreateLightAccountParams]\nexport type CreateLightAccountParams<\n TTransport extends Transport = Transport,\n TSigner extends SmartAccountSigner = SmartAccountSigner,\n TLightAccountVersion extends LightAccountVersion<\"LightAccount\"> = LightAccountVersion<\"LightAccount\">\n> = Omit<\n CreateLightAccountBaseParams<\n \"LightAccount\",\n TLightAccountVersion,\n TTransport,\n TSigner\n >,\n | \"getAccountInitCode\"\n | \"entryPoint\"\n | \"version\"\n | \"abi\"\n | \"accountAddress\"\n | \"type\"\n> & {\n salt?: bigint;\n initCode?: Hex;\n accountAddress?: Address;\n factoryAddress?: Address;\n version?: TLightAccountVersion;\n entryPoint?: EntryPointDef<\n LightAccountEntryPointVersion<\"LightAccount\", TLightAccountVersion>,\n Chain\n >;\n};\n// [!endregion CreateLightAccountParams]\n\nexport async function createLightAccount<\n TTransport extends Transport = Transport,\n TSigner extends SmartAccountSigner = SmartAccountSigner,\n TLightAccountVersion extends LightAccountVersion<\"LightAccount\"> = \"v2.0.0\"\n>(\n config: CreateLightAccountParams<TTransport, TSigner, TLightAccountVersion>\n): Promise<LightAccount<TSigner, TLightAccountVersion>>;\n\n/**\n * Creates a light account based on the provided parameters such as transport, chain, signer, init code, and more. Ensures that an account is configured and returned with various capabilities, such as transferring ownership and retrieving the owner's address.\n *\n * @example\n * ```ts\n * import { createLightAccount } from \"@account-kit/smart-contracts\";\n * import { LocalAccountSigner } from \"@aa-sdk/core\";\n * import { sepolia } from \"viem/chains\";\n * import { http, generatePrivateKey } from \"viem\"\n *\n * const account = await createLightAccount({\n * chain: sepolia,\n * transport: http(\"RPC_URL\"),\n * signer: LocalAccountSigner.privateKeyToAccountSigner(generatePrivateKey())\n * });\n * ```\n *\n * @param {CreateLightAccountParams} config The parameters for creating a light account\n * @returns {Promise<LightAccount>} A promise that resolves to a `LightAccount` object containing the created account information and methods\n */\nexport async function createLightAccount({\n transport,\n chain,\n signer,\n initCode,\n version = defaultLightAccountVersion(),\n entryPoint = getEntryPoint(chain, {\n version: AccountVersionRegistry[\"LightAccount\"][version]\n .entryPointVersion as any,\n }),\n accountAddress,\n factoryAddress = getDefaultLightAccountFactoryAddress(chain, version),\n salt: salt_ = 0n,\n}: CreateLightAccountParams): Promise<LightAccount> {\n const client = createBundlerClient({\n transport,\n chain,\n });\n\n const accountAbi =\n version === \"v2.0.0\" ? LightAccountAbi_v2 : LightAccountAbi_v1;\n const factoryAbi =\n version === \"v2.0.0\"\n ? LightAccountFactoryAbi_v1\n : LightAccountFactoryAbi_v2;\n\n const signerAddress = await signer.getAddress();\n\n const salt = LightAccountUnsupported1271Factories.has(\n factoryAddress.toLowerCase() as Address\n )\n ? 0n\n : salt_;\n\n const getAccountInitCode = async () => {\n if (initCode) return initCode;\n\n return concatHex([\n factoryAddress,\n encodeFunctionData({\n abi: factoryAbi,\n functionName: \"createAccount\",\n args: [signerAddress, salt],\n }),\n ]);\n };\n\n const address =\n accountAddress ??\n predictLightAccountAddress({\n factoryAddress,\n salt,\n signerAddress,\n version,\n });\n\n const account = await createLightAccountBase<\n \"LightAccount\",\n LightAccountVersion<\"LightAccount\">,\n Transport,\n SmartAccountSigner\n >({\n transport,\n chain,\n signer,\n abi: accountAbi,\n type: \"LightAccount\",\n version,\n entryPoint,\n accountAddress: address,\n getAccountInitCode,\n });\n\n return {\n ...account,\n\n encodeTransferOwnership: (newOwner: Address) => {\n return encodeFunctionData({\n abi: accountAbi,\n functionName: \"transferOwnership\",\n args: [newOwner],\n });\n },\n async getOwnerAddress(): Promise<Address> {\n const callResult = await client.readContract({\n address,\n abi: accountAbi,\n functionName: \"owner\",\n });\n\n if (callResult == null) {\n throw new Error(\"could not get on-chain owner\");\n }\n\n return callResult;\n },\n };\n}\n"]}
1
+ {"version":3,"file":"account.js","sourceRoot":"","sources":["../../../../../src/light-account/accounts/account.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,aAAa,GAId,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,SAAS,EACT,kBAAkB,GAInB,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAKjF,OAAO,EACL,sBAAsB,EACtB,oCAAoC,EACpC,0BAA0B,EAC1B,oCAAoC,GACrC,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,GAGvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAiDjE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EACvC,SAAS,EACT,KAAK,EACL,MAAM,EACN,QAAQ,EACR,OAAO,GAAG,0BAA0B,EAAE,EACtC,UAAU,GAAG,aAAa,CAAC,KAAK,EAAE;IAChC,OAAO,EAAE,sBAAsB,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC;SACrD,iBAAwB;CAC5B,CAAC,EACF,cAAc,EACd,cAAc,GAAG,oCAAoC,CAAC,KAAK,EAAE,OAAO,CAAC,EACrE,IAAI,EAAE,KAAK,GAAG,EAAE,GACS;IACzB,MAAM,MAAM,GAAG,mBAAmB,CAAC;QACjC,SAAS;QACT,KAAK;KACN,CAAC,CAAC;IAEH,MAAM,UAAU,GACd,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,kBAAkB,CAAC;IACjE,MAAM,UAAU,GACd,OAAO,KAAK,QAAQ;QAClB,CAAC,CAAC,yBAAyB;QAC3B,CAAC,CAAC,yBAAyB,CAAC;IAEhC,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;IAEhD,MAAM,IAAI,GAAG,oCAAoC,CAAC,GAAG,CACnD,cAAc,CAAC,WAAW,EAAa,CACxC;QACC,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,KAAK,CAAC;IAEV,MAAM,kBAAkB,GAAG,KAAK,IAAI,EAAE;QACpC,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAE9B,OAAO,SAAS,CAAC;YACf,cAAc;YACd,kBAAkB,CAAC;gBACjB,GAAG,EAAE,UAAU;gBACf,YAAY,EAAE,eAAe;gBAC7B,IAAI,EAAE,CAAC,aAAa,EAAE,IAAI,CAAC;aAC5B,CAAC;SACH,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,OAAO,GACX,cAAc;QACd,0BAA0B,CAAC;YACzB,cAAc;YACd,IAAI;YACJ,YAAY,EAAE,aAAa;YAC3B,OAAO;SACR,CAAC,CAAC;IAEL,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAK1C;QACA,SAAS;QACT,KAAK;QACL,MAAM;QACN,GAAG,EAAE,UAAU;QACf,IAAI,EAAE,cAAc;QACpB,OAAO;QACP,UAAU;QACV,cAAc,EAAE,OAAO;QACvB,kBAAkB;KACnB,CAAC,CAAC;IAEH,OAAO;QACL,GAAG,OAAO;QAEV,uBAAuB,EAAE,CAAC,QAAiB,EAAE,EAAE;YAC7C,OAAO,kBAAkB,CAAC;gBACxB,GAAG,EAAE,UAAU;gBACf,YAAY,EAAE,mBAAmB;gBACjC,IAAI,EAAE,CAAC,QAAQ,CAAC;aACjB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,eAAe;YACnB,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;gBAC3C,OAAO;gBACP,GAAG,EAAE,UAAU;gBACf,YAAY,EAAE,OAAO;aACtB,CAAC,CAAC;YAEH,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAClD,CAAC;YAED,OAAO,UAAU,CAAC;QACpB,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import {\n createBundlerClient,\n getEntryPoint,\n type Address,\n type EntryPointDef,\n type SmartAccountSigner,\n} from \"@aa-sdk/core\";\nimport {\n concatHex,\n encodeFunctionData,\n type Chain,\n type Hex,\n type Transport,\n} from \"viem\";\nimport { LightAccountAbi_v1 } from \"../abis/LightAccountAbi_v1.js\";\nimport { LightAccountAbi_v2 } from \"../abis/LightAccountAbi_v2.js\";\nimport { LightAccountFactoryAbi_v1 } from \"../abis/LightAccountFactoryAbi_v1.js\";\nimport { LightAccountFactoryAbi_v2 } from \"../abis/LightAccountFactoryAbi_v2.js\";\nimport type {\n LightAccountEntryPointVersion,\n LightAccountVersion,\n} from \"../types.js\";\nimport {\n AccountVersionRegistry,\n LightAccountUnsupported1271Factories,\n defaultLightAccountVersion,\n getDefaultLightAccountFactoryAddress,\n} from \"../utils.js\";\nimport {\n createLightAccountBase,\n type CreateLightAccountBaseParams,\n type LightAccountBase,\n} from \"./base.js\";\nimport { predictLightAccountAddress } from \"./predictAddress.js\";\n\nexport type LightAccount<\n TSigner extends SmartAccountSigner = SmartAccountSigner,\n TLightAccountVersion extends LightAccountVersion<\"LightAccount\"> = LightAccountVersion<\"LightAccount\">\n> = LightAccountBase<TSigner, \"LightAccount\", TLightAccountVersion> & {\n encodeTransferOwnership: (newOwner: Address) => Hex;\n getOwnerAddress: () => Promise<Address>;\n};\n\n// [!region CreateLightAccountParams]\nexport type CreateLightAccountParams<\n TTransport extends Transport = Transport,\n TSigner extends SmartAccountSigner = SmartAccountSigner,\n TLightAccountVersion extends LightAccountVersion<\"LightAccount\"> = LightAccountVersion<\"LightAccount\">\n> = Omit<\n CreateLightAccountBaseParams<\n \"LightAccount\",\n TLightAccountVersion,\n TTransport,\n TSigner\n >,\n | \"getAccountInitCode\"\n | \"entryPoint\"\n | \"version\"\n | \"abi\"\n | \"accountAddress\"\n | \"type\"\n> & {\n salt?: bigint;\n initCode?: Hex;\n accountAddress?: Address;\n factoryAddress?: Address;\n version?: TLightAccountVersion;\n entryPoint?: EntryPointDef<\n LightAccountEntryPointVersion<\"LightAccount\", TLightAccountVersion>,\n Chain\n >;\n};\n// [!endregion CreateLightAccountParams]\n\nexport async function createLightAccount<\n TTransport extends Transport = Transport,\n TSigner extends SmartAccountSigner = SmartAccountSigner,\n TLightAccountVersion extends LightAccountVersion<\"LightAccount\"> = \"v2.0.0\"\n>(\n config: CreateLightAccountParams<TTransport, TSigner, TLightAccountVersion>\n): Promise<LightAccount<TSigner, TLightAccountVersion>>;\n\n/**\n * Creates a light account based on the provided parameters such as transport, chain, signer, init code, and more. Ensures that an account is configured and returned with various capabilities, such as transferring ownership and retrieving the owner's address.\n *\n * @example\n * ```ts\n * import { createLightAccount } from \"@account-kit/smart-contracts\";\n * import { LocalAccountSigner } from \"@aa-sdk/core\";\n * import { sepolia } from \"viem/chains\";\n * import { http, generatePrivateKey } from \"viem\"\n *\n * const account = await createLightAccount({\n * chain: sepolia,\n * transport: http(\"RPC_URL\"),\n * signer: LocalAccountSigner.privateKeyToAccountSigner(generatePrivateKey())\n * });\n * ```\n *\n * @param {CreateLightAccountParams} config The parameters for creating a light account\n * @returns {Promise<LightAccount>} A promise that resolves to a `LightAccount` object containing the created account information and methods\n */\nexport async function createLightAccount({\n transport,\n chain,\n signer,\n initCode,\n version = defaultLightAccountVersion(),\n entryPoint = getEntryPoint(chain, {\n version: AccountVersionRegistry[\"LightAccount\"][version]\n .entryPointVersion as any,\n }),\n accountAddress,\n factoryAddress = getDefaultLightAccountFactoryAddress(chain, version),\n salt: salt_ = 0n,\n}: CreateLightAccountParams): Promise<LightAccount> {\n const client = createBundlerClient({\n transport,\n chain,\n });\n\n const accountAbi =\n version === \"v2.0.0\" ? LightAccountAbi_v2 : LightAccountAbi_v1;\n const factoryAbi =\n version === \"v2.0.0\"\n ? LightAccountFactoryAbi_v1\n : LightAccountFactoryAbi_v2;\n\n const signerAddress = await signer.getAddress();\n\n const salt = LightAccountUnsupported1271Factories.has(\n factoryAddress.toLowerCase() as Address\n )\n ? 0n\n : salt_;\n\n const getAccountInitCode = async () => {\n if (initCode) return initCode;\n\n return concatHex([\n factoryAddress,\n encodeFunctionData({\n abi: factoryAbi,\n functionName: \"createAccount\",\n args: [signerAddress, salt],\n }),\n ]);\n };\n\n const address =\n accountAddress ??\n predictLightAccountAddress({\n factoryAddress,\n salt,\n ownerAddress: signerAddress,\n version,\n });\n\n const account = await createLightAccountBase<\n \"LightAccount\",\n LightAccountVersion<\"LightAccount\">,\n Transport,\n SmartAccountSigner\n >({\n transport,\n chain,\n signer,\n abi: accountAbi,\n type: \"LightAccount\",\n version,\n entryPoint,\n accountAddress: address,\n getAccountInitCode,\n });\n\n return {\n ...account,\n\n encodeTransferOwnership: (newOwner: Address) => {\n return encodeFunctionData({\n abi: accountAbi,\n functionName: \"transferOwnership\",\n args: [newOwner],\n });\n },\n async getOwnerAddress(): Promise<Address> {\n const callResult = await client.readContract({\n address,\n abi: accountAbi,\n functionName: \"owner\",\n });\n\n if (callResult == null) {\n throw new Error(\"could not get on-chain owner\");\n }\n\n return callResult;\n },\n };\n}\n"]}
@@ -1,9 +1,10 @@
1
- import { createBundlerClient, getAccountAddress, getEntryPoint, } from "@aa-sdk/core";
1
+ import { createBundlerClient, getEntryPoint, } from "@aa-sdk/core";
2
2
  import { concatHex, encodeFunctionData, hexToBigInt, } from "viem";
3
3
  import { MultiOwnerLightAccountAbi } from "../abis/MultiOwnerLightAccountAbi.js";
4
4
  import { MultiOwnerLightAccountFactoryAbi } from "../abis/MultiOwnerLightAccountFactoryAbi.js";
5
5
  import { defaultLightAccountVersion, getDefaultMultiOwnerLightAccountFactoryAddress, } from "../utils.js";
6
6
  import { createLightAccountBase, } from "./base.js";
7
+ import { predictMultiOwnerLightAccountAddress } from "./predictAddress.js";
7
8
  /**
8
9
  * Creates a multi-owner light account using the provided parameters, including transport, chain, signer, initialization code, version, account address, factory address, salt, and owners. Ensures the owners list is deduplicated, ordered, and valid.
9
10
  *
@@ -31,19 +32,19 @@ export async function createMultiOwnerLightAccount({ transport, chain, signer, i
31
32
  transport,
32
33
  chain,
33
34
  });
35
+ // NOTE: the current signer connected will be one of the owners as well
36
+ const ownerAddress = await signer.getAddress();
37
+ // owners need to be dedupe + ordered in ascending order and not == to zero address
38
+ const owners_ = Array.from(new Set([...owners, ownerAddress]))
39
+ .filter((x) => hexToBigInt(x) !== 0n)
40
+ .sort((a, b) => {
41
+ const bigintA = hexToBigInt(a);
42
+ const bigintB = hexToBigInt(b);
43
+ return bigintA < bigintB ? -1 : bigintA > bigintB ? 1 : 0;
44
+ });
34
45
  const getAccountInitCode = async () => {
35
46
  if (initCode)
36
47
  return initCode;
37
- // NOTE: the current signer connected will be one of the owners as well
38
- const ownerAddress = await signer.getAddress();
39
- // owners need to be dedupe + ordered in ascending order and not == to zero address
40
- const owners_ = Array.from(new Set([...owners, ownerAddress]))
41
- .filter((x) => hexToBigInt(x) !== 0n)
42
- .sort((a, b) => {
43
- const bigintA = hexToBigInt(a);
44
- const bigintB = hexToBigInt(b);
45
- return bigintA < bigintB ? -1 : bigintA > bigintB ? 1 : 0;
46
- });
47
48
  return concatHex([
48
49
  factoryAddress,
49
50
  encodeFunctionData({
@@ -53,12 +54,12 @@ export async function createMultiOwnerLightAccount({ transport, chain, signer, i
53
54
  }),
54
55
  ]);
55
56
  };
56
- const address = await getAccountAddress({
57
- client,
58
- entryPoint,
59
- accountAddress,
60
- getAccountInitCode,
61
- });
57
+ const address = accountAddress ??
58
+ predictMultiOwnerLightAccountAddress({
59
+ factoryAddress,
60
+ salt: salt_,
61
+ ownerAddresses: owners_,
62
+ });
62
63
  const account = await createLightAccountBase({
63
64
  transport,
64
65
  chain,
@@ -1 +1 @@
1
- {"version":3,"file":"multiOwner.js","sourceRoot":"","sources":["../../../../../src/light-account/accounts/multiOwner.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createBundlerClient,\n getAccountAddress,\n getEntryPoint,\n type EntryPointDef,\n type SmartAccountSigner,\n} from \"@aa-sdk/core\";\nimport {\n concatHex,\n encodeFunctionData,\n hexToBigInt,\n type Address,\n type Chain,\n type Hex,\n type Transport,\n} from \"viem\";\nimport { MultiOwnerLightAccountAbi } from \"../abis/MultiOwnerLightAccountAbi.js\";\nimport { MultiOwnerLightAccountFactoryAbi } from \"../abis/MultiOwnerLightAccountFactoryAbi.js\";\nimport type {\n LightAccountEntryPointVersion,\n LightAccountVersion,\n} from \"../types.js\";\nimport {\n defaultLightAccountVersion,\n getDefaultMultiOwnerLightAccountFactoryAddress,\n} from \"../utils.js\";\nimport {\n createLightAccountBase,\n type CreateLightAccountBaseParams,\n type LightAccountBase,\n} from \"./base.js\";\n\nexport type MultiOwnerLightAccount<\n TSigner extends SmartAccountSigner = SmartAccountSigner,\n TLightAccountVersion extends LightAccountVersion<\"MultiOwnerLightAccount\"> = LightAccountVersion<\"MultiOwnerLightAccount\">\n> = LightAccountBase<\n TSigner,\n \"MultiOwnerLightAccount\",\n TLightAccountVersion\n> & {\n encodeUpdateOwners: (\n ownersToAdd: Address[],\n ownersToRemove: Address[]\n ) => Hex;\n getOwnerAddresses: () => Promise<readonly Address[]>;\n};\n\nexport type CreateMultiOwnerLightAccountParams<\n TTransport extends Transport = Transport,\n TSigner extends SmartAccountSigner = SmartAccountSigner,\n TLightAccountVersion extends LightAccountVersion<\"MultiOwnerLightAccount\"> = LightAccountVersion<\"MultiOwnerLightAccount\">\n> = Omit<\n CreateLightAccountBaseParams<\n \"MultiOwnerLightAccount\",\n TLightAccountVersion,\n TTransport,\n TSigner\n >,\n | \"getAccountInitCode\"\n | \"entryPoint\"\n | \"version\"\n | \"abi\"\n | \"accountAddress\"\n | \"type\"\n> & {\n salt?: bigint;\n initCode?: Hex;\n accountAddress?: Address;\n factoryAddress?: Address;\n version?: TLightAccountVersion;\n entryPoint?: EntryPointDef<\n LightAccountEntryPointVersion<\n \"MultiOwnerLightAccount\",\n TLightAccountVersion\n >,\n Chain\n >;\n owners?: Address[];\n};\n\nexport async function createMultiOwnerLightAccount<\n TTransport extends Transport = Transport,\n TSigner extends SmartAccountSigner = SmartAccountSigner,\n TLightAccountVersion extends LightAccountVersion<\"MultiOwnerLightAccount\"> = LightAccountVersion<\"MultiOwnerLightAccount\">\n>(\n config: CreateMultiOwnerLightAccountParams<\n TTransport,\n TSigner,\n TLightAccountVersion\n >\n): Promise<MultiOwnerLightAccount<TSigner, TLightAccountVersion>>;\n\n/**\n * Creates a multi-owner light account using the provided parameters, including transport, chain, signer, initialization code, version, account address, factory address, salt, and owners. Ensures the owners list is deduplicated, ordered, and valid.\n *\n * @example\n * ```ts\n * import { createMultiOwnerLightAccount } from \"@account-kit/smart-contracts\";\n * import { LocalAccountSigner } from \"@aa-sdk/core\";\n * import { sepolia } from \"viem/chains\";\n * import { http, generatePrivateKey } from \"viem\"\n *\n * const account = await createMultiOwnerLightAccount({\n * chain: sepolia,\n * transport: http(\"RPC_URL\"),\n * signer: LocalAccountSigner.privateKeyToAccountSigner(generatePrivateKey())\n * });\n * ```\n *\n * @param {CreateMultiOwnerLightAccountParams} config The parameters for creating a multi-owner light account\n * @returns {Promise<MultiOwnerLightAccount>} A promise that resolves to a `MultiOwnerLightAccount` object containing the created account information and methods\n */\nexport async function createMultiOwnerLightAccount({\n transport,\n chain,\n signer,\n initCode,\n version = defaultLightAccountVersion(),\n entryPoint = getEntryPoint(chain, {\n version: \"0.7.0\",\n }),\n accountAddress,\n factoryAddress = getDefaultMultiOwnerLightAccountFactoryAddress(\n chain,\n version\n ),\n salt: salt_ = 0n,\n owners = [],\n}: CreateMultiOwnerLightAccountParams): Promise<MultiOwnerLightAccount> {\n const client = createBundlerClient({\n transport,\n chain,\n });\n\n const getAccountInitCode = async () => {\n if (initCode) return initCode;\n\n // NOTE: the current signer connected will be one of the owners as well\n const ownerAddress = await signer.getAddress();\n // owners need to be dedupe + ordered in ascending order and not == to zero address\n const owners_ = Array.from(new Set([...owners, ownerAddress]))\n .filter((x) => hexToBigInt(x) !== 0n)\n .sort((a, b) => {\n const bigintA = hexToBigInt(a);\n const bigintB = hexToBigInt(b);\n\n return bigintA < bigintB ? -1 : bigintA > bigintB ? 1 : 0;\n });\n\n return concatHex([\n factoryAddress,\n encodeFunctionData({\n abi: MultiOwnerLightAccountFactoryAbi,\n functionName: \"createAccount\",\n args: [owners_, salt_],\n }),\n ]);\n };\n\n const address = await getAccountAddress({\n client,\n entryPoint,\n accountAddress,\n getAccountInitCode,\n });\n\n const account = await createLightAccountBase<\n \"MultiOwnerLightAccount\",\n LightAccountVersion<\"MultiOwnerLightAccount\">,\n Transport,\n SmartAccountSigner\n >({\n transport,\n chain,\n signer,\n abi: MultiOwnerLightAccountAbi,\n version,\n type: \"MultiOwnerLightAccount\",\n entryPoint,\n accountAddress: address,\n getAccountInitCode,\n });\n\n return {\n ...account,\n encodeUpdateOwners: (ownersToAdd: Address[], ownersToRemove: Address[]) => {\n return encodeFunctionData({\n abi: MultiOwnerLightAccountAbi,\n functionName: \"updateOwners\",\n args: [ownersToAdd, ownersToRemove],\n });\n },\n async getOwnerAddresses(): Promise<readonly Address[]> {\n const callResult = await client.readContract({\n address,\n abi: MultiOwnerLightAccountAbi,\n functionName: \"owners\",\n });\n\n if (callResult == null) {\n throw new Error(\"could not get on-chain owners\");\n }\n\n if (!callResult.includes(await signer.getAddress())) {\n throw new Error(\"on-chain owners does not include the current signer\");\n }\n\n return callResult;\n },\n };\n}\n"]}
1
+ {"version":3,"file":"multiOwner.js","sourceRoot":"","sources":["../../../../../src/light-account/accounts/multiOwner.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createBundlerClient,\n getEntryPoint,\n type EntryPointDef,\n type SmartAccountSigner,\n} from \"@aa-sdk/core\";\nimport {\n concatHex,\n encodeFunctionData,\n hexToBigInt,\n type Address,\n type Chain,\n type Hex,\n type Transport,\n} from \"viem\";\nimport { MultiOwnerLightAccountAbi } from \"../abis/MultiOwnerLightAccountAbi.js\";\nimport { MultiOwnerLightAccountFactoryAbi } from \"../abis/MultiOwnerLightAccountFactoryAbi.js\";\nimport type {\n LightAccountEntryPointVersion,\n LightAccountVersion,\n} from \"../types.js\";\nimport {\n defaultLightAccountVersion,\n getDefaultMultiOwnerLightAccountFactoryAddress,\n} from \"../utils.js\";\nimport {\n createLightAccountBase,\n type CreateLightAccountBaseParams,\n type LightAccountBase,\n} from \"./base.js\";\nimport { predictMultiOwnerLightAccountAddress } from \"./predictAddress.js\";\n\nexport type MultiOwnerLightAccount<\n TSigner extends SmartAccountSigner = SmartAccountSigner,\n TLightAccountVersion extends LightAccountVersion<\"MultiOwnerLightAccount\"> = LightAccountVersion<\"MultiOwnerLightAccount\">\n> = LightAccountBase<\n TSigner,\n \"MultiOwnerLightAccount\",\n TLightAccountVersion\n> & {\n encodeUpdateOwners: (\n ownersToAdd: Address[],\n ownersToRemove: Address[]\n ) => Hex;\n getOwnerAddresses: () => Promise<readonly Address[]>;\n};\n\nexport type CreateMultiOwnerLightAccountParams<\n TTransport extends Transport = Transport,\n TSigner extends SmartAccountSigner = SmartAccountSigner,\n TLightAccountVersion extends LightAccountVersion<\"MultiOwnerLightAccount\"> = LightAccountVersion<\"MultiOwnerLightAccount\">\n> = Omit<\n CreateLightAccountBaseParams<\n \"MultiOwnerLightAccount\",\n TLightAccountVersion,\n TTransport,\n TSigner\n >,\n | \"getAccountInitCode\"\n | \"entryPoint\"\n | \"version\"\n | \"abi\"\n | \"accountAddress\"\n | \"type\"\n> & {\n salt?: bigint;\n initCode?: Hex;\n accountAddress?: Address;\n factoryAddress?: Address;\n version?: TLightAccountVersion;\n entryPoint?: EntryPointDef<\n LightAccountEntryPointVersion<\n \"MultiOwnerLightAccount\",\n TLightAccountVersion\n >,\n Chain\n >;\n owners?: Address[];\n};\n\nexport async function createMultiOwnerLightAccount<\n TTransport extends Transport = Transport,\n TSigner extends SmartAccountSigner = SmartAccountSigner,\n TLightAccountVersion extends LightAccountVersion<\"MultiOwnerLightAccount\"> = LightAccountVersion<\"MultiOwnerLightAccount\">\n>(\n config: CreateMultiOwnerLightAccountParams<\n TTransport,\n TSigner,\n TLightAccountVersion\n >\n): Promise<MultiOwnerLightAccount<TSigner, TLightAccountVersion>>;\n\n/**\n * Creates a multi-owner light account using the provided parameters, including transport, chain, signer, initialization code, version, account address, factory address, salt, and owners. Ensures the owners list is deduplicated, ordered, and valid.\n *\n * @example\n * ```ts\n * import { createMultiOwnerLightAccount } from \"@account-kit/smart-contracts\";\n * import { LocalAccountSigner } from \"@aa-sdk/core\";\n * import { sepolia } from \"viem/chains\";\n * import { http, generatePrivateKey } from \"viem\"\n *\n * const account = await createMultiOwnerLightAccount({\n * chain: sepolia,\n * transport: http(\"RPC_URL\"),\n * signer: LocalAccountSigner.privateKeyToAccountSigner(generatePrivateKey())\n * });\n * ```\n *\n * @param {CreateMultiOwnerLightAccountParams} config The parameters for creating a multi-owner light account\n * @returns {Promise<MultiOwnerLightAccount>} A promise that resolves to a `MultiOwnerLightAccount` object containing the created account information and methods\n */\nexport async function createMultiOwnerLightAccount({\n transport,\n chain,\n signer,\n initCode,\n version = defaultLightAccountVersion(),\n entryPoint = getEntryPoint(chain, {\n version: \"0.7.0\",\n }),\n accountAddress,\n factoryAddress = getDefaultMultiOwnerLightAccountFactoryAddress(\n chain,\n version\n ),\n salt: salt_ = 0n,\n owners = [],\n}: CreateMultiOwnerLightAccountParams): Promise<MultiOwnerLightAccount> {\n const client = createBundlerClient({\n transport,\n chain,\n });\n\n // NOTE: the current signer connected will be one of the owners as well\n const ownerAddress = await signer.getAddress();\n // owners need to be dedupe + ordered in ascending order and not == to zero address\n const owners_ = Array.from(new Set([...owners, ownerAddress]))\n .filter((x) => hexToBigInt(x) !== 0n)\n .sort((a, b) => {\n const bigintA = hexToBigInt(a);\n const bigintB = hexToBigInt(b);\n\n return bigintA < bigintB ? -1 : bigintA > bigintB ? 1 : 0;\n });\n\n const getAccountInitCode = async () => {\n if (initCode) return initCode;\n\n return concatHex([\n factoryAddress,\n encodeFunctionData({\n abi: MultiOwnerLightAccountFactoryAbi,\n functionName: \"createAccount\",\n args: [owners_, salt_],\n }),\n ]);\n };\n\n const address =\n accountAddress ??\n predictMultiOwnerLightAccountAddress({\n factoryAddress,\n salt: salt_,\n ownerAddresses: owners_,\n });\n\n const account = await createLightAccountBase<\n \"MultiOwnerLightAccount\",\n LightAccountVersion<\"MultiOwnerLightAccount\">,\n Transport,\n SmartAccountSigner\n >({\n transport,\n chain,\n signer,\n abi: MultiOwnerLightAccountAbi,\n version,\n type: \"MultiOwnerLightAccount\",\n entryPoint,\n accountAddress: address,\n getAccountInitCode,\n });\n\n return {\n ...account,\n encodeUpdateOwners: (ownersToAdd: Address[], ownersToRemove: Address[]) => {\n return encodeFunctionData({\n abi: MultiOwnerLightAccountAbi,\n functionName: \"updateOwners\",\n args: [ownersToAdd, ownersToRemove],\n });\n },\n async getOwnerAddresses(): Promise<readonly Address[]> {\n const callResult = await client.readContract({\n address,\n abi: MultiOwnerLightAccountAbi,\n functionName: \"owners\",\n });\n\n if (callResult == null) {\n throw new Error(\"could not get on-chain owners\");\n }\n\n if (!callResult.includes(await signer.getAddress())) {\n throw new Error(\"on-chain owners does not include the current signer\");\n }\n\n return callResult;\n },\n };\n}\n"]}
@@ -3,7 +3,13 @@ import type { LightAccountVersionConfigs } from "../types";
3
3
  export type PredictLightAccountAddressParams = {
4
4
  factoryAddress: Address;
5
5
  salt: bigint;
6
- signerAddress: Address;
6
+ ownerAddress: Address;
7
7
  version: keyof LightAccountVersionConfigs["LightAccount"];
8
8
  };
9
- export declare function predictLightAccountAddress({ factoryAddress, salt, signerAddress, version, }: PredictLightAccountAddressParams): Address;
9
+ export declare function predictLightAccountAddress({ factoryAddress, salt, ownerAddress, version, }: PredictLightAccountAddressParams): Address;
10
+ export type PredictMultiOwnerLightAccountAddressParams = {
11
+ factoryAddress: Address;
12
+ salt: bigint;
13
+ ownerAddresses: Address[];
14
+ };
15
+ export declare function predictMultiOwnerLightAccountAddress({ factoryAddress, salt, ownerAddresses, }: PredictMultiOwnerLightAccountAddressParams): Address;
@@ -2,7 +2,7 @@ import { encodeAbiParameters, encodeDeployData, keccak256, getContractAddress, t
2
2
  import { OZ_ERC1967Proxy_ConstructorAbi } from "../abis/OZ_ERC1967Proxy.js";
3
3
  import { AccountVersionRegistry } from "../utils.js";
4
4
  import { LightAccountAbi_v1 } from "../abis/LightAccountAbi_v1.js";
5
- export function predictLightAccountAddress({ factoryAddress, salt, signerAddress, version, }) {
5
+ export function predictLightAccountAddress({ factoryAddress, salt, ownerAddress, version, }) {
6
6
  const implementationAddress =
7
7
  // If we aren't using the default factory address, we compute the implementation address from the factory's `create` deployment.
8
8
  // This is accurate for both LA v1 and v2 factories. If we are using the default factory address, we use the implementation address from the registry.
@@ -31,16 +31,15 @@ export function predictLightAccountAddress({ factoryAddress, salt, signerAddress
31
31
  encodeFunctionData({
32
32
  abi: LightAccountAbi_v1,
33
33
  functionName: "initialize",
34
- args: [signerAddress],
34
+ args: [ownerAddress],
35
35
  }),
36
36
  ],
37
37
  }),
38
38
  });
39
39
  case "v2.0.0":
40
40
  // Logic ported from LA factory v2.0.0
41
- const combinedSalt = keccak256(encodeAbiParameters([{ type: "address" }, { type: "uint256" }], [signerAddress, salt]));
42
- // Bytecode from https://github.com/Vectorized/solady/blob/c6e5238e5f3b621789c59e1a443f43b6606394b2/src/utils/LibClone.sol#L721
43
- const initCode = `0x603d3d8160223d3973${implementationAddress.slice(2)}60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3`;
41
+ const combinedSalt = keccak256(encodeAbiParameters([{ type: "address" }, { type: "uint256" }], [ownerAddress, salt]));
42
+ const initCode = getLAv2ProxyBytecode(implementationAddress);
44
43
  return getContractAddress({
45
44
  from: factoryAddress,
46
45
  opcode: "CREATE2",
@@ -51,6 +50,33 @@ export function predictLightAccountAddress({ factoryAddress, salt, signerAddress
51
50
  assertNeverLightAccountVersion(version);
52
51
  }
53
52
  }
53
+ // Note: assumes the owner addresses are already deduped, sorted in ascending order, and have the signer address included.
54
+ export function predictMultiOwnerLightAccountAddress({ factoryAddress, salt, ownerAddresses, }) {
55
+ const implementationAddress =
56
+ // If we aren't using the default factory address, we compute the implementation address from the factory's `create` deployment.
57
+ // This is accurate for both LA v1 and v2 factories. If we are using the default factory address, we use the implementation address from the registry.
58
+ factoryAddress !==
59
+ AccountVersionRegistry.MultiOwnerLightAccount["v2.0.0"].addresses.default
60
+ .factory
61
+ ? getContractAddress({
62
+ from: factoryAddress,
63
+ nonce: 1n,
64
+ })
65
+ : AccountVersionRegistry.MultiOwnerLightAccount["v2.0.0"].addresses
66
+ .default.impl;
67
+ const combinedSalt = keccak256(encodeAbiParameters([{ type: "address[]" }, { type: "uint256" }], [ownerAddresses, salt]));
68
+ const initCode = getLAv2ProxyBytecode(implementationAddress);
69
+ return getContractAddress({
70
+ from: factoryAddress,
71
+ opcode: "CREATE2",
72
+ salt: combinedSalt,
73
+ bytecode: initCode,
74
+ });
75
+ }
76
+ // Bytecode from https://github.com/Vectorized/solady/blob/c6e5238e5f3b621789c59e1a443f43b6606394b2/src/utils/LibClone.sol#L721
77
+ function getLAv2ProxyBytecode(implementationAddress) {
78
+ return `0x603d3d8160223d3973${implementationAddress.slice(2)}60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3`;
79
+ }
54
80
  function assertNeverLightAccountVersion(version) {
55
81
  throw new Error(`Unknown light account version: ${version}`);
56
82
  }
@@ -1 +1 @@
1
- {"version":3,"file":"predictAddress.js","sourceRoot":"","sources":["../../../../../src/light-account/accounts/predictAddress.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,SAAS,EACT,kBAAkB,EAGlB,KAAK,EACL,kBAAkB,GACnB,MAAM,MAAM,CAAC;AAEd,OAAO,EAAE,8BAA8B,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AASnE,MAAM,UAAU,0BAA0B,CAAC,EACzC,cAAc,EACd,IAAI,EACJ,aAAa,EACb,OAAO,GAC0B;IACjC,MAAM,qBAAqB;IACzB,gIAAgI;IAChI,sJAAsJ;IACtJ,cAAc;QACd,sBAAsB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO;QACpE,CAAC,CAAC,kBAAkB,CAAC;YACjB,IAAI,EAAE,cAAc;YACpB,KAAK,EAAE,EAAE;SACV,CAAC;QACJ,CAAC,CAAC,sBAAsB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;IAE1E,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ;YACX,8CAA8C;YAC9C,MAAM,mBAAmB,GACvB,4lEAA4lE,CAAC;YAE/lE,OAAO,kBAAkB,CAAC;gBACxB,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,SAAS;gBACjB,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;gBAC/B,QAAQ,EAAE,gBAAgB,CAAC;oBACzB,QAAQ,EAAE,mBAAmB;oBAC7B,GAAG,EAAE,8BAA8B;oBACnC,IAAI,EAAE;wBACJ,qBAAqB;wBACrB,kBAAkB,CAAC;4BACjB,GAAG,EAAE,kBAAkB;4BACvB,YAAY,EAAE,YAAY;4BAC1B,IAAI,EAAE,CAAC,aAAa,CAAC;yBACtB,CAAC;qBACH;iBACF,CAAC;aACH,CAAC,CAAC;QAEL,KAAK,QAAQ;YACX,sCAAsC;YACtC,MAAM,YAAY,GAAG,SAAS,CAC5B,mBAAmB,CACjB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAC1C,CAAC,aAAa,EAAE,IAAI,CAAC,CACtB,CACF,CAAC;YAEF,+HAA+H;YAE/H,MAAM,QAAQ,GAAQ,uBAAuB,qBAAqB,CAAC,KAAK,CACtE,CAAC,CACF,sIAAsI,CAAC;YAExI,OAAO,kBAAkB,CAAC;gBACxB,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,SAAS;gBACjB,IAAI,EAAE,YAAY;gBAClB,QAAQ,EAAE,QAAQ;aACnB,CAAC,CAAC;QAEL;YACE,8BAA8B,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,SAAS,8BAA8B,CAAC,OAAc;IACpD,MAAM,IAAI,KAAK,CAAC,kCAAkC,OAAO,EAAE,CAAC,CAAC;AAC/D,CAAC","sourcesContent":["import {\n encodeAbiParameters,\n encodeDeployData,\n keccak256,\n getContractAddress,\n type Address,\n type Hex,\n toHex,\n encodeFunctionData,\n} from \"viem\";\nimport type { LightAccountVersionConfigs } from \"../types\";\nimport { OZ_ERC1967Proxy_ConstructorAbi } from \"../abis/OZ_ERC1967Proxy.js\";\nimport { AccountVersionRegistry } from \"../utils.js\";\nimport { LightAccountAbi_v1 } from \"../abis/LightAccountAbi_v1.js\";\n\nexport type PredictLightAccountAddressParams = {\n factoryAddress: Address;\n salt: bigint;\n signerAddress: Address;\n version: keyof LightAccountVersionConfigs[\"LightAccount\"];\n};\n\nexport function predictLightAccountAddress({\n factoryAddress,\n salt,\n signerAddress,\n version,\n}: PredictLightAccountAddressParams): Address {\n const implementationAddress =\n // If we aren't using the default factory address, we compute the implementation address from the factory's `create` deployment.\n // This is accurate for both LA v1 and v2 factories. If we are using the default factory address, we use the implementation address from the registry.\n factoryAddress !==\n AccountVersionRegistry.LightAccount[version].addresses.default.factory\n ? getContractAddress({\n from: factoryAddress,\n nonce: 1n,\n })\n : AccountVersionRegistry.LightAccount[version].addresses.default.impl;\n\n switch (version) {\n case \"v1.0.1\":\n case \"v1.0.2\":\n case \"v1.1.0\":\n // Same proxy initcode for all LA v1 factories\n const LAv1_proxy_bytecode: Hex =\n \"0x60406080815261042c908138038061001681610218565b93843982019181818403126102135780516001600160a01b038116808203610213576020838101516001600160401b0394919391858211610213570186601f820112156102135780519061007161006c83610253565b610218565b918083528583019886828401011161021357888661008f930161026e565b813b156101b9577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916841790556000927fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8480a28051158015906101b2575b61010b575b855160e790816103458239f35b855194606086019081118682101761019e578697849283926101889952602788527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c87890152660819985a5b195960ca1b8a8901525190845af4913d15610194573d9061017a61006c83610253565b91825281943d92013e610291565b508038808080806100fe565b5060609250610291565b634e487b7160e01b84526041600452602484fd5b50826100f9565b855162461bcd60e51b815260048101859052602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b600080fd5b6040519190601f01601f191682016001600160401b0381118382101761023d57604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161023d57601f01601f191660200190565b60005b8381106102815750506000910152565b8181015183820152602001610271565b919290156102f357508151156102a5575090565b3b156102ae5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156103065750805190602001fd5b6044604051809262461bcd60e51b825260206004830152610336815180928160248601526020868601910161026e565b601f01601f19168101030190fdfe60806040523615605f5773ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54166000808092368280378136915af43d82803e15605b573d90f35b3d90fd5b73ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54166000808092368280378136915af43d82803e15605b573d90f3fea26469706673582212205da2750cd2b0cadfd354d8a1ca4752ed7f22214c8069d852f7dc6b8e9e5ee66964736f6c63430008150033\";\n\n return getContractAddress({\n from: factoryAddress,\n opcode: \"CREATE2\",\n salt: toHex(salt, { size: 32 }),\n bytecode: encodeDeployData({\n bytecode: LAv1_proxy_bytecode,\n abi: OZ_ERC1967Proxy_ConstructorAbi,\n args: [\n implementationAddress,\n encodeFunctionData({\n abi: LightAccountAbi_v1,\n functionName: \"initialize\",\n args: [signerAddress],\n }),\n ],\n }),\n });\n\n case \"v2.0.0\":\n // Logic ported from LA factory v2.0.0\n const combinedSalt = keccak256(\n encodeAbiParameters(\n [{ type: \"address\" }, { type: \"uint256\" }],\n [signerAddress, salt]\n )\n );\n\n // Bytecode from https://github.com/Vectorized/solady/blob/c6e5238e5f3b621789c59e1a443f43b6606394b2/src/utils/LibClone.sol#L721\n\n const initCode: Hex = `0x603d3d8160223d3973${implementationAddress.slice(\n 2\n )}60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3`;\n\n return getContractAddress({\n from: factoryAddress,\n opcode: \"CREATE2\",\n salt: combinedSalt,\n bytecode: initCode,\n });\n\n default:\n assertNeverLightAccountVersion(version);\n }\n}\n\nfunction assertNeverLightAccountVersion(version: never): never {\n throw new Error(`Unknown light account version: ${version}`);\n}\n"]}
1
+ {"version":3,"file":"predictAddress.js","sourceRoot":"","sources":["../../../../../src/light-account/accounts/predictAddress.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n encodeAbiParameters,\n encodeDeployData,\n keccak256,\n getContractAddress,\n type Address,\n type Hex,\n toHex,\n encodeFunctionData,\n} from \"viem\";\nimport type { LightAccountVersionConfigs } from \"../types\";\nimport { OZ_ERC1967Proxy_ConstructorAbi } from \"../abis/OZ_ERC1967Proxy.js\";\nimport { AccountVersionRegistry } from \"../utils.js\";\nimport { LightAccountAbi_v1 } from \"../abis/LightAccountAbi_v1.js\";\n\nexport type PredictLightAccountAddressParams = {\n factoryAddress: Address;\n salt: bigint;\n ownerAddress: Address;\n version: keyof LightAccountVersionConfigs[\"LightAccount\"];\n};\n\nexport function predictLightAccountAddress({\n factoryAddress,\n salt,\n ownerAddress,\n version,\n}: PredictLightAccountAddressParams): Address {\n const implementationAddress =\n // If we aren't using the default factory address, we compute the implementation address from the factory's `create` deployment.\n // This is accurate for both LA v1 and v2 factories. If we are using the default factory address, we use the implementation address from the registry.\n factoryAddress !==\n AccountVersionRegistry.LightAccount[version].addresses.default.factory\n ? getContractAddress({\n from: factoryAddress,\n nonce: 1n,\n })\n : AccountVersionRegistry.LightAccount[version].addresses.default.impl;\n\n switch (version) {\n case \"v1.0.1\":\n case \"v1.0.2\":\n case \"v1.1.0\":\n // Same proxy initcode for all LA v1 factories\n const LAv1_proxy_bytecode: Hex =\n \"0x60406080815261042c908138038061001681610218565b93843982019181818403126102135780516001600160a01b038116808203610213576020838101516001600160401b0394919391858211610213570186601f820112156102135780519061007161006c83610253565b610218565b918083528583019886828401011161021357888661008f930161026e565b813b156101b9577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916841790556000927fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8480a28051158015906101b2575b61010b575b855160e790816103458239f35b855194606086019081118682101761019e578697849283926101889952602788527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c87890152660819985a5b195960ca1b8a8901525190845af4913d15610194573d9061017a61006c83610253565b91825281943d92013e610291565b508038808080806100fe565b5060609250610291565b634e487b7160e01b84526041600452602484fd5b50826100f9565b855162461bcd60e51b815260048101859052602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b600080fd5b6040519190601f01601f191682016001600160401b0381118382101761023d57604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161023d57601f01601f191660200190565b60005b8381106102815750506000910152565b8181015183820152602001610271565b919290156102f357508151156102a5575090565b3b156102ae5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156103065750805190602001fd5b6044604051809262461bcd60e51b825260206004830152610336815180928160248601526020868601910161026e565b601f01601f19168101030190fdfe60806040523615605f5773ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54166000808092368280378136915af43d82803e15605b573d90f35b3d90fd5b73ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54166000808092368280378136915af43d82803e15605b573d90f3fea26469706673582212205da2750cd2b0cadfd354d8a1ca4752ed7f22214c8069d852f7dc6b8e9e5ee66964736f6c63430008150033\";\n\n return getContractAddress({\n from: factoryAddress,\n opcode: \"CREATE2\",\n salt: toHex(salt, { size: 32 }),\n bytecode: encodeDeployData({\n bytecode: LAv1_proxy_bytecode,\n abi: OZ_ERC1967Proxy_ConstructorAbi,\n args: [\n implementationAddress,\n encodeFunctionData({\n abi: LightAccountAbi_v1,\n functionName: \"initialize\",\n args: [ownerAddress],\n }),\n ],\n }),\n });\n\n case \"v2.0.0\":\n // Logic ported from LA factory v2.0.0\n const combinedSalt = keccak256(\n encodeAbiParameters(\n [{ type: \"address\" }, { type: \"uint256\" }],\n [ownerAddress, salt]\n )\n );\n\n const initCode: Hex = getLAv2ProxyBytecode(implementationAddress);\n\n return getContractAddress({\n from: factoryAddress,\n opcode: \"CREATE2\",\n salt: combinedSalt,\n bytecode: initCode,\n });\n\n default:\n assertNeverLightAccountVersion(version);\n }\n}\n\nexport type PredictMultiOwnerLightAccountAddressParams = {\n factoryAddress: Address;\n salt: bigint;\n ownerAddresses: Address[];\n // There's just one version of the MultiOwnerLightAccount for now, so skip requiring the version as a parameter.\n};\n\n// Note: assumes the owner addresses are already deduped, sorted in ascending order, and have the signer address included.\nexport function predictMultiOwnerLightAccountAddress({\n factoryAddress,\n salt,\n ownerAddresses,\n}: PredictMultiOwnerLightAccountAddressParams): Address {\n const implementationAddress =\n // If we aren't using the default factory address, we compute the implementation address from the factory's `create` deployment.\n // This is accurate for both LA v1 and v2 factories. If we are using the default factory address, we use the implementation address from the registry.\n factoryAddress !==\n AccountVersionRegistry.MultiOwnerLightAccount[\"v2.0.0\"].addresses.default\n .factory\n ? getContractAddress({\n from: factoryAddress,\n nonce: 1n,\n })\n : AccountVersionRegistry.MultiOwnerLightAccount[\"v2.0.0\"].addresses\n .default.impl;\n\n const combinedSalt = keccak256(\n encodeAbiParameters(\n [{ type: \"address[]\" }, { type: \"uint256\" }],\n [ownerAddresses, salt]\n )\n );\n\n const initCode: Hex = getLAv2ProxyBytecode(implementationAddress);\n\n return getContractAddress({\n from: factoryAddress,\n opcode: \"CREATE2\",\n salt: combinedSalt,\n bytecode: initCode,\n });\n}\n\n// Bytecode from https://github.com/Vectorized/solady/blob/c6e5238e5f3b621789c59e1a443f43b6606394b2/src/utils/LibClone.sol#L721\n\nfunction getLAv2ProxyBytecode(implementationAddress: Address): Hex {\n return `0x603d3d8160223d3973${implementationAddress.slice(\n 2\n )}60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3`;\n}\n\nfunction assertNeverLightAccountVersion(version: never): never {\n throw new Error(`Unknown light account version: ${version}`);\n}\n"]}
@@ -10,6 +10,7 @@ export type CreateModularAccountV2Params<TTransport extends Transport = Transpor
10
10
  mode?: "default";
11
11
  salt?: bigint;
12
12
  factoryAddress?: Address;
13
+ implementationAddress?: Address;
13
14
  initCode?: Hex;
14
15
  } | {
15
16
  mode: "7702";
@@ -1,9 +1,10 @@
1
- import { createBundlerClient, getEntryPoint, getAccountAddress, EntityIdOverrideError, InvalidModularAccountV2Mode, } from "@aa-sdk/core";
1
+ import { getEntryPoint, EntityIdOverrideError, InvalidModularAccountV2Mode, } from "@aa-sdk/core";
2
2
  import { concatHex, encodeFunctionData, } from "viem";
3
3
  import { accountFactoryAbi } from "../abis/accountFactoryAbi.js";
4
- import { getDefaultMAV2FactoryAddress } from "../utils.js";
4
+ import { getDefaultMAV2FactoryAddress, getDefaultSMAV2BytecodeAddress, } from "../utils.js";
5
5
  import { createMAv2Base, } from "./common/modularAccountV2Base.js";
6
6
  import { DEFAULT_OWNER_ENTITY_ID } from "../utils.js";
7
+ import { predictModularAccountV2Address } from "./predictAddress.js";
7
8
  /**
8
9
  * Creates a ModularAccount V2 account, with the mode depending on the provided "mode" field.
9
10
  * Possible modes include: "default", which is SMA Bytecode, and "7702", which is SMA 7702.
@@ -41,10 +42,6 @@ export async function createModularAccountV2(config) {
41
42
  isGlobalValidation: true,
42
43
  entityId: DEFAULT_OWNER_ENTITY_ID,
43
44
  }, signerEntity: { entityId = DEFAULT_OWNER_ENTITY_ID } = {}, deferredAction, } = config;
44
- const client = createBundlerClient({
45
- transport,
46
- chain,
47
- });
48
45
  const accountFunctions = await (async () => {
49
46
  switch (config.mode) {
50
47
  case "7702": {
@@ -67,7 +64,8 @@ export async function createModularAccountV2(config) {
67
64
  }
68
65
  case "default":
69
66
  case undefined: {
70
- const { salt = 0n, factoryAddress = getDefaultMAV2FactoryAddress(chain), initCode, } = config;
67
+ const { salt = 0n, factoryAddress = getDefaultMAV2FactoryAddress(chain), implementationAddress = getDefaultSMAV2BytecodeAddress(chain), initCode, } = config;
68
+ const signerAddress = await signer.getAddress();
71
69
  const getAccountInitCode = async () => {
72
70
  if (initCode) {
73
71
  return initCode;
@@ -77,16 +75,18 @@ export async function createModularAccountV2(config) {
77
75
  encodeFunctionData({
78
76
  abi: accountFactoryAbi,
79
77
  functionName: "createSemiModularAccount",
80
- args: [await signer.getAddress(), salt],
78
+ args: [signerAddress, salt],
81
79
  }),
82
80
  ]);
83
81
  };
84
- const accountAddress = await getAccountAddress({
85
- client,
86
- entryPoint,
87
- accountAddress: _accountAddress,
88
- getAccountInitCode,
89
- });
82
+ const accountAddress = _accountAddress ??
83
+ predictModularAccountV2Address({
84
+ factoryAddress,
85
+ implementationAddress,
86
+ salt,
87
+ type: "SMA",
88
+ ownerAddress: signerAddress,
89
+ });
90
90
  return {
91
91
  getAccountInitCode,
92
92
  accountAddress,
@@ -1 +1 @@
1
- {"version":3,"file":"modularAccountV2.js","sourceRoot":"","sources":["../../../../../src/ma-v2/account/modularAccountV2.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n EntryPointDef,\n SmartAccountSigner,\n ToSmartContractAccountParams,\n} from \"@aa-sdk/core\";\nimport {\n createBundlerClient,\n getEntryPoint,\n getAccountAddress,\n EntityIdOverrideError,\n InvalidModularAccountV2Mode,\n} from \"@aa-sdk/core\";\nimport {\n concatHex,\n encodeFunctionData,\n type Address,\n type Chain,\n type Hex,\n type Transport,\n} from \"viem\";\nimport { accountFactoryAbi } from \"../abis/accountFactoryAbi.js\";\nimport { getDefaultMAV2FactoryAddress } from \"../utils.js\";\nimport {\n type SignerEntity,\n type ModularAccountV2,\n createMAv2Base,\n} from \"./common/modularAccountV2Base.js\";\nimport { DEFAULT_OWNER_ENTITY_ID } from \"../utils.js\";\n\nexport type CreateModularAccountV2Params<\n TTransport extends Transport = Transport,\n TSigner extends SmartAccountSigner = SmartAccountSigner\n> = (Pick<\n ToSmartContractAccountParams<\"ModularAccountV2\", TTransport, Chain, \"0.7.0\">,\n \"transport\" | \"chain\" | \"accountAddress\"\n> & {\n signer: TSigner;\n entryPoint?: EntryPointDef<\"0.7.0\", Chain>;\n deferredAction?: Hex;\n signerEntity?: SignerEntity;\n}) &\n (\n | {\n mode?: \"default\";\n salt?: bigint;\n factoryAddress?: Address;\n initCode?: Hex;\n }\n | {\n mode: \"7702\";\n }\n );\n\nexport async function createModularAccountV2<\n TTransport extends Transport = Transport,\n TSigner extends SmartAccountSigner = SmartAccountSigner\n>(\n config: CreateModularAccountV2Params<TTransport, TSigner>\n): Promise<ModularAccountV2<TSigner>>;\n\n/**\n * Creates a ModularAccount V2 account, with the mode depending on the provided \"mode\" field.\n * Possible modes include: \"default\", which is SMA Bytecode, and \"7702\", which is SMA 7702.\n * Handles nonce generation, transaction encoding, and mode variant-specific behavior like initcode construction.\n *\n * @example\n * ```ts twoslash\n * import { createModularAccountV2 } from \"@account-kit/smart-contracts\";\n * import { LocalAccountSigner } from \"@aa-sdk/core\";\n * import { alchemy, sepolia } from \"@account-kit/infra\";\n *\n * const MNEMONIC = \"...\";\n * const RPC_URL = \"...\";\n *\n * const signer = LocalAccountSigner.mnemonicToAccountSigner(MNEMONIC);\n *\n * const chain = sepolia;\n *\n * const transport = alchemy({ rpcUrl: RPC_URL });\n *\n *\n * const modularAccountV2 = await createModularAccountV2({\n * mode: \"default\", // or \"7702\"\n * chain,\n * signer,\n * transport,\n * });\n * ```\n *\n * @param {CreateModularAccountV2Params} config Configuration parameters for creating a Modular Account V2.\n * @returns {Promise<ModularAccountV2>} A promise that resolves to an `ModularAccountV2` providing methods for nonce retrieval, transaction execution, and more.\n */\nexport async function createModularAccountV2(\n config: CreateModularAccountV2Params\n): Promise<ModularAccountV2> {\n const {\n transport,\n chain,\n signer,\n accountAddress: _accountAddress,\n entryPoint = getEntryPoint(chain, { version: \"0.7.0\" }),\n signerEntity = {\n isGlobalValidation: true,\n entityId: DEFAULT_OWNER_ENTITY_ID,\n },\n signerEntity: { entityId = DEFAULT_OWNER_ENTITY_ID } = {},\n deferredAction,\n } = config;\n\n const client = createBundlerClient({\n transport,\n chain,\n });\n\n const accountFunctions = await (async () => {\n switch (config.mode) {\n case \"7702\": {\n const getAccountInitCode = async (): Promise<Hex> => {\n return \"0x\";\n };\n const signerAddress = await signer.getAddress();\n const accountAddress = _accountAddress ?? signerAddress;\n if (\n entityId === DEFAULT_OWNER_ENTITY_ID &&\n signerAddress !== accountAddress\n ) {\n throw new EntityIdOverrideError();\n }\n\n const implementation: Address =\n \"0x69007702764179f14F51cdce752f4f775d74E139\";\n\n const getImplementationAddress = async () => implementation;\n\n return {\n getAccountInitCode,\n accountAddress,\n getImplementationAddress,\n };\n }\n case \"default\":\n case undefined: {\n const {\n salt = 0n,\n factoryAddress = getDefaultMAV2FactoryAddress(chain),\n initCode,\n } = config;\n\n const getAccountInitCode = async () => {\n if (initCode) {\n return initCode;\n }\n\n return concatHex([\n factoryAddress,\n encodeFunctionData({\n abi: accountFactoryAbi,\n functionName: \"createSemiModularAccount\",\n args: [await signer.getAddress(), salt],\n }),\n ]);\n };\n\n const accountAddress = await getAccountAddress({\n client,\n entryPoint,\n accountAddress: _accountAddress,\n getAccountInitCode,\n });\n\n return {\n getAccountInitCode,\n accountAddress,\n };\n }\n default:\n assertNever(config);\n }\n })();\n\n return createMAv2Base({\n source: \"ModularAccountV2\",\n transport,\n chain,\n signer,\n entryPoint,\n signerEntity,\n deferredAction,\n ...accountFunctions,\n });\n}\n\n// If we add more valid modes, the switch case branch's mode will no longer be `never`, which will cause a compile time error here and ensure we handle the new type.\nfunction assertNever(_valid: never): never {\n throw new InvalidModularAccountV2Mode();\n}\n"]}
1
+ {"version":3,"file":"modularAccountV2.js","sourceRoot":"","sources":["../../../../../src/ma-v2/account/modularAccountV2.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n EntryPointDef,\n SmartAccountSigner,\n ToSmartContractAccountParams,\n} from \"@aa-sdk/core\";\nimport {\n getEntryPoint,\n EntityIdOverrideError,\n InvalidModularAccountV2Mode,\n} from \"@aa-sdk/core\";\nimport {\n concatHex,\n encodeFunctionData,\n type Address,\n type Chain,\n type Hex,\n type Transport,\n} from \"viem\";\nimport { accountFactoryAbi } from \"../abis/accountFactoryAbi.js\";\nimport {\n getDefaultMAV2FactoryAddress,\n getDefaultSMAV2BytecodeAddress,\n} from \"../utils.js\";\nimport {\n type SignerEntity,\n type ModularAccountV2,\n createMAv2Base,\n} from \"./common/modularAccountV2Base.js\";\nimport { DEFAULT_OWNER_ENTITY_ID } from \"../utils.js\";\nimport { predictModularAccountV2Address } from \"./predictAddress.js\";\n\nexport type CreateModularAccountV2Params<\n TTransport extends Transport = Transport,\n TSigner extends SmartAccountSigner = SmartAccountSigner\n> = (Pick<\n ToSmartContractAccountParams<\"ModularAccountV2\", TTransport, Chain, \"0.7.0\">,\n \"transport\" | \"chain\" | \"accountAddress\"\n> & {\n signer: TSigner;\n entryPoint?: EntryPointDef<\"0.7.0\", Chain>;\n deferredAction?: Hex;\n signerEntity?: SignerEntity;\n}) &\n (\n | {\n mode?: \"default\";\n salt?: bigint;\n factoryAddress?: Address;\n implementationAddress?: Address;\n initCode?: Hex;\n }\n | {\n mode: \"7702\";\n }\n );\n\nexport async function createModularAccountV2<\n TTransport extends Transport = Transport,\n TSigner extends SmartAccountSigner = SmartAccountSigner\n>(\n config: CreateModularAccountV2Params<TTransport, TSigner>\n): Promise<ModularAccountV2<TSigner>>;\n\n/**\n * Creates a ModularAccount V2 account, with the mode depending on the provided \"mode\" field.\n * Possible modes include: \"default\", which is SMA Bytecode, and \"7702\", which is SMA 7702.\n * Handles nonce generation, transaction encoding, and mode variant-specific behavior like initcode construction.\n *\n * @example\n * ```ts twoslash\n * import { createModularAccountV2 } from \"@account-kit/smart-contracts\";\n * import { LocalAccountSigner } from \"@aa-sdk/core\";\n * import { alchemy, sepolia } from \"@account-kit/infra\";\n *\n * const MNEMONIC = \"...\";\n * const RPC_URL = \"...\";\n *\n * const signer = LocalAccountSigner.mnemonicToAccountSigner(MNEMONIC);\n *\n * const chain = sepolia;\n *\n * const transport = alchemy({ rpcUrl: RPC_URL });\n *\n *\n * const modularAccountV2 = await createModularAccountV2({\n * mode: \"default\", // or \"7702\"\n * chain,\n * signer,\n * transport,\n * });\n * ```\n *\n * @param {CreateModularAccountV2Params} config Configuration parameters for creating a Modular Account V2.\n * @returns {Promise<ModularAccountV2>} A promise that resolves to an `ModularAccountV2` providing methods for nonce retrieval, transaction execution, and more.\n */\nexport async function createModularAccountV2(\n config: CreateModularAccountV2Params\n): Promise<ModularAccountV2> {\n const {\n transport,\n chain,\n signer,\n accountAddress: _accountAddress,\n entryPoint = getEntryPoint(chain, { version: \"0.7.0\" }),\n signerEntity = {\n isGlobalValidation: true,\n entityId: DEFAULT_OWNER_ENTITY_ID,\n },\n signerEntity: { entityId = DEFAULT_OWNER_ENTITY_ID } = {},\n deferredAction,\n } = config;\n\n const accountFunctions = await (async () => {\n switch (config.mode) {\n case \"7702\": {\n const getAccountInitCode = async (): Promise<Hex> => {\n return \"0x\";\n };\n const signerAddress = await signer.getAddress();\n const accountAddress = _accountAddress ?? signerAddress;\n if (\n entityId === DEFAULT_OWNER_ENTITY_ID &&\n signerAddress !== accountAddress\n ) {\n throw new EntityIdOverrideError();\n }\n\n const implementation: Address =\n \"0x69007702764179f14F51cdce752f4f775d74E139\";\n\n const getImplementationAddress = async () => implementation;\n\n return {\n getAccountInitCode,\n accountAddress,\n getImplementationAddress,\n };\n }\n case \"default\":\n case undefined: {\n const {\n salt = 0n,\n factoryAddress = getDefaultMAV2FactoryAddress(chain),\n implementationAddress = getDefaultSMAV2BytecodeAddress(chain),\n initCode,\n } = config;\n\n const signerAddress = await signer.getAddress();\n\n const getAccountInitCode = async () => {\n if (initCode) {\n return initCode;\n }\n\n return concatHex([\n factoryAddress,\n encodeFunctionData({\n abi: accountFactoryAbi,\n functionName: \"createSemiModularAccount\",\n args: [signerAddress, salt],\n }),\n ]);\n };\n\n const accountAddress =\n _accountAddress ??\n predictModularAccountV2Address({\n factoryAddress,\n implementationAddress,\n salt,\n type: \"SMA\",\n ownerAddress: signerAddress,\n });\n\n return {\n getAccountInitCode,\n accountAddress,\n };\n }\n default:\n assertNever(config);\n }\n })();\n\n return createMAv2Base({\n source: \"ModularAccountV2\",\n transport,\n chain,\n signer,\n entryPoint,\n signerEntity,\n deferredAction,\n ...accountFunctions,\n });\n}\n\n// If we add more valid modes, the switch case branch's mode will no longer be `never`, which will cause a compile time error here and ensure we handle the new type.\nfunction assertNever(_valid: never): never {\n throw new InvalidModularAccountV2Mode();\n}\n"]}
@@ -0,0 +1,21 @@
1
+ import { type Address } from "viem";
2
+ export type PredictModularAccountV2AddressParams = {
3
+ factoryAddress: Address;
4
+ implementationAddress: Address;
5
+ salt: bigint;
6
+ } & ({
7
+ type: "MA";
8
+ ownerAddress: Address;
9
+ entityId: number;
10
+ } | {
11
+ type: "SMA";
12
+ ownerAddress: Address;
13
+ } | {
14
+ type: "WebAuthn";
15
+ ownerPublicKey: {
16
+ x: bigint;
17
+ y: bigint;
18
+ };
19
+ entityId: number;
20
+ });
21
+ export declare function predictModularAccountV2Address(params: PredictModularAccountV2AddressParams): Address;
@@ -0,0 +1,46 @@
1
+ import { encodePacked, getContractAddress, keccak256, } from "viem";
2
+ export function predictModularAccountV2Address(params) {
3
+ const { factoryAddress, salt, implementationAddress } = params;
4
+ let combinedSalt;
5
+ let initcode;
6
+ // Note: prediction for MA and WebAuthn is currently untested, because they are not supported as an account type yet.
7
+ // Prior to using this prediction logic, ensure that the counterfactual computation is correct by updating `predictAddress.test.ts` to include a test for MA and WebAuthn.
8
+ switch (params.type) {
9
+ case "SMA":
10
+ // MAv2 factory uses max uint32 for SMA entityId
11
+ combinedSalt = getCombinedSaltK1(params.ownerAddress, salt, 0xffffffff);
12
+ const immutableArgs = params.ownerAddress;
13
+ initcode = getProxyBytecodeWithImmutableArgs(implementationAddress, immutableArgs);
14
+ break;
15
+ case "MA":
16
+ combinedSalt = getCombinedSaltK1(params.ownerAddress, salt, params.entityId);
17
+ initcode = getProxyBytecode(implementationAddress);
18
+ break;
19
+ case "WebAuthn":
20
+ const { ownerPublicKey: { x, y }, } = params;
21
+ combinedSalt = keccak256(encodePacked(["uint256", "uint256", "uint256", "uint32"], [x, y, salt, params.entityId]));
22
+ initcode = getProxyBytecode(implementationAddress);
23
+ break;
24
+ default:
25
+ return assertNeverModularAccountV2Type(params);
26
+ }
27
+ return getContractAddress({
28
+ from: factoryAddress,
29
+ opcode: "CREATE2",
30
+ salt: combinedSalt,
31
+ bytecode: initcode,
32
+ });
33
+ }
34
+ function getCombinedSaltK1(ownerAddress, salt, entityId) {
35
+ return keccak256(encodePacked(["address", "uint256", "uint32"], [ownerAddress, salt, entityId]));
36
+ }
37
+ function getProxyBytecode(implementationAddress) {
38
+ return `0x603d3d8160223d3973${implementationAddress.slice(2)}60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3`;
39
+ }
40
+ function getProxyBytecodeWithImmutableArgs(implementationAddress, immutableArgs) {
41
+ return `0x6100513d8160233d3973${implementationAddress.slice(2)}60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3${immutableArgs.slice(2)}`;
42
+ }
43
+ function assertNeverModularAccountV2Type(_) {
44
+ throw new Error("Unknown modular account type in predictModularAccountV2Address");
45
+ }
46
+ //# sourceMappingURL=predictAddress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predictAddress.js","sourceRoot":"","sources":["../../../../../src/ma-v2/account/predictAddress.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,SAAS,GAGV,MAAM,MAAM,CAAC;AA0Bd,MAAM,UAAU,8BAA8B,CAC5C,MAA4C;IAE5C,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAAC;IAE/D,IAAI,YAAiB,CAAC;IACtB,IAAI,QAAa,CAAC;IAElB,qHAAqH;IACrH,0KAA0K;IAC1K,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,KAAK;YACR,gDAAgD;YAChD,YAAY,GAAG,iBAAiB,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;YACxE,MAAM,aAAa,GAAG,MAAM,CAAC,YAAY,CAAC;YAC1C,QAAQ,GAAG,iCAAiC,CAC1C,qBAAqB,EACrB,aAAa,CACd,CAAC;YACF,MAAM;QACR,KAAK,IAAI;YACP,YAAY,GAAG,iBAAiB,CAC9B,MAAM,CAAC,YAAY,EACnB,IAAI,EACJ,MAAM,CAAC,QAAQ,CAChB,CAAC;YAEF,QAAQ,GAAG,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;YACnD,MAAM;QACR,KAAK,UAAU;YACb,MAAM,EACJ,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GACzB,GAAG,MAAM,CAAC;YAEX,YAAY,GAAG,SAAS,CACtB,YAAY,CACV,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,EAC3C,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAC9B,CACF,CAAC;YAEF,QAAQ,GAAG,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;YAEnD,MAAM;QACR;YACE,OAAO,+BAA+B,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,kBAAkB,CAAC;QACxB,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,SAAS;QACjB,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,QAAQ;KACnB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CACxB,YAAqB,EACrB,IAAY,EACZ,QAAgB;IAEhB,OAAO,SAAS,CACd,YAAY,CACV,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,EAChC,CAAC,YAAY,EAAE,IAAI,EAAE,QAAQ,CAAC,CAC/B,CACF,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,qBAA8B;IACtD,OAAO,uBAAuB,qBAAqB,CAAC,KAAK,CACvD,CAAC,CACF,sIAAsI,CAAC;AAC1I,CAAC;AAED,SAAS,iCAAiC,CACxC,qBAA8B,EAC9B,aAAkB;IAElB,OAAO,yBAAyB,qBAAqB,CAAC,KAAK,CACzD,CAAC,CACF,uIAAuI,aAAa,CAAC,KAAK,CACzJ,CAAC,CACF,EAAE,CAAC;AACN,CAAC;AAED,SAAS,+BAA+B,CAAC,CAAQ;IAC/C,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE,CAAC;AACJ,CAAC","sourcesContent":["import {\n encodePacked,\n getContractAddress,\n keccak256,\n type Address,\n type Hex,\n} from \"viem\";\n\nexport type PredictModularAccountV2AddressParams = {\n factoryAddress: Address;\n implementationAddress: Address; // Should be the implementation address of the account type you are predicting the address for.\n salt: bigint;\n} & (\n | {\n type: \"MA\";\n ownerAddress: Address;\n entityId: number;\n }\n | {\n type: \"SMA\";\n ownerAddress: Address;\n }\n | {\n type: \"WebAuthn\";\n ownerPublicKey: {\n x: bigint;\n y: bigint;\n };\n entityId: number;\n }\n);\n\nexport function predictModularAccountV2Address(\n params: PredictModularAccountV2AddressParams\n): Address {\n const { factoryAddress, salt, implementationAddress } = params;\n\n let combinedSalt: Hex;\n let initcode: Hex;\n\n // Note: prediction for MA and WebAuthn is currently untested, because they are not supported as an account type yet.\n // Prior to using this prediction logic, ensure that the counterfactual computation is correct by updating `predictAddress.test.ts` to include a test for MA and WebAuthn.\n switch (params.type) {\n case \"SMA\":\n // MAv2 factory uses max uint32 for SMA entityId\n combinedSalt = getCombinedSaltK1(params.ownerAddress, salt, 0xffffffff);\n const immutableArgs = params.ownerAddress;\n initcode = getProxyBytecodeWithImmutableArgs(\n implementationAddress,\n immutableArgs\n );\n break;\n case \"MA\":\n combinedSalt = getCombinedSaltK1(\n params.ownerAddress,\n salt,\n params.entityId\n );\n\n initcode = getProxyBytecode(implementationAddress);\n break;\n case \"WebAuthn\":\n const {\n ownerPublicKey: { x, y },\n } = params;\n\n combinedSalt = keccak256(\n encodePacked(\n [\"uint256\", \"uint256\", \"uint256\", \"uint32\"],\n [x, y, salt, params.entityId]\n )\n );\n\n initcode = getProxyBytecode(implementationAddress);\n\n break;\n default:\n return assertNeverModularAccountV2Type(params);\n }\n\n return getContractAddress({\n from: factoryAddress,\n opcode: \"CREATE2\",\n salt: combinedSalt,\n bytecode: initcode,\n });\n}\n\nfunction getCombinedSaltK1(\n ownerAddress: Address,\n salt: bigint,\n entityId: number\n): Hex {\n return keccak256(\n encodePacked(\n [\"address\", \"uint256\", \"uint32\"],\n [ownerAddress, salt, entityId]\n )\n );\n}\n\nfunction getProxyBytecode(implementationAddress: Address): Hex {\n return `0x603d3d8160223d3973${implementationAddress.slice(\n 2\n )}60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3`;\n}\n\nfunction getProxyBytecodeWithImmutableArgs(\n implementationAddress: Address,\n immutableArgs: Hex\n): Hex {\n return `0x6100513d8160233d3973${implementationAddress.slice(\n 2\n )}60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3${immutableArgs.slice(\n 2\n )}`;\n}\n\nfunction assertNeverModularAccountV2Type(_: never): never {\n throw new Error(\n \"Unknown modular account type in predictModularAccountV2Address\"\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"multiOwner.d.ts","sourceRoot":"","sources":["../../../../../src/light-account/accounts/multiOwner.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EAIL,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,GAAG,EACR,KAAK,SAAS,EACf,MAAM,MAAM,CAAC;AAGd,OAAO,KAAK,EACV,6BAA6B,EAC7B,mBAAmB,EACpB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,gBAAgB,EACtB,MAAM,WAAW,CAAC;AAEnB,MAAM,MAAM,sBAAsB,CAChC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,EACvD,oBAAoB,SAAS,mBAAmB,CAAC,wBAAwB,CAAC,GAAG,mBAAmB,CAAC,wBAAwB,CAAC,IACxH,gBAAgB,CAClB,OAAO,EACP,wBAAwB,EACxB,oBAAoB,CACrB,GAAG;IACF,kBAAkB,EAAE,CAClB,WAAW,EAAE,OAAO,EAAE,EACtB,cAAc,EAAE,OAAO,EAAE,KACtB,GAAG,CAAC;IACT,iBAAiB,EAAE,MAAM,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;CACtD,CAAC;AAEF,MAAM,MAAM,kCAAkC,CAC5C,UAAU,SAAS,SAAS,GAAG,SAAS,EACxC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,EACvD,oBAAoB,SAAS,mBAAmB,CAAC,wBAAwB,CAAC,GAAG,mBAAmB,CAAC,wBAAwB,CAAC,IACxH,IAAI,CACN,4BAA4B,CAC1B,wBAAwB,EACxB,oBAAoB,EACpB,UAAU,EACV,OAAO,CACR,EACC,oBAAoB,GACpB,YAAY,GACZ,SAAS,GACT,KAAK,GACL,gBAAgB,GAChB,MAAM,CACT,GAAG;IACF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,UAAU,CAAC,EAAE,aAAa,CACxB,6BAA6B,CAC3B,wBAAwB,EACxB,oBAAoB,CACrB,EACD,KAAK,CACN,CAAC;IACF,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB,CAAC;AAEF,wBAAsB,4BAA4B,CAChD,UAAU,SAAS,SAAS,GAAG,SAAS,EACxC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,EACvD,oBAAoB,SAAS,mBAAmB,CAAC,wBAAwB,CAAC,GAAG,mBAAmB,CAAC,wBAAwB,CAAC,EAE1H,MAAM,EAAE,kCAAkC,CACxC,UAAU,EACV,OAAO,EACP,oBAAoB,CACrB,GACA,OAAO,CAAC,sBAAsB,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"multiOwner.d.ts","sourceRoot":"","sources":["../../../../../src/light-account/accounts/multiOwner.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EAIL,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,GAAG,EACR,KAAK,SAAS,EACf,MAAM,MAAM,CAAC;AAGd,OAAO,KAAK,EACV,6BAA6B,EAC7B,mBAAmB,EACpB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,gBAAgB,EACtB,MAAM,WAAW,CAAC;AAGnB,MAAM,MAAM,sBAAsB,CAChC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,EACvD,oBAAoB,SAAS,mBAAmB,CAAC,wBAAwB,CAAC,GAAG,mBAAmB,CAAC,wBAAwB,CAAC,IACxH,gBAAgB,CAClB,OAAO,EACP,wBAAwB,EACxB,oBAAoB,CACrB,GAAG;IACF,kBAAkB,EAAE,CAClB,WAAW,EAAE,OAAO,EAAE,EACtB,cAAc,EAAE,OAAO,EAAE,KACtB,GAAG,CAAC;IACT,iBAAiB,EAAE,MAAM,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;CACtD,CAAC;AAEF,MAAM,MAAM,kCAAkC,CAC5C,UAAU,SAAS,SAAS,GAAG,SAAS,EACxC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,EACvD,oBAAoB,SAAS,mBAAmB,CAAC,wBAAwB,CAAC,GAAG,mBAAmB,CAAC,wBAAwB,CAAC,IACxH,IAAI,CACN,4BAA4B,CAC1B,wBAAwB,EACxB,oBAAoB,EACpB,UAAU,EACV,OAAO,CACR,EACC,oBAAoB,GACpB,YAAY,GACZ,SAAS,GACT,KAAK,GACL,gBAAgB,GAChB,MAAM,CACT,GAAG;IACF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,UAAU,CAAC,EAAE,aAAa,CACxB,6BAA6B,CAC3B,wBAAwB,EACxB,oBAAoB,CACrB,EACD,KAAK,CACN,CAAC;IACF,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB,CAAC;AAEF,wBAAsB,4BAA4B,CAChD,UAAU,SAAS,SAAS,GAAG,SAAS,EACxC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,EACvD,oBAAoB,SAAS,mBAAmB,CAAC,wBAAwB,CAAC,GAAG,mBAAmB,CAAC,wBAAwB,CAAC,EAE1H,MAAM,EAAE,kCAAkC,CACxC,UAAU,EACV,OAAO,EACP,oBAAoB,CACrB,GACA,OAAO,CAAC,sBAAsB,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC"}
@@ -3,8 +3,14 @@ import type { LightAccountVersionConfigs } from "../types";
3
3
  export type PredictLightAccountAddressParams = {
4
4
  factoryAddress: Address;
5
5
  salt: bigint;
6
- signerAddress: Address;
6
+ ownerAddress: Address;
7
7
  version: keyof LightAccountVersionConfigs["LightAccount"];
8
8
  };
9
- export declare function predictLightAccountAddress({ factoryAddress, salt, signerAddress, version, }: PredictLightAccountAddressParams): Address;
9
+ export declare function predictLightAccountAddress({ factoryAddress, salt, ownerAddress, version, }: PredictLightAccountAddressParams): Address;
10
+ export type PredictMultiOwnerLightAccountAddressParams = {
11
+ factoryAddress: Address;
12
+ salt: bigint;
13
+ ownerAddresses: Address[];
14
+ };
15
+ export declare function predictMultiOwnerLightAccountAddress({ factoryAddress, salt, ownerAddresses, }: PredictMultiOwnerLightAccountAddressParams): Address;
10
16
  //# sourceMappingURL=predictAddress.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"predictAddress.d.ts","sourceRoot":"","sources":["../../../../../src/light-account/accounts/predictAddress.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,OAAO,EAIb,MAAM,MAAM,CAAC;AACd,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAK3D,MAAM,MAAM,gCAAgC,GAAG;IAC7C,cAAc,EAAE,OAAO,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,0BAA0B,CAAC,cAAc,CAAC,CAAC;CAC3D,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,EACzC,cAAc,EACd,IAAI,EACJ,aAAa,EACb,OAAO,GACR,EAAE,gCAAgC,GAAG,OAAO,CA+D5C"}
1
+ {"version":3,"file":"predictAddress.d.ts","sourceRoot":"","sources":["../../../../../src/light-account/accounts/predictAddress.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,OAAO,EAIb,MAAM,MAAM,CAAC;AACd,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAK3D,MAAM,MAAM,gCAAgC,GAAG;IAC7C,cAAc,EAAE,OAAO,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,MAAM,0BAA0B,CAAC,cAAc,CAAC,CAAC;CAC3D,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,EACzC,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,OAAO,GACR,EAAE,gCAAgC,GAAG,OAAO,CA2D5C;AAED,MAAM,MAAM,0CAA0C,GAAG;IACvD,cAAc,EAAE,OAAO,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,OAAO,EAAE,CAAC;CAE3B,CAAC;AAGF,wBAAgB,oCAAoC,CAAC,EACnD,cAAc,EACd,IAAI,EACJ,cAAc,GACf,EAAE,0CAA0C,GAAG,OAAO,CA6BtD"}
@@ -10,6 +10,7 @@ export type CreateModularAccountV2Params<TTransport extends Transport = Transpor
10
10
  mode?: "default";
11
11
  salt?: bigint;
12
12
  factoryAddress?: Address;
13
+ implementationAddress?: Address;
13
14
  initCode?: Hex;
14
15
  } | {
15
16
  mode: "7702";
@@ -1 +1 @@
1
- {"version":3,"file":"modularAccountV2.d.ts","sourceRoot":"","sources":["../../../../../src/ma-v2/account/modularAccountV2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,4BAA4B,EAC7B,MAAM,cAAc,CAAC;AAQtB,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,GAAG,EACR,KAAK,SAAS,EACf,MAAM,MAAM,CAAC;AAGd,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAEtB,MAAM,kCAAkC,CAAC;AAG1C,MAAM,MAAM,4BAA4B,CACtC,UAAU,SAAS,SAAS,GAAG,SAAS,EACxC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,IACrD,CAAC,IAAI,CACP,4BAA4B,CAAC,kBAAkB,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,CAAC,EAC5E,WAAW,GAAG,OAAO,GAAG,gBAAgB,CACzC,GAAG;IACF,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC3C,cAAc,CAAC,EAAE,GAAG,CAAC;IACrB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC,GACA,CACI;IACE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,GAAG,CAAC;CAChB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;CACd,CACJ,CAAC;AAEJ,wBAAsB,sBAAsB,CAC1C,UAAU,SAAS,SAAS,GAAG,SAAS,EACxC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,EAEvD,MAAM,EAAE,4BAA4B,CAAC,UAAU,EAAE,OAAO,CAAC,GACxD,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"modularAccountV2.d.ts","sourceRoot":"","sources":["../../../../../src/ma-v2/account/modularAccountV2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,4BAA4B,EAC7B,MAAM,cAAc,CAAC;AAMtB,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,GAAG,EACR,KAAK,SAAS,EACf,MAAM,MAAM,CAAC;AAMd,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAEtB,MAAM,kCAAkC,CAAC;AAI1C,MAAM,MAAM,4BAA4B,CACtC,UAAU,SAAS,SAAS,GAAG,SAAS,EACxC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,IACrD,CAAC,IAAI,CACP,4BAA4B,CAAC,kBAAkB,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,CAAC,EAC5E,WAAW,GAAG,OAAO,GAAG,gBAAgB,CACzC,GAAG;IACF,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC3C,cAAc,CAAC,EAAE,GAAG,CAAC;IACrB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC,GACA,CACI;IACE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,EAAE,GAAG,CAAC;CAChB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;CACd,CACJ,CAAC;AAEJ,wBAAsB,sBAAsB,CAC1C,UAAU,SAAS,SAAS,GAAG,SAAS,EACxC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,EAEvD,MAAM,EAAE,4BAA4B,CAAC,UAAU,EAAE,OAAO,CAAC,GACxD,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { type Address } from "viem";
2
+ export type PredictModularAccountV2AddressParams = {
3
+ factoryAddress: Address;
4
+ implementationAddress: Address;
5
+ salt: bigint;
6
+ } & ({
7
+ type: "MA";
8
+ ownerAddress: Address;
9
+ entityId: number;
10
+ } | {
11
+ type: "SMA";
12
+ ownerAddress: Address;
13
+ } | {
14
+ type: "WebAuthn";
15
+ ownerPublicKey: {
16
+ x: bigint;
17
+ y: bigint;
18
+ };
19
+ entityId: number;
20
+ });
21
+ export declare function predictModularAccountV2Address(params: PredictModularAccountV2AddressParams): Address;
22
+ //# sourceMappingURL=predictAddress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predictAddress.d.ts","sourceRoot":"","sources":["../../../../../src/ma-v2/account/predictAddress.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,OAAO,EAEb,MAAM,MAAM,CAAC;AAEd,MAAM,MAAM,oCAAoC,GAAG;IACjD,cAAc,EAAE,OAAO,CAAC;IACxB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,CACA;IACE,IAAI,EAAE,IAAI,CAAC;IACX,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB,GACD;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,YAAY,EAAE,OAAO,CAAC;CACvB,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,cAAc,EAAE;QACd,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;KACX,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC;CAClB,CACJ,CAAC;AAEF,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,oCAAoC,GAC3C,OAAO,CAoDT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@account-kit/smart-contracts",
3
- "version": "4.33.0",
3
+ "version": "4.34.0",
4
4
  "description": "aa-sdk compatible interfaces for Alchemy Smart Accounts",
5
5
  "author": "Alchemy",
6
6
  "license": "MIT",
@@ -52,7 +52,7 @@
52
52
  "test:run": "vitest run"
53
53
  },
54
54
  "devDependencies": {
55
- "@account-kit/plugingen": "^4.33.0",
55
+ "@account-kit/plugingen": "^4.34.0",
56
56
  "change-case": "^5.1.2",
57
57
  "dedent": "^1.5.1",
58
58
  "dotenv": "^16.3.1",
@@ -72,10 +72,10 @@
72
72
  "url": "https://github.com/alchemyplatform/aa-sdk/issues"
73
73
  },
74
74
  "homepage": "https://github.com/alchemyplatform/aa-sdk#readme",
75
- "gitHead": "ef2c269bcfa2115b6103f342ac4d846f1b4db991",
75
+ "gitHead": "99f4944de3a220aa9603d90b56f26cde9774e53f",
76
76
  "dependencies": {
77
- "@aa-sdk/core": "^4.33.0",
78
- "@account-kit/infra": "^4.33.0"
77
+ "@aa-sdk/core": "^4.34.0",
78
+ "@account-kit/infra": "^4.34.0"
79
79
  },
80
80
  "peerDependencies": {
81
81
  "viem": "^2.29.2"
@@ -152,7 +152,7 @@ export async function createLightAccount({
152
152
  predictLightAccountAddress({
153
153
  factoryAddress,
154
154
  salt,
155
- signerAddress,
155
+ ownerAddress: signerAddress,
156
156
  version,
157
157
  });
158
158
 
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  createBundlerClient,
3
- getAccountAddress,
4
3
  getEntryPoint,
5
4
  type EntryPointDef,
6
5
  type SmartAccountSigner,
@@ -29,6 +28,7 @@ import {
29
28
  type CreateLightAccountBaseParams,
30
29
  type LightAccountBase,
31
30
  } from "./base.js";
31
+ import { predictMultiOwnerLightAccountAddress } from "./predictAddress.js";
32
32
 
33
33
  export type MultiOwnerLightAccount<
34
34
  TSigner extends SmartAccountSigner = SmartAccountSigner,
@@ -132,20 +132,20 @@ export async function createMultiOwnerLightAccount({
132
132
  chain,
133
133
  });
134
134
 
135
- const getAccountInitCode = async () => {
136
- if (initCode) return initCode;
135
+ // NOTE: the current signer connected will be one of the owners as well
136
+ const ownerAddress = await signer.getAddress();
137
+ // owners need to be dedupe + ordered in ascending order and not == to zero address
138
+ const owners_ = Array.from(new Set([...owners, ownerAddress]))
139
+ .filter((x) => hexToBigInt(x) !== 0n)
140
+ .sort((a, b) => {
141
+ const bigintA = hexToBigInt(a);
142
+ const bigintB = hexToBigInt(b);
137
143
 
138
- // NOTE: the current signer connected will be one of the owners as well
139
- const ownerAddress = await signer.getAddress();
140
- // owners need to be dedupe + ordered in ascending order and not == to zero address
141
- const owners_ = Array.from(new Set([...owners, ownerAddress]))
142
- .filter((x) => hexToBigInt(x) !== 0n)
143
- .sort((a, b) => {
144
- const bigintA = hexToBigInt(a);
145
- const bigintB = hexToBigInt(b);
144
+ return bigintA < bigintB ? -1 : bigintA > bigintB ? 1 : 0;
145
+ });
146
146
 
147
- return bigintA < bigintB ? -1 : bigintA > bigintB ? 1 : 0;
148
- });
147
+ const getAccountInitCode = async () => {
148
+ if (initCode) return initCode;
149
149
 
150
150
  return concatHex([
151
151
  factoryAddress,
@@ -157,12 +157,13 @@ export async function createMultiOwnerLightAccount({
157
157
  ]);
158
158
  };
159
159
 
160
- const address = await getAccountAddress({
161
- client,
162
- entryPoint,
163
- accountAddress,
164
- getAccountInitCode,
165
- });
160
+ const address =
161
+ accountAddress ??
162
+ predictMultiOwnerLightAccountAddress({
163
+ factoryAddress,
164
+ salt: salt_,
165
+ ownerAddresses: owners_,
166
+ });
166
167
 
167
168
  const account = await createLightAccountBase<
168
169
  "MultiOwnerLightAccount",
@@ -16,14 +16,14 @@ import { LightAccountAbi_v1 } from "../abis/LightAccountAbi_v1.js";
16
16
  export type PredictLightAccountAddressParams = {
17
17
  factoryAddress: Address;
18
18
  salt: bigint;
19
- signerAddress: Address;
19
+ ownerAddress: Address;
20
20
  version: keyof LightAccountVersionConfigs["LightAccount"];
21
21
  };
22
22
 
23
23
  export function predictLightAccountAddress({
24
24
  factoryAddress,
25
25
  salt,
26
- signerAddress,
26
+ ownerAddress,
27
27
  version,
28
28
  }: PredictLightAccountAddressParams): Address {
29
29
  const implementationAddress =
@@ -57,7 +57,7 @@ export function predictLightAccountAddress({
57
57
  encodeFunctionData({
58
58
  abi: LightAccountAbi_v1,
59
59
  functionName: "initialize",
60
- args: [signerAddress],
60
+ args: [ownerAddress],
61
61
  }),
62
62
  ],
63
63
  }),
@@ -68,15 +68,11 @@ export function predictLightAccountAddress({
68
68
  const combinedSalt = keccak256(
69
69
  encodeAbiParameters(
70
70
  [{ type: "address" }, { type: "uint256" }],
71
- [signerAddress, salt]
71
+ [ownerAddress, salt]
72
72
  )
73
73
  );
74
74
 
75
- // Bytecode from https://github.com/Vectorized/solady/blob/c6e5238e5f3b621789c59e1a443f43b6606394b2/src/utils/LibClone.sol#L721
76
-
77
- const initCode: Hex = `0x603d3d8160223d3973${implementationAddress.slice(
78
- 2
79
- )}60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3`;
75
+ const initCode: Hex = getLAv2ProxyBytecode(implementationAddress);
80
76
 
81
77
  return getContractAddress({
82
78
  from: factoryAddress,
@@ -90,6 +86,57 @@ export function predictLightAccountAddress({
90
86
  }
91
87
  }
92
88
 
89
+ export type PredictMultiOwnerLightAccountAddressParams = {
90
+ factoryAddress: Address;
91
+ salt: bigint;
92
+ ownerAddresses: Address[];
93
+ // There's just one version of the MultiOwnerLightAccount for now, so skip requiring the version as a parameter.
94
+ };
95
+
96
+ // Note: assumes the owner addresses are already deduped, sorted in ascending order, and have the signer address included.
97
+ export function predictMultiOwnerLightAccountAddress({
98
+ factoryAddress,
99
+ salt,
100
+ ownerAddresses,
101
+ }: PredictMultiOwnerLightAccountAddressParams): Address {
102
+ const implementationAddress =
103
+ // If we aren't using the default factory address, we compute the implementation address from the factory's `create` deployment.
104
+ // This is accurate for both LA v1 and v2 factories. If we are using the default factory address, we use the implementation address from the registry.
105
+ factoryAddress !==
106
+ AccountVersionRegistry.MultiOwnerLightAccount["v2.0.0"].addresses.default
107
+ .factory
108
+ ? getContractAddress({
109
+ from: factoryAddress,
110
+ nonce: 1n,
111
+ })
112
+ : AccountVersionRegistry.MultiOwnerLightAccount["v2.0.0"].addresses
113
+ .default.impl;
114
+
115
+ const combinedSalt = keccak256(
116
+ encodeAbiParameters(
117
+ [{ type: "address[]" }, { type: "uint256" }],
118
+ [ownerAddresses, salt]
119
+ )
120
+ );
121
+
122
+ const initCode: Hex = getLAv2ProxyBytecode(implementationAddress);
123
+
124
+ return getContractAddress({
125
+ from: factoryAddress,
126
+ opcode: "CREATE2",
127
+ salt: combinedSalt,
128
+ bytecode: initCode,
129
+ });
130
+ }
131
+
132
+ // Bytecode from https://github.com/Vectorized/solady/blob/c6e5238e5f3b621789c59e1a443f43b6606394b2/src/utils/LibClone.sol#L721
133
+
134
+ function getLAv2ProxyBytecode(implementationAddress: Address): Hex {
135
+ return `0x603d3d8160223d3973${implementationAddress.slice(
136
+ 2
137
+ )}60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3`;
138
+ }
139
+
93
140
  function assertNeverLightAccountVersion(version: never): never {
94
141
  throw new Error(`Unknown light account version: ${version}`);
95
142
  }
@@ -4,9 +4,7 @@ import type {
4
4
  ToSmartContractAccountParams,
5
5
  } from "@aa-sdk/core";
6
6
  import {
7
- createBundlerClient,
8
7
  getEntryPoint,
9
- getAccountAddress,
10
8
  EntityIdOverrideError,
11
9
  InvalidModularAccountV2Mode,
12
10
  } from "@aa-sdk/core";
@@ -19,13 +17,17 @@ import {
19
17
  type Transport,
20
18
  } from "viem";
21
19
  import { accountFactoryAbi } from "../abis/accountFactoryAbi.js";
22
- import { getDefaultMAV2FactoryAddress } from "../utils.js";
20
+ import {
21
+ getDefaultMAV2FactoryAddress,
22
+ getDefaultSMAV2BytecodeAddress,
23
+ } from "../utils.js";
23
24
  import {
24
25
  type SignerEntity,
25
26
  type ModularAccountV2,
26
27
  createMAv2Base,
27
28
  } from "./common/modularAccountV2Base.js";
28
29
  import { DEFAULT_OWNER_ENTITY_ID } from "../utils.js";
30
+ import { predictModularAccountV2Address } from "./predictAddress.js";
29
31
 
30
32
  export type CreateModularAccountV2Params<
31
33
  TTransport extends Transport = Transport,
@@ -44,6 +46,7 @@ export type CreateModularAccountV2Params<
44
46
  mode?: "default";
45
47
  salt?: bigint;
46
48
  factoryAddress?: Address;
49
+ implementationAddress?: Address;
47
50
  initCode?: Hex;
48
51
  }
49
52
  | {
@@ -107,11 +110,6 @@ export async function createModularAccountV2(
107
110
  deferredAction,
108
111
  } = config;
109
112
 
110
- const client = createBundlerClient({
111
- transport,
112
- chain,
113
- });
114
-
115
113
  const accountFunctions = await (async () => {
116
114
  switch (config.mode) {
117
115
  case "7702": {
@@ -143,9 +141,12 @@ export async function createModularAccountV2(
143
141
  const {
144
142
  salt = 0n,
145
143
  factoryAddress = getDefaultMAV2FactoryAddress(chain),
144
+ implementationAddress = getDefaultSMAV2BytecodeAddress(chain),
146
145
  initCode,
147
146
  } = config;
148
147
 
148
+ const signerAddress = await signer.getAddress();
149
+
149
150
  const getAccountInitCode = async () => {
150
151
  if (initCode) {
151
152
  return initCode;
@@ -156,17 +157,20 @@ export async function createModularAccountV2(
156
157
  encodeFunctionData({
157
158
  abi: accountFactoryAbi,
158
159
  functionName: "createSemiModularAccount",
159
- args: [await signer.getAddress(), salt],
160
+ args: [signerAddress, salt],
160
161
  }),
161
162
  ]);
162
163
  };
163
164
 
164
- const accountAddress = await getAccountAddress({
165
- client,
166
- entryPoint,
167
- accountAddress: _accountAddress,
168
- getAccountInitCode,
169
- });
165
+ const accountAddress =
166
+ _accountAddress ??
167
+ predictModularAccountV2Address({
168
+ factoryAddress,
169
+ implementationAddress,
170
+ salt,
171
+ type: "SMA",
172
+ ownerAddress: signerAddress,
173
+ });
170
174
 
171
175
  return {
172
176
  getAccountInitCode,
@@ -0,0 +1,123 @@
1
+ import {
2
+ encodePacked,
3
+ getContractAddress,
4
+ keccak256,
5
+ type Address,
6
+ type Hex,
7
+ } from "viem";
8
+
9
+ export type PredictModularAccountV2AddressParams = {
10
+ factoryAddress: Address;
11
+ implementationAddress: Address; // Should be the implementation address of the account type you are predicting the address for.
12
+ salt: bigint;
13
+ } & (
14
+ | {
15
+ type: "MA";
16
+ ownerAddress: Address;
17
+ entityId: number;
18
+ }
19
+ | {
20
+ type: "SMA";
21
+ ownerAddress: Address;
22
+ }
23
+ | {
24
+ type: "WebAuthn";
25
+ ownerPublicKey: {
26
+ x: bigint;
27
+ y: bigint;
28
+ };
29
+ entityId: number;
30
+ }
31
+ );
32
+
33
+ export function predictModularAccountV2Address(
34
+ params: PredictModularAccountV2AddressParams
35
+ ): Address {
36
+ const { factoryAddress, salt, implementationAddress } = params;
37
+
38
+ let combinedSalt: Hex;
39
+ let initcode: Hex;
40
+
41
+ // Note: prediction for MA and WebAuthn is currently untested, because they are not supported as an account type yet.
42
+ // Prior to using this prediction logic, ensure that the counterfactual computation is correct by updating `predictAddress.test.ts` to include a test for MA and WebAuthn.
43
+ switch (params.type) {
44
+ case "SMA":
45
+ // MAv2 factory uses max uint32 for SMA entityId
46
+ combinedSalt = getCombinedSaltK1(params.ownerAddress, salt, 0xffffffff);
47
+ const immutableArgs = params.ownerAddress;
48
+ initcode = getProxyBytecodeWithImmutableArgs(
49
+ implementationAddress,
50
+ immutableArgs
51
+ );
52
+ break;
53
+ case "MA":
54
+ combinedSalt = getCombinedSaltK1(
55
+ params.ownerAddress,
56
+ salt,
57
+ params.entityId
58
+ );
59
+
60
+ initcode = getProxyBytecode(implementationAddress);
61
+ break;
62
+ case "WebAuthn":
63
+ const {
64
+ ownerPublicKey: { x, y },
65
+ } = params;
66
+
67
+ combinedSalt = keccak256(
68
+ encodePacked(
69
+ ["uint256", "uint256", "uint256", "uint32"],
70
+ [x, y, salt, params.entityId]
71
+ )
72
+ );
73
+
74
+ initcode = getProxyBytecode(implementationAddress);
75
+
76
+ break;
77
+ default:
78
+ return assertNeverModularAccountV2Type(params);
79
+ }
80
+
81
+ return getContractAddress({
82
+ from: factoryAddress,
83
+ opcode: "CREATE2",
84
+ salt: combinedSalt,
85
+ bytecode: initcode,
86
+ });
87
+ }
88
+
89
+ function getCombinedSaltK1(
90
+ ownerAddress: Address,
91
+ salt: bigint,
92
+ entityId: number
93
+ ): Hex {
94
+ return keccak256(
95
+ encodePacked(
96
+ ["address", "uint256", "uint32"],
97
+ [ownerAddress, salt, entityId]
98
+ )
99
+ );
100
+ }
101
+
102
+ function getProxyBytecode(implementationAddress: Address): Hex {
103
+ return `0x603d3d8160223d3973${implementationAddress.slice(
104
+ 2
105
+ )}60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3`;
106
+ }
107
+
108
+ function getProxyBytecodeWithImmutableArgs(
109
+ implementationAddress: Address,
110
+ immutableArgs: Hex
111
+ ): Hex {
112
+ return `0x6100513d8160233d3973${implementationAddress.slice(
113
+ 2
114
+ )}60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3${immutableArgs.slice(
115
+ 2
116
+ )}`;
117
+ }
118
+
119
+ function assertNeverModularAccountV2Type(_: never): never {
120
+ throw new Error(
121
+ "Unknown modular account type in predictModularAccountV2Address"
122
+ );
123
+ }