@metamask-previews/multichain-account-service 0.3.0-preview-0910ff0 → 0.3.0-preview-43d47013
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.
- package/CHANGELOG.md +15 -0
- package/dist/MultichainAccountGroup.cjs +192 -0
- package/dist/MultichainAccountGroup.cjs.map +1 -0
- package/dist/MultichainAccountGroup.d.cts +84 -0
- package/dist/MultichainAccountGroup.d.cts.map +1 -0
- package/dist/MultichainAccountGroup.d.mts +84 -0
- package/dist/MultichainAccountGroup.d.mts.map +1 -0
- package/dist/MultichainAccountGroup.mjs +188 -0
- package/dist/MultichainAccountGroup.mjs.map +1 -0
- package/dist/MultichainAccountService.cjs +36 -23
- package/dist/MultichainAccountService.cjs.map +1 -1
- package/dist/MultichainAccountService.d.cts +26 -15
- package/dist/MultichainAccountService.d.cts.map +1 -1
- package/dist/MultichainAccountService.d.mts +26 -15
- package/dist/MultichainAccountService.d.mts.map +1 -1
- package/dist/MultichainAccountService.mjs +35 -22
- package/dist/MultichainAccountService.mjs.map +1 -1
- package/dist/MultichainAccountWallet.cjs +237 -0
- package/dist/MultichainAccountWallet.cjs.map +1 -0
- package/dist/MultichainAccountWallet.d.cts +91 -0
- package/dist/MultichainAccountWallet.d.cts.map +1 -0
- package/dist/MultichainAccountWallet.d.mts +91 -0
- package/dist/MultichainAccountWallet.d.mts.map +1 -0
- package/dist/MultichainAccountWallet.mjs +233 -0
- package/dist/MultichainAccountWallet.mjs.map +1 -0
- package/dist/index.cjs +5 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -1
- package/dist/providers/BaseAccountProvider.cjs +20 -1
- package/dist/providers/BaseAccountProvider.cjs.map +1 -1
- package/dist/providers/BaseAccountProvider.d.cts +25 -5
- package/dist/providers/BaseAccountProvider.d.cts.map +1 -1
- package/dist/providers/BaseAccountProvider.d.mts +25 -5
- package/dist/providers/BaseAccountProvider.d.mts.map +1 -1
- package/dist/providers/BaseAccountProvider.mjs +18 -0
- package/dist/providers/BaseAccountProvider.mjs.map +1 -1
- package/dist/providers/EvmAccountProvider.cjs +35 -0
- package/dist/providers/EvmAccountProvider.cjs.map +1 -1
- package/dist/providers/EvmAccountProvider.d.cts +66 -0
- package/dist/providers/EvmAccountProvider.d.cts.map +1 -1
- package/dist/providers/EvmAccountProvider.d.mts +66 -0
- package/dist/providers/EvmAccountProvider.d.mts.map +1 -1
- package/dist/providers/EvmAccountProvider.mjs +36 -1
- package/dist/providers/EvmAccountProvider.mjs.map +1 -1
- package/dist/providers/SolAccountProvider.cjs +39 -0
- package/dist/providers/SolAccountProvider.cjs.map +1 -1
- package/dist/providers/SolAccountProvider.d.cts +28 -1
- package/dist/providers/SolAccountProvider.d.cts.map +1 -1
- package/dist/providers/SolAccountProvider.d.mts +28 -1
- package/dist/providers/SolAccountProvider.d.mts.map +1 -1
- package/dist/providers/SolAccountProvider.mjs +40 -1
- package/dist/providers/SolAccountProvider.mjs.map +1 -1
- package/dist/tests/accounts.cjs +89 -4
- package/dist/tests/accounts.cjs.map +1 -1
- package/dist/tests/accounts.d.cts +235 -36
- package/dist/tests/accounts.d.cts.map +1 -1
- package/dist/tests/accounts.d.mts +235 -36
- package/dist/tests/accounts.d.mts.map +1 -1
- package/dist/tests/accounts.mjs +89 -4
- package/dist/tests/accounts.mjs.map +1 -1
- package/dist/tests/index.cjs +1 -0
- package/dist/tests/index.cjs.map +1 -1
- package/dist/tests/index.d.cts +1 -0
- package/dist/tests/index.d.cts.map +1 -1
- package/dist/tests/index.d.mts +1 -0
- package/dist/tests/index.d.mts.map +1 -1
- package/dist/tests/index.mjs +1 -0
- package/dist/tests/index.mjs.map +1 -1
- package/dist/tests/providers.cjs +28 -0
- package/dist/tests/providers.cjs.map +1 -0
- package/dist/tests/providers.d.cts +16 -0
- package/dist/tests/providers.d.cts.map +1 -0
- package/dist/tests/providers.d.mts +16 -0
- package/dist/tests/providers.d.mts.map +1 -0
- package/dist/tests/providers.mjs +23 -0
- package/dist/tests/providers.mjs.map +1 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +11 -7
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +11 -7
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +7 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultichainAccountService.mjs","sourceRoot":"","sources":["../src/MultichainAccountService.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n MultichainAccountWalletId,\n AccountProvider,\n Bip44Account,\n} from '@metamask/account-api';\nimport {\n isBip44Account,\n MultichainAccountWallet,\n toMultichainAccountWalletId,\n type MultichainAccount,\n} from '@metamask/account-api';\nimport type { EntropySourceId, KeyringAccount } from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport { EvmAccountProvider } from './providers/EvmAccountProvider';\nimport { SolAccountProvider } from './providers/SolAccountProvider';\nimport type { MultichainAccountServiceMessenger } from './types';\n\nexport const serviceName = 'MultichainAccountService';\n\n/**\n * The options that {@link MultichainAccountService} takes.\n */\ntype MultichainAccountServiceOptions = {\n messenger: MultichainAccountServiceMessenger;\n};\n\n/** Reverse mapping object used to map account IDs and their wallet/multichain account. */\ntype AccountContext<Account extends Bip44Account<KeyringAccount>> = {\n wallet: MultichainAccountWallet<Account>;\n multichainAccount: MultichainAccount<Account>;\n};\n\n/**\n * Service to expose multichain accounts capabilities.\n */\nexport class MultichainAccountService {\n readonly #messenger: MultichainAccountServiceMessenger;\n\n readonly #providers: AccountProvider<Bip44Account<InternalAccount>>[];\n\n readonly #wallets: Map<\n MultichainAccountWalletId,\n MultichainAccountWallet<Bip44Account<InternalAccount>>\n >;\n\n readonly #accountIdToContext: Map<\n Bip44Account<InternalAccount>['id'],\n AccountContext<Bip44Account<InternalAccount>>\n >;\n\n /**\n * The name of the service.\n */\n name: typeof serviceName = serviceName;\n\n /**\n * Constructs a new MultichainAccountService.\n *\n * @param options - The options.\n * @param options.messenger - The messenger suited to this\n * MultichainAccountService.\n */\n constructor({ messenger }: MultichainAccountServiceOptions) {\n this.#messenger = messenger;\n this.#wallets = new Map();\n this.#accountIdToContext = new Map();\n // TODO: Rely on keyring capabilities once the keyring API is used by all keyrings.\n this.#providers = [\n new EvmAccountProvider(this.#messenger),\n new SolAccountProvider(this.#messenger),\n ];\n\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccount',\n (...args) => this.getMultichainAccount(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccounts',\n (...args) => this.getMultichainAccounts(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountWallet',\n (...args) => this.getMultichainAccountWallet(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountWallets',\n (...args) => this.getMultichainAccountWallets(...args),\n );\n }\n\n /**\n * Initialize the service and constructs the internal reprensentation of\n * multichain accounts and wallets.\n */\n init(): void {\n // Create initial wallets.\n const { keyrings } = this.#messenger.call('KeyringController:getState');\n for (const keyring of keyrings) {\n if (keyring.type === (KeyringTypes.hd as string)) {\n // Only HD keyrings have an entropy source/SRP.\n const entropySource = keyring.metadata.id;\n\n // This will automatically \"associate\" all multichain accounts for that wallet\n // (based on the accounts owned by each account providers).\n const wallet = new MultichainAccountWallet({\n entropySource,\n providers: this.#providers,\n });\n this.#wallets.set(wallet.id, wallet);\n\n // Reverse mapping between account ID and their multichain wallet/account:\n for (const multichainAccount of wallet.getMultichainAccounts()) {\n for (const account of multichainAccount.getAccounts()) {\n this.#accountIdToContext.set(account.id, {\n wallet,\n multichainAccount,\n });\n }\n }\n }\n }\n\n this.#messenger.subscribe('AccountsController:accountAdded', (account) =>\n this.#handleOnAccountAdded(account),\n );\n this.#messenger.subscribe('AccountsController:accountRemoved', (id) =>\n this.#handleOnAccountRemoved(id),\n );\n }\n\n #handleOnAccountAdded(account: InternalAccount): void {\n // We completely omit non-BIP-44 accounts!\n if (!isBip44Account(account)) {\n return;\n }\n\n let sync = true;\n\n let wallet = this.#wallets.get(\n toMultichainAccountWalletId(account.options.entropy.id),\n );\n if (!wallet) {\n // That's a new wallet.\n wallet = new MultichainAccountWallet({\n entropySource: account.options.entropy.id,\n providers: this.#providers,\n });\n this.#wallets.set(wallet.id, wallet);\n\n // If that's a new wallet wallet. There's nothing to \"force-sync\".\n sync = false;\n }\n\n let multichainAccount = wallet.getMultichainAccount(\n account.options.entropy.groupIndex,\n );\n if (!multichainAccount) {\n // This new account is a new multichain account, let the wallet know\n // it has to re-sync with its providers.\n if (sync) {\n wallet.sync();\n }\n\n multichainAccount = wallet.getMultichainAccount(\n account.options.entropy.groupIndex,\n );\n\n // If that's a new multichain account. There's nothing to \"force-sync\".\n sync = false;\n }\n\n // We have to check against `undefined` in case `getMultichainAccount` is\n // not able to find this multichain account (which should not be possible...)\n if (multichainAccount) {\n if (sync) {\n multichainAccount.sync();\n }\n\n // Same here, this account should have been already grouped in that\n // multichain account.\n this.#accountIdToContext.set(account.id, {\n wallet,\n multichainAccount,\n });\n }\n }\n\n #handleOnAccountRemoved(id: InternalAccount['id']): void {\n // Force sync of the appropriate wallet if an account got removed.\n const found = this.#accountIdToContext.get(id);\n if (found) {\n const { wallet } = found;\n\n wallet.sync();\n }\n\n // Safe to call delete even if the `id` was not referencing a BIP-44 account.\n this.#accountIdToContext.delete(id);\n }\n\n #getWallet(\n entropySource: EntropySourceId,\n ): MultichainAccountWallet<Bip44Account<InternalAccount>> {\n const wallet = this.#wallets.get(\n toMultichainAccountWalletId(entropySource),\n );\n\n if (!wallet) {\n throw new Error('Unknown wallet, no wallet matching this entropy source');\n }\n\n return wallet;\n }\n\n /**\n * Gets a reference to the wallet and multichain account for a given account ID.\n *\n * @param id - Account ID.\n * @returns An object with references to the wallet and multichain account associated for\n * that account ID, or undefined if this account ID is not part of any.\n */\n getMultichainAccountAndWallet(\n id: InternalAccount['id'],\n ): AccountContext<Bip44Account<InternalAccount>> | undefined {\n return this.#accountIdToContext.get(id);\n }\n\n /**\n * Gets a reference to the multichain account wallet matching this entropy source.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source of the multichain account.\n * @throws If none multichain account match this entropy.\n * @returns A reference to the multichain account wallet.\n */\n getMultichainAccountWallet({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): MultichainAccountWallet<Bip44Account<InternalAccount>> {\n return this.#getWallet(entropySource);\n }\n\n /**\n * Gets an array of all multichain account wallets.\n *\n * @returns An array of all multichain account wallets.\n */\n getMultichainAccountWallets(): MultichainAccountWallet<\n Bip44Account<InternalAccount>\n >[] {\n return Array.from(this.#wallets.values());\n }\n\n /**\n * Gets a reference to the multichain account matching this entropy source and group index.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source of the multichain account.\n * @param options.groupIndex - The group index of the multichain account.\n * @throws If none multichain account match this entropy source and group index.\n * @returns A reference to the multichain account.\n */\n getMultichainAccount({\n entropySource,\n groupIndex,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): MultichainAccount<Bip44Account<InternalAccount>> {\n const multichainAccount =\n this.#getWallet(entropySource).getMultichainAccount(groupIndex);\n\n if (!multichainAccount) {\n throw new Error(`No multichain account for index: ${groupIndex}`);\n }\n\n return multichainAccount;\n }\n\n /**\n * Gets all multichain accounts for a given entropy source.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source to query.\n * @throws If no multichain accounts match this entropy source.\n * @returns A list of all multichain accounts.\n */\n getMultichainAccounts({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): MultichainAccount<Bip44Account<InternalAccount>>[] {\n return this.#getWallet(entropySource).getMultichainAccounts();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MultichainAccountService.mjs","sourceRoot":"","sources":["../src/MultichainAccountService.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n isBip44Account,\n toMultichainAccountWalletId,\n} from '@metamask/account-api';\nimport type {\n MultichainAccountWalletId,\n Bip44Account,\n} from '@metamask/account-api';\nimport type { AccountProvider } from '@metamask/account-api';\nimport type { EntropySourceId, KeyringAccount } from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\n\nimport type { MultichainAccountGroup } from './MultichainAccountGroup';\nimport { MultichainAccountWallet } from './MultichainAccountWallet';\nimport { EvmAccountProvider } from './providers/EvmAccountProvider';\nimport { SolAccountProvider } from './providers/SolAccountProvider';\nimport type { MultichainAccountServiceMessenger } from './types';\n\nexport const serviceName = 'MultichainAccountService';\n\n/**\n * The options that {@link MultichainAccountService} takes.\n */\ntype MultichainAccountServiceOptions = {\n messenger: MultichainAccountServiceMessenger;\n};\n\n/** Reverse mapping object used to map account IDs and their wallet/multichain account. */\ntype AccountContext<Account extends Bip44Account<KeyringAccount>> = {\n wallet: MultichainAccountWallet<Account>;\n group: MultichainAccountGroup<Account>;\n};\n\n/**\n * Service to expose multichain accounts capabilities.\n */\nexport class MultichainAccountService {\n readonly #messenger: MultichainAccountServiceMessenger;\n\n readonly #providers: AccountProvider<Bip44Account<KeyringAccount>>[];\n\n readonly #wallets: Map<\n MultichainAccountWalletId,\n MultichainAccountWallet<Bip44Account<KeyringAccount>>\n >;\n\n readonly #accountIdToContext: Map<\n Bip44Account<KeyringAccount>['id'],\n AccountContext<Bip44Account<KeyringAccount>>\n >;\n\n /**\n * The name of the service.\n */\n name: typeof serviceName = serviceName;\n\n /**\n * Constructs a new MultichainAccountService.\n *\n * @param options - The options.\n * @param options.messenger - The messenger suited to this\n * MultichainAccountService.\n */\n constructor({ messenger }: MultichainAccountServiceOptions) {\n this.#messenger = messenger;\n this.#wallets = new Map();\n this.#accountIdToContext = new Map();\n // TODO: Rely on keyring capabilities once the keyring API is used by all keyrings.\n this.#providers = [\n new EvmAccountProvider(this.#messenger),\n new SolAccountProvider(this.#messenger),\n ];\n\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountGroup',\n (...args) => this.getMultichainAccountGroup(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountGroups',\n (...args) => this.getMultichainAccountGroups(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountWallet',\n (...args) => this.getMultichainAccountWallet(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountWallets',\n (...args) => this.getMultichainAccountWallets(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:createNextMultichainAccountGroup',\n (...args) => this.createNextMultichainAccountGroup(...args),\n );\n }\n\n /**\n * Initialize the service and constructs the internal reprensentation of\n * multichain accounts and wallets.\n */\n init(): void {\n // Create initial wallets.\n const { keyrings } = this.#messenger.call('KeyringController:getState');\n for (const keyring of keyrings) {\n if (keyring.type === (KeyringTypes.hd as string)) {\n // Only HD keyrings have an entropy source/SRP.\n const entropySource = keyring.metadata.id;\n\n // This will automatically \"associate\" all multichain accounts for that wallet\n // (based on the accounts owned by each account providers).\n const wallet = new MultichainAccountWallet({\n entropySource,\n providers: this.#providers,\n });\n this.#wallets.set(wallet.id, wallet);\n\n // Reverse mapping between account ID and their multichain wallet/account:\n for (const group of wallet.getMultichainAccountGroups()) {\n for (const account of group.getAccounts()) {\n this.#accountIdToContext.set(account.id, {\n wallet,\n group,\n });\n }\n }\n }\n }\n\n this.#messenger.subscribe('AccountsController:accountAdded', (account) =>\n this.#handleOnAccountAdded(account),\n );\n this.#messenger.subscribe('AccountsController:accountRemoved', (id) =>\n this.#handleOnAccountRemoved(id),\n );\n }\n\n #handleOnAccountAdded(account: KeyringAccount): void {\n // We completely omit non-BIP-44 accounts!\n if (!isBip44Account(account)) {\n return;\n }\n\n let sync = true;\n\n let wallet = this.#wallets.get(\n toMultichainAccountWalletId(account.options.entropy.id),\n );\n if (!wallet) {\n // That's a new wallet.\n wallet = new MultichainAccountWallet({\n entropySource: account.options.entropy.id,\n providers: this.#providers,\n });\n this.#wallets.set(wallet.id, wallet);\n\n // If that's a new wallet wallet. There's nothing to \"force-sync\".\n sync = false;\n }\n\n let group = wallet.getMultichainAccountGroup(\n account.options.entropy.groupIndex,\n );\n if (!group) {\n // This new account is a new multichain account, let the wallet know\n // it has to re-sync with its providers.\n if (sync) {\n wallet.sync();\n }\n\n group = wallet.getMultichainAccountGroup(\n account.options.entropy.groupIndex,\n );\n\n // If that's a new multichain account. There's nothing to \"force-sync\".\n sync = false;\n }\n\n // We have to check against `undefined` in case `getMultichainAccount` is\n // not able to find this multichain account (which should not be possible...)\n if (group) {\n if (sync) {\n group.sync();\n }\n\n // Same here, this account should have been already grouped in that\n // multichain account.\n this.#accountIdToContext.set(account.id, {\n wallet,\n group,\n });\n }\n }\n\n #handleOnAccountRemoved(id: KeyringAccount['id']): void {\n // Force sync of the appropriate wallet if an account got removed.\n const found = this.#accountIdToContext.get(id);\n if (found) {\n const { wallet } = found;\n\n wallet.sync();\n }\n\n // Safe to call delete even if the `id` was not referencing a BIP-44 account.\n this.#accountIdToContext.delete(id);\n }\n\n #getWallet(\n entropySource: EntropySourceId,\n ): MultichainAccountWallet<Bip44Account<KeyringAccount>> {\n const wallet = this.#wallets.get(\n toMultichainAccountWalletId(entropySource),\n );\n\n if (!wallet) {\n throw new Error('Unknown wallet, no wallet matching this entropy source');\n }\n\n return wallet;\n }\n\n /**\n * Gets the account's context which contains its multichain wallet and\n * multichain account group references.\n *\n * @param id - Account ID.\n * @returns The account context if any, undefined otherwise.\n */\n getAccountContext(\n id: KeyringAccount['id'],\n ): AccountContext<Bip44Account<KeyringAccount>> | undefined {\n return this.#accountIdToContext.get(id);\n }\n\n /**\n * Gets a reference to the multichain account wallet matching this entropy source.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source of the multichain account.\n * @throws If none multichain account match this entropy.\n * @returns A reference to the multichain account wallet.\n */\n getMultichainAccountWallet({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): MultichainAccountWallet<Bip44Account<KeyringAccount>> {\n return this.#getWallet(entropySource);\n }\n\n /**\n * Gets an array of all multichain account wallets.\n *\n * @returns An array of all multichain account wallets.\n */\n getMultichainAccountWallets(): MultichainAccountWallet<\n Bip44Account<KeyringAccount>\n >[] {\n return Array.from(this.#wallets.values());\n }\n\n /**\n * Gets a reference to the multichain account group matching this entropy source\n * and a group index.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source of the multichain account.\n * @param options.groupIndex - The group index of the multichain account.\n * @throws If none multichain account match this entropy source and group index.\n * @returns A reference to the multichain account.\n */\n getMultichainAccountGroup({\n entropySource,\n groupIndex,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): MultichainAccountGroup<Bip44Account<KeyringAccount>> {\n const multichainAccount =\n this.#getWallet(entropySource).getMultichainAccountGroup(groupIndex);\n\n if (!multichainAccount) {\n throw new Error(`No multichain account for index: ${groupIndex}`);\n }\n\n return multichainAccount;\n }\n\n /**\n * Gets all multichain account groups for a given entropy source.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source to query.\n * @throws If no multichain accounts match this entropy source.\n * @returns A list of all multichain accounts.\n */\n getMultichainAccountGroups({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): MultichainAccountGroup<Bip44Account<KeyringAccount>>[] {\n return this.#getWallet(entropySource).getMultichainAccountGroups();\n }\n\n /**\n * Creates the next multichain account group.\n *\n * @param options - Options.\n * @param options.entropySource - The wallet's entropy source.\n * @returns The next multichain account group.\n */\n async createNextMultichainAccountGroup({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): Promise<MultichainAccountGroup<Bip44Account<KeyringAccount>>> {\n return await this.#getWallet(\n entropySource,\n ).createNextMultichainAccountGroup();\n }\n}\n"]}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var _MultichainAccountWallet_id, _MultichainAccountWallet_providers, _MultichainAccountWallet_entropySource, _MultichainAccountWallet_accounts;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.MultichainAccountWallet = void 0;
|
|
16
|
+
const account_api_1 = require("@metamask/account-api");
|
|
17
|
+
const account_api_2 = require("@metamask/account-api");
|
|
18
|
+
const account_api_3 = require("@metamask/account-api");
|
|
19
|
+
const MultichainAccountGroup_1 = require("./MultichainAccountGroup.cjs");
|
|
20
|
+
/**
|
|
21
|
+
* A multichain account wallet that holds multiple multichain accounts (one multichain account per
|
|
22
|
+
* group index).
|
|
23
|
+
*/
|
|
24
|
+
class MultichainAccountWallet {
|
|
25
|
+
constructor({ providers, entropySource, }) {
|
|
26
|
+
_MultichainAccountWallet_id.set(this, void 0);
|
|
27
|
+
_MultichainAccountWallet_providers.set(this, void 0);
|
|
28
|
+
_MultichainAccountWallet_entropySource.set(this, void 0);
|
|
29
|
+
_MultichainAccountWallet_accounts.set(this, void 0);
|
|
30
|
+
__classPrivateFieldSet(this, _MultichainAccountWallet_id, (0, account_api_1.toMultichainAccountWalletId)(entropySource), "f");
|
|
31
|
+
__classPrivateFieldSet(this, _MultichainAccountWallet_providers, providers, "f");
|
|
32
|
+
__classPrivateFieldSet(this, _MultichainAccountWallet_entropySource, entropySource, "f");
|
|
33
|
+
__classPrivateFieldSet(this, _MultichainAccountWallet_accounts, new Map(), "f");
|
|
34
|
+
// Initial synchronization.
|
|
35
|
+
this.sync();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Force wallet synchronization.
|
|
39
|
+
*
|
|
40
|
+
* This can be used if account providers got new accounts that the wallet
|
|
41
|
+
* doesn't know about.
|
|
42
|
+
*/
|
|
43
|
+
sync() {
|
|
44
|
+
for (const provider of __classPrivateFieldGet(this, _MultichainAccountWallet_providers, "f")) {
|
|
45
|
+
for (const account of provider.getAccounts()) {
|
|
46
|
+
const { entropy } = account.options;
|
|
47
|
+
// Filter for this wallet only.
|
|
48
|
+
if (entropy.id !== this.entropySource) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
// This multichain account might exists already.
|
|
52
|
+
let multichainAccount = __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").get(entropy.groupIndex);
|
|
53
|
+
if (!multichainAccount) {
|
|
54
|
+
multichainAccount = new MultichainAccountGroup_1.MultichainAccountGroup({
|
|
55
|
+
groupIndex: entropy.groupIndex,
|
|
56
|
+
wallet: this,
|
|
57
|
+
providers: __classPrivateFieldGet(this, _MultichainAccountWallet_providers, "f"),
|
|
58
|
+
});
|
|
59
|
+
// This existing multichain account group might differ from the
|
|
60
|
+
// `createMultichainAccountGroup` behavior. When creating a new
|
|
61
|
+
// group, we expect the providers to all succeed. But here, we're
|
|
62
|
+
// just fetching the account lists from them, so this group might
|
|
63
|
+
// not be "aligned" yet (e.g having a missing Solana account).
|
|
64
|
+
//
|
|
65
|
+
// Since "aligning" is an async operation, it would have to be run
|
|
66
|
+
// after the first-sync.
|
|
67
|
+
// TODO: Implement align mechanism to create "missing" accounts.
|
|
68
|
+
__classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").set(entropy.groupIndex, multichainAccount);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Now force-sync all remaining multichain accounts.
|
|
73
|
+
for (const [groupIndex, multichainAccount] of __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").entries()) {
|
|
74
|
+
multichainAccount.sync();
|
|
75
|
+
// Clean up old multichain accounts.
|
|
76
|
+
if (!multichainAccount.hasAccounts()) {
|
|
77
|
+
__classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").delete(groupIndex);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Gets the multichain account wallet ID.
|
|
83
|
+
*
|
|
84
|
+
* @returns The multichain account wallet ID.
|
|
85
|
+
*/
|
|
86
|
+
get id() {
|
|
87
|
+
return __classPrivateFieldGet(this, _MultichainAccountWallet_id, "f");
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Gets the multichain account wallet type, which is always {@link AccountWalletType.Entropy}.
|
|
91
|
+
*
|
|
92
|
+
* @returns The multichain account wallet type.
|
|
93
|
+
*/
|
|
94
|
+
get type() {
|
|
95
|
+
return account_api_3.AccountWalletType.Entropy;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Gets the multichain account wallet entropy source.
|
|
99
|
+
*
|
|
100
|
+
* @returns The multichain account wallet entropy source.
|
|
101
|
+
*/
|
|
102
|
+
get entropySource() {
|
|
103
|
+
return __classPrivateFieldGet(this, _MultichainAccountWallet_entropySource, "f");
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Gets multichain account for a given ID.
|
|
107
|
+
* The default group ID will default to the multichain account with index 0.
|
|
108
|
+
*
|
|
109
|
+
* @param id - Account group ID.
|
|
110
|
+
* @returns Account group.
|
|
111
|
+
*/
|
|
112
|
+
getAccountGroup(id) {
|
|
113
|
+
// We consider the "default case" to be mapped to index 0.
|
|
114
|
+
if (id === (0, account_api_2.toDefaultAccountGroupId)(this.id)) {
|
|
115
|
+
return __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").get(0);
|
|
116
|
+
}
|
|
117
|
+
// If it is not a valid ID, we cannot extract the group index
|
|
118
|
+
// from it, so we fail fast.
|
|
119
|
+
if (!(0, account_api_1.isMultichainAccountGroupId)(id)) {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
const groupIndex = (0, account_api_1.getGroupIndexFromMultichainAccountGroupId)(id);
|
|
123
|
+
return __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").get(groupIndex);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Gets all multichain accounts. Similar to {@link MultichainAccountWallet.getMultichainAccountGroups}.
|
|
127
|
+
*
|
|
128
|
+
* @returns The multichain accounts.
|
|
129
|
+
*/
|
|
130
|
+
getAccountGroups() {
|
|
131
|
+
return this.getMultichainAccountGroups();
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Gets multichain account group for a given index.
|
|
135
|
+
*
|
|
136
|
+
* @param groupIndex - Multichain account index.
|
|
137
|
+
* @returns The multichain account associated with the given index.
|
|
138
|
+
*/
|
|
139
|
+
getMultichainAccountGroup(groupIndex) {
|
|
140
|
+
return __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").get(groupIndex);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Gets all multichain account groups.
|
|
144
|
+
*
|
|
145
|
+
* @returns The multichain accounts.
|
|
146
|
+
*/
|
|
147
|
+
getMultichainAccountGroups() {
|
|
148
|
+
return Array.from(__classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").values()); // TODO: Prevent copy here.
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Gets next group index for this wallet.
|
|
152
|
+
*
|
|
153
|
+
* @returns The next group index of this wallet.
|
|
154
|
+
*/
|
|
155
|
+
getNextGroupIndex() {
|
|
156
|
+
// Assuming we cannot have indexes gaps.
|
|
157
|
+
return __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").size; // No +1 here, group indexes starts at 0.
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Creates a multichain account group for a given group index.
|
|
161
|
+
*
|
|
162
|
+
* @param groupIndex - The group index to use.
|
|
163
|
+
* @throws If any of the account providers fails to create their accounts.
|
|
164
|
+
* @returns The multichain account group for this group index.
|
|
165
|
+
*/
|
|
166
|
+
async createMultichainAccountGroup(groupIndex) {
|
|
167
|
+
const nextGroupIndex = this.getNextGroupIndex();
|
|
168
|
+
if (groupIndex > nextGroupIndex) {
|
|
169
|
+
throw new Error(`You cannot use a group index that is higher than the next available one: expected <=${nextGroupIndex}, got ${groupIndex}`);
|
|
170
|
+
}
|
|
171
|
+
let group = this.getMultichainAccountGroup(groupIndex);
|
|
172
|
+
if (group) {
|
|
173
|
+
// If the group already exists, we just `sync` it and returns the same
|
|
174
|
+
// reference.
|
|
175
|
+
group.sync();
|
|
176
|
+
return group;
|
|
177
|
+
}
|
|
178
|
+
const results = await Promise.allSettled(__classPrivateFieldGet(this, _MultichainAccountWallet_providers, "f").map((provider) => provider.createAccounts({
|
|
179
|
+
entropySource: __classPrivateFieldGet(this, _MultichainAccountWallet_entropySource, "f"),
|
|
180
|
+
groupIndex,
|
|
181
|
+
})));
|
|
182
|
+
// READ THIS CAREFULLY:
|
|
183
|
+
// Since we're not "fully supporting multichain" for now, we still rely on single
|
|
184
|
+
// :accountCreated events to sync multichain account groups and wallets. Which means
|
|
185
|
+
// that even if of the provider fails, some accouns (on the `AccountsController`
|
|
186
|
+
// might be showing up AND that some multichain account wallets/groups might have
|
|
187
|
+
// been automatically sync'd too.
|
|
188
|
+
//
|
|
189
|
+
// We will need to unsubscribe from :accountAdded once we "fully support multichain"
|
|
190
|
+
// (meaning, the entire codebase relies on this new service for multichain account
|
|
191
|
+
// creations).
|
|
192
|
+
// --------------------------------------------------------------------------------
|
|
193
|
+
// If any of the provider failed to create their accounts, then we consider the
|
|
194
|
+
// multichain account group to have failed too.
|
|
195
|
+
// NOTE: Though, we don't rollback existing created accounts and that's totally fine
|
|
196
|
+
// because account creations is assumed to be imdepotent, thus, trying again should
|
|
197
|
+
// just create the missing accounts, and previously created accounts will just be
|
|
198
|
+
// re-used as is.
|
|
199
|
+
if (results.some((result) => result.status === 'rejected')) {
|
|
200
|
+
const error = `Unable to create multichain account group for index: ${groupIndex}`;
|
|
201
|
+
let warn = `${error}:`;
|
|
202
|
+
for (const result of results) {
|
|
203
|
+
if (result.status === 'rejected') {
|
|
204
|
+
warn += `\n- ${result.reason}`;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
console.warn(warn);
|
|
208
|
+
throw new Error(error);
|
|
209
|
+
}
|
|
210
|
+
// Because of the :accountAdded automatic sync, we might already have created the
|
|
211
|
+
// group, so we first try to get it.
|
|
212
|
+
group = this.getMultichainAccountGroup(groupIndex);
|
|
213
|
+
if (!group) {
|
|
214
|
+
// If for some reason it's still not created, we're creating it explicitly now:
|
|
215
|
+
group = new MultichainAccountGroup_1.MultichainAccountGroup({
|
|
216
|
+
wallet: this,
|
|
217
|
+
providers: __classPrivateFieldGet(this, _MultichainAccountWallet_providers, "f"),
|
|
218
|
+
groupIndex,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
// Register the account to our internal map.
|
|
222
|
+
__classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").set(groupIndex, group); // `group` cannot be undefined here.
|
|
223
|
+
return group;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Creates the next multichain account group.
|
|
227
|
+
*
|
|
228
|
+
* @throws If any of the account providers fails to create their accounts.
|
|
229
|
+
* @returns The multichain account group for the next group index available.
|
|
230
|
+
*/
|
|
231
|
+
async createNextMultichainAccountGroup() {
|
|
232
|
+
return this.createMultichainAccountGroup(this.getNextGroupIndex());
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
exports.MultichainAccountWallet = MultichainAccountWallet;
|
|
236
|
+
_MultichainAccountWallet_id = new WeakMap(), _MultichainAccountWallet_providers = new WeakMap(), _MultichainAccountWallet_entropySource = new WeakMap(), _MultichainAccountWallet_accounts = new WeakMap();
|
|
237
|
+
//# sourceMappingURL=MultichainAccountWallet.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultichainAccountWallet.cjs","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getGroupIndexFromMultichainAccountGroupId,\n isMultichainAccountGroupId,\n toMultichainAccountWalletId,\n} from '@metamask/account-api';\nimport { toDefaultAccountGroupId } from '@metamask/account-api';\nimport { AccountWalletType } from '@metamask/account-api';\nimport type {\n Bip44Account,\n MultichainAccountWalletId,\n MultichainAccountWallet as MultichainAccountWalletDefinition,\n} from '@metamask/account-api';\nimport type { AccountGroupId } from '@metamask/account-api';\nimport type { AccountProvider } from '@metamask/account-api';\nimport {\n type EntropySourceId,\n type KeyringAccount,\n} from '@metamask/keyring-api';\n\nimport { MultichainAccountGroup } from './MultichainAccountGroup';\n\n/**\n * A multichain account wallet that holds multiple multichain accounts (one multichain account per\n * group index).\n */\nexport class MultichainAccountWallet<\n Account extends Bip44Account<KeyringAccount>,\n> implements MultichainAccountWalletDefinition<Account>\n{\n readonly #id: MultichainAccountWalletId;\n\n readonly #providers: AccountProvider<Account>[];\n\n readonly #entropySource: EntropySourceId;\n\n readonly #accounts: Map<number, MultichainAccountGroup<Account>>;\n\n constructor({\n providers,\n entropySource,\n }: {\n providers: AccountProvider<Account>[];\n entropySource: EntropySourceId;\n }) {\n this.#id = toMultichainAccountWalletId(entropySource);\n this.#providers = providers;\n this.#entropySource = entropySource;\n this.#accounts = new Map();\n\n // Initial synchronization.\n this.sync();\n }\n\n /**\n * Force wallet synchronization.\n *\n * This can be used if account providers got new accounts that the wallet\n * doesn't know about.\n */\n sync(): void {\n for (const provider of this.#providers) {\n for (const account of provider.getAccounts()) {\n const { entropy } = account.options;\n\n // Filter for this wallet only.\n if (entropy.id !== this.entropySource) {\n continue;\n }\n\n // This multichain account might exists already.\n let multichainAccount = this.#accounts.get(entropy.groupIndex);\n if (!multichainAccount) {\n multichainAccount = new MultichainAccountGroup<Account>({\n groupIndex: entropy.groupIndex,\n wallet: this,\n providers: this.#providers,\n });\n\n // This existing multichain account group might differ from the\n // `createMultichainAccountGroup` behavior. When creating a new\n // group, we expect the providers to all succeed. But here, we're\n // just fetching the account lists from them, so this group might\n // not be \"aligned\" yet (e.g having a missing Solana account).\n //\n // Since \"aligning\" is an async operation, it would have to be run\n // after the first-sync.\n // TODO: Implement align mechanism to create \"missing\" accounts.\n\n this.#accounts.set(entropy.groupIndex, multichainAccount);\n }\n }\n }\n\n // Now force-sync all remaining multichain accounts.\n for (const [groupIndex, multichainAccount] of this.#accounts.entries()) {\n multichainAccount.sync();\n\n // Clean up old multichain accounts.\n if (!multichainAccount.hasAccounts()) {\n this.#accounts.delete(groupIndex);\n }\n }\n }\n\n /**\n * Gets the multichain account wallet ID.\n *\n * @returns The multichain account wallet ID.\n */\n get id(): MultichainAccountWalletId {\n return this.#id;\n }\n\n /**\n * Gets the multichain account wallet type, which is always {@link AccountWalletType.Entropy}.\n *\n * @returns The multichain account wallet type.\n */\n get type(): AccountWalletType.Entropy {\n return AccountWalletType.Entropy;\n }\n\n /**\n * Gets the multichain account wallet entropy source.\n *\n * @returns The multichain account wallet entropy source.\n */\n get entropySource(): EntropySourceId {\n return this.#entropySource;\n }\n\n /**\n * Gets multichain account for a given ID.\n * The default group ID will default to the multichain account with index 0.\n *\n * @param id - Account group ID.\n * @returns Account group.\n */\n getAccountGroup(\n id: AccountGroupId,\n ): MultichainAccountGroup<Account> | undefined {\n // We consider the \"default case\" to be mapped to index 0.\n if (id === toDefaultAccountGroupId(this.id)) {\n return this.#accounts.get(0);\n }\n\n // If it is not a valid ID, we cannot extract the group index\n // from it, so we fail fast.\n if (!isMultichainAccountGroupId(id)) {\n return undefined;\n }\n\n const groupIndex = getGroupIndexFromMultichainAccountGroupId(id);\n return this.#accounts.get(groupIndex);\n }\n\n /**\n * Gets all multichain accounts. Similar to {@link MultichainAccountWallet.getMultichainAccountGroups}.\n *\n * @returns The multichain accounts.\n */\n getAccountGroups(): MultichainAccountGroup<Account>[] {\n return this.getMultichainAccountGroups();\n }\n\n /**\n * Gets multichain account group for a given index.\n *\n * @param groupIndex - Multichain account index.\n * @returns The multichain account associated with the given index.\n */\n getMultichainAccountGroup(\n groupIndex: number,\n ): MultichainAccountGroup<Account> | undefined {\n return this.#accounts.get(groupIndex);\n }\n\n /**\n * Gets all multichain account groups.\n *\n * @returns The multichain accounts.\n */\n getMultichainAccountGroups(): MultichainAccountGroup<Account>[] {\n return Array.from(this.#accounts.values()); // TODO: Prevent copy here.\n }\n\n /**\n * Gets next group index for this wallet.\n *\n * @returns The next group index of this wallet.\n */\n getNextGroupIndex(): number {\n // Assuming we cannot have indexes gaps.\n return this.#accounts.size; // No +1 here, group indexes starts at 0.\n }\n\n /**\n * Creates a multichain account group for a given group index.\n *\n * @param groupIndex - The group index to use.\n * @throws If any of the account providers fails to create their accounts.\n * @returns The multichain account group for this group index.\n */\n async createMultichainAccountGroup(\n groupIndex: number,\n ): Promise<MultichainAccountGroup<Account>> {\n const nextGroupIndex = this.getNextGroupIndex();\n if (groupIndex > nextGroupIndex) {\n throw new Error(\n `You cannot use a group index that is higher than the next available one: expected <=${nextGroupIndex}, got ${groupIndex}`,\n );\n }\n\n let group = this.getMultichainAccountGroup(groupIndex);\n if (group) {\n // If the group already exists, we just `sync` it and returns the same\n // reference.\n group.sync();\n\n return group;\n }\n\n const results = await Promise.allSettled(\n this.#providers.map((provider) =>\n provider.createAccounts({\n entropySource: this.#entropySource,\n groupIndex,\n }),\n ),\n );\n\n // READ THIS CAREFULLY:\n // Since we're not \"fully supporting multichain\" for now, we still rely on single\n // :accountCreated events to sync multichain account groups and wallets. Which means\n // that even if of the provider fails, some accouns (on the `AccountsController`\n // might be showing up AND that some multichain account wallets/groups might have\n // been automatically sync'd too.\n //\n // We will need to unsubscribe from :accountAdded once we \"fully support multichain\"\n // (meaning, the entire codebase relies on this new service for multichain account\n // creations).\n // --------------------------------------------------------------------------------\n\n // If any of the provider failed to create their accounts, then we consider the\n // multichain account group to have failed too.\n // NOTE: Though, we don't rollback existing created accounts and that's totally fine\n // because account creations is assumed to be imdepotent, thus, trying again should\n // just create the missing accounts, and previously created accounts will just be\n // re-used as is.\n if (results.some((result) => result.status === 'rejected')) {\n const error = `Unable to create multichain account group for index: ${groupIndex}`;\n\n let warn = `${error}:`;\n for (const result of results) {\n if (result.status === 'rejected') {\n warn += `\\n- ${result.reason}`;\n }\n }\n console.warn(warn);\n\n throw new Error(error);\n }\n\n // Because of the :accountAdded automatic sync, we might already have created the\n // group, so we first try to get it.\n group = this.getMultichainAccountGroup(groupIndex);\n if (!group) {\n // If for some reason it's still not created, we're creating it explicitly now:\n group = new MultichainAccountGroup({\n wallet: this,\n providers: this.#providers,\n groupIndex,\n });\n }\n\n // Register the account to our internal map.\n this.#accounts.set(groupIndex, group); // `group` cannot be undefined here.\n\n return group;\n }\n\n /**\n * Creates the next multichain account group.\n *\n * @throws If any of the account providers fails to create their accounts.\n * @returns The multichain account group for the next group index available.\n */\n async createNextMultichainAccountGroup(): Promise<\n MultichainAccountGroup<Account>\n > {\n return this.createMultichainAccountGroup(this.getNextGroupIndex());\n }\n}\n"]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { AccountWalletType } from "@metamask/account-api";
|
|
2
|
+
import type { Bip44Account, MultichainAccountWalletId, MultichainAccountWallet as MultichainAccountWalletDefinition } from "@metamask/account-api";
|
|
3
|
+
import type { AccountGroupId } from "@metamask/account-api";
|
|
4
|
+
import type { AccountProvider } from "@metamask/account-api";
|
|
5
|
+
import { type EntropySourceId, type KeyringAccount } from "@metamask/keyring-api";
|
|
6
|
+
import { MultichainAccountGroup } from "./MultichainAccountGroup.cjs";
|
|
7
|
+
/**
|
|
8
|
+
* A multichain account wallet that holds multiple multichain accounts (one multichain account per
|
|
9
|
+
* group index).
|
|
10
|
+
*/
|
|
11
|
+
export declare class MultichainAccountWallet<Account extends Bip44Account<KeyringAccount>> implements MultichainAccountWalletDefinition<Account> {
|
|
12
|
+
#private;
|
|
13
|
+
constructor({ providers, entropySource, }: {
|
|
14
|
+
providers: AccountProvider<Account>[];
|
|
15
|
+
entropySource: EntropySourceId;
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Force wallet synchronization.
|
|
19
|
+
*
|
|
20
|
+
* This can be used if account providers got new accounts that the wallet
|
|
21
|
+
* doesn't know about.
|
|
22
|
+
*/
|
|
23
|
+
sync(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Gets the multichain account wallet ID.
|
|
26
|
+
*
|
|
27
|
+
* @returns The multichain account wallet ID.
|
|
28
|
+
*/
|
|
29
|
+
get id(): MultichainAccountWalletId;
|
|
30
|
+
/**
|
|
31
|
+
* Gets the multichain account wallet type, which is always {@link AccountWalletType.Entropy}.
|
|
32
|
+
*
|
|
33
|
+
* @returns The multichain account wallet type.
|
|
34
|
+
*/
|
|
35
|
+
get type(): AccountWalletType.Entropy;
|
|
36
|
+
/**
|
|
37
|
+
* Gets the multichain account wallet entropy source.
|
|
38
|
+
*
|
|
39
|
+
* @returns The multichain account wallet entropy source.
|
|
40
|
+
*/
|
|
41
|
+
get entropySource(): EntropySourceId;
|
|
42
|
+
/**
|
|
43
|
+
* Gets multichain account for a given ID.
|
|
44
|
+
* The default group ID will default to the multichain account with index 0.
|
|
45
|
+
*
|
|
46
|
+
* @param id - Account group ID.
|
|
47
|
+
* @returns Account group.
|
|
48
|
+
*/
|
|
49
|
+
getAccountGroup(id: AccountGroupId): MultichainAccountGroup<Account> | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Gets all multichain accounts. Similar to {@link MultichainAccountWallet.getMultichainAccountGroups}.
|
|
52
|
+
*
|
|
53
|
+
* @returns The multichain accounts.
|
|
54
|
+
*/
|
|
55
|
+
getAccountGroups(): MultichainAccountGroup<Account>[];
|
|
56
|
+
/**
|
|
57
|
+
* Gets multichain account group for a given index.
|
|
58
|
+
*
|
|
59
|
+
* @param groupIndex - Multichain account index.
|
|
60
|
+
* @returns The multichain account associated with the given index.
|
|
61
|
+
*/
|
|
62
|
+
getMultichainAccountGroup(groupIndex: number): MultichainAccountGroup<Account> | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Gets all multichain account groups.
|
|
65
|
+
*
|
|
66
|
+
* @returns The multichain accounts.
|
|
67
|
+
*/
|
|
68
|
+
getMultichainAccountGroups(): MultichainAccountGroup<Account>[];
|
|
69
|
+
/**
|
|
70
|
+
* Gets next group index for this wallet.
|
|
71
|
+
*
|
|
72
|
+
* @returns The next group index of this wallet.
|
|
73
|
+
*/
|
|
74
|
+
getNextGroupIndex(): number;
|
|
75
|
+
/**
|
|
76
|
+
* Creates a multichain account group for a given group index.
|
|
77
|
+
*
|
|
78
|
+
* @param groupIndex - The group index to use.
|
|
79
|
+
* @throws If any of the account providers fails to create their accounts.
|
|
80
|
+
* @returns The multichain account group for this group index.
|
|
81
|
+
*/
|
|
82
|
+
createMultichainAccountGroup(groupIndex: number): Promise<MultichainAccountGroup<Account>>;
|
|
83
|
+
/**
|
|
84
|
+
* Creates the next multichain account group.
|
|
85
|
+
*
|
|
86
|
+
* @throws If any of the account providers fails to create their accounts.
|
|
87
|
+
* @returns The multichain account group for the next group index available.
|
|
88
|
+
*/
|
|
89
|
+
createNextMultichainAccountGroup(): Promise<MultichainAccountGroup<Account>>;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=MultichainAccountWallet.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultichainAccountWallet.d.cts","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,IAAI,iCAAiC,EAC7D,8BAA8B;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,8BAA8B;AAE/B,OAAO,EAAE,sBAAsB,EAAE,qCAAiC;AAElE;;;GAGG;AACH,qBAAa,uBAAuB,CAClC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,iCAAiC,CAAC,OAAO,CAAC;;gBAUzC,EACV,SAAS,EACT,aAAa,GACd,EAAE;QACD,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,aAAa,EAAE,eAAe,CAAC;KAChC;IAUD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IA6CZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,yBAAyB,CAElC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,iBAAiB,CAAC,OAAO,CAEpC;IAED;;;;OAIG;IACH,IAAI,aAAa,IAAI,eAAe,CAEnC;IAED;;;;;;OAMG;IACH,eAAe,CACb,EAAE,EAAE,cAAc,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAgB9C;;;;OAIG;IACH,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAIrD;;;;;OAKG;IACH,yBAAyB,CACvB,UAAU,EAAE,MAAM,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAI9C;;;;OAIG;IACH,0BAA0B,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAI/D;;;;OAIG;IACH,iBAAiB,IAAI,MAAM;IAK3B;;;;;;OAMG;IACG,4BAA4B,CAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IA4E3C;;;;;OAKG;IACG,gCAAgC,IAAI,OAAO,CAC/C,sBAAsB,CAAC,OAAO,CAAC,CAChC;CAGF"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { AccountWalletType } from "@metamask/account-api";
|
|
2
|
+
import type { Bip44Account, MultichainAccountWalletId, MultichainAccountWallet as MultichainAccountWalletDefinition } from "@metamask/account-api";
|
|
3
|
+
import type { AccountGroupId } from "@metamask/account-api";
|
|
4
|
+
import type { AccountProvider } from "@metamask/account-api";
|
|
5
|
+
import { type EntropySourceId, type KeyringAccount } from "@metamask/keyring-api";
|
|
6
|
+
import { MultichainAccountGroup } from "./MultichainAccountGroup.mjs";
|
|
7
|
+
/**
|
|
8
|
+
* A multichain account wallet that holds multiple multichain accounts (one multichain account per
|
|
9
|
+
* group index).
|
|
10
|
+
*/
|
|
11
|
+
export declare class MultichainAccountWallet<Account extends Bip44Account<KeyringAccount>> implements MultichainAccountWalletDefinition<Account> {
|
|
12
|
+
#private;
|
|
13
|
+
constructor({ providers, entropySource, }: {
|
|
14
|
+
providers: AccountProvider<Account>[];
|
|
15
|
+
entropySource: EntropySourceId;
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Force wallet synchronization.
|
|
19
|
+
*
|
|
20
|
+
* This can be used if account providers got new accounts that the wallet
|
|
21
|
+
* doesn't know about.
|
|
22
|
+
*/
|
|
23
|
+
sync(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Gets the multichain account wallet ID.
|
|
26
|
+
*
|
|
27
|
+
* @returns The multichain account wallet ID.
|
|
28
|
+
*/
|
|
29
|
+
get id(): MultichainAccountWalletId;
|
|
30
|
+
/**
|
|
31
|
+
* Gets the multichain account wallet type, which is always {@link AccountWalletType.Entropy}.
|
|
32
|
+
*
|
|
33
|
+
* @returns The multichain account wallet type.
|
|
34
|
+
*/
|
|
35
|
+
get type(): AccountWalletType.Entropy;
|
|
36
|
+
/**
|
|
37
|
+
* Gets the multichain account wallet entropy source.
|
|
38
|
+
*
|
|
39
|
+
* @returns The multichain account wallet entropy source.
|
|
40
|
+
*/
|
|
41
|
+
get entropySource(): EntropySourceId;
|
|
42
|
+
/**
|
|
43
|
+
* Gets multichain account for a given ID.
|
|
44
|
+
* The default group ID will default to the multichain account with index 0.
|
|
45
|
+
*
|
|
46
|
+
* @param id - Account group ID.
|
|
47
|
+
* @returns Account group.
|
|
48
|
+
*/
|
|
49
|
+
getAccountGroup(id: AccountGroupId): MultichainAccountGroup<Account> | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Gets all multichain accounts. Similar to {@link MultichainAccountWallet.getMultichainAccountGroups}.
|
|
52
|
+
*
|
|
53
|
+
* @returns The multichain accounts.
|
|
54
|
+
*/
|
|
55
|
+
getAccountGroups(): MultichainAccountGroup<Account>[];
|
|
56
|
+
/**
|
|
57
|
+
* Gets multichain account group for a given index.
|
|
58
|
+
*
|
|
59
|
+
* @param groupIndex - Multichain account index.
|
|
60
|
+
* @returns The multichain account associated with the given index.
|
|
61
|
+
*/
|
|
62
|
+
getMultichainAccountGroup(groupIndex: number): MultichainAccountGroup<Account> | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Gets all multichain account groups.
|
|
65
|
+
*
|
|
66
|
+
* @returns The multichain accounts.
|
|
67
|
+
*/
|
|
68
|
+
getMultichainAccountGroups(): MultichainAccountGroup<Account>[];
|
|
69
|
+
/**
|
|
70
|
+
* Gets next group index for this wallet.
|
|
71
|
+
*
|
|
72
|
+
* @returns The next group index of this wallet.
|
|
73
|
+
*/
|
|
74
|
+
getNextGroupIndex(): number;
|
|
75
|
+
/**
|
|
76
|
+
* Creates a multichain account group for a given group index.
|
|
77
|
+
*
|
|
78
|
+
* @param groupIndex - The group index to use.
|
|
79
|
+
* @throws If any of the account providers fails to create their accounts.
|
|
80
|
+
* @returns The multichain account group for this group index.
|
|
81
|
+
*/
|
|
82
|
+
createMultichainAccountGroup(groupIndex: number): Promise<MultichainAccountGroup<Account>>;
|
|
83
|
+
/**
|
|
84
|
+
* Creates the next multichain account group.
|
|
85
|
+
*
|
|
86
|
+
* @throws If any of the account providers fails to create their accounts.
|
|
87
|
+
* @returns The multichain account group for the next group index available.
|
|
88
|
+
*/
|
|
89
|
+
createNextMultichainAccountGroup(): Promise<MultichainAccountGroup<Account>>;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=MultichainAccountWallet.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultichainAccountWallet.d.mts","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,IAAI,iCAAiC,EAC7D,8BAA8B;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,8BAA8B;AAE/B,OAAO,EAAE,sBAAsB,EAAE,qCAAiC;AAElE;;;GAGG;AACH,qBAAa,uBAAuB,CAClC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,iCAAiC,CAAC,OAAO,CAAC;;gBAUzC,EACV,SAAS,EACT,aAAa,GACd,EAAE;QACD,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,aAAa,EAAE,eAAe,CAAC;KAChC;IAUD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IA6CZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,yBAAyB,CAElC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,iBAAiB,CAAC,OAAO,CAEpC;IAED;;;;OAIG;IACH,IAAI,aAAa,IAAI,eAAe,CAEnC;IAED;;;;;;OAMG;IACH,eAAe,CACb,EAAE,EAAE,cAAc,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAgB9C;;;;OAIG;IACH,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAIrD;;;;;OAKG;IACH,yBAAyB,CACvB,UAAU,EAAE,MAAM,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAI9C;;;;OAIG;IACH,0BAA0B,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAI/D;;;;OAIG;IACH,iBAAiB,IAAI,MAAM;IAK3B;;;;;;OAMG;IACG,4BAA4B,CAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IA4E3C;;;;;OAKG;IACG,gCAAgC,IAAI,OAAO,CAC/C,sBAAsB,CAAC,OAAO,CAAC,CAChC;CAGF"}
|