@metamask/multichain-account-service 0.3.0 → 0.5.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 (104) hide show
  1. package/CHANGELOG.md +39 -1
  2. package/dist/MultichainAccountGroup.cjs +182 -0
  3. package/dist/MultichainAccountGroup.cjs.map +1 -0
  4. package/dist/MultichainAccountGroup.d.cts +90 -0
  5. package/dist/MultichainAccountGroup.d.cts.map +1 -0
  6. package/dist/MultichainAccountGroup.d.mts +90 -0
  7. package/dist/MultichainAccountGroup.d.mts.map +1 -0
  8. package/dist/MultichainAccountGroup.mjs +178 -0
  9. package/dist/MultichainAccountGroup.mjs.map +1 -0
  10. package/dist/MultichainAccountService.cjs +71 -24
  11. package/dist/MultichainAccountService.cjs.map +1 -1
  12. package/dist/MultichainAccountService.d.cts +54 -17
  13. package/dist/MultichainAccountService.d.cts.map +1 -1
  14. package/dist/MultichainAccountService.d.mts +54 -17
  15. package/dist/MultichainAccountService.d.mts.map +1 -1
  16. package/dist/MultichainAccountService.mjs +70 -23
  17. package/dist/MultichainAccountService.mjs.map +1 -1
  18. package/dist/MultichainAccountWallet.cjs +264 -0
  19. package/dist/MultichainAccountWallet.cjs.map +1 -0
  20. package/dist/MultichainAccountWallet.d.cts +101 -0
  21. package/dist/MultichainAccountWallet.d.cts.map +1 -0
  22. package/dist/MultichainAccountWallet.d.mts +101 -0
  23. package/dist/MultichainAccountWallet.d.mts.map +1 -0
  24. package/dist/MultichainAccountWallet.mjs +260 -0
  25. package/dist/MultichainAccountWallet.mjs.map +1 -0
  26. package/dist/index.cjs +8 -1
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +4 -1
  29. package/dist/index.d.cts.map +1 -1
  30. package/dist/index.d.mts +4 -1
  31. package/dist/index.d.mts.map +1 -1
  32. package/dist/index.mjs +3 -0
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/providers/BaseAccountProvider.cjs +30 -1
  35. package/dist/providers/BaseAccountProvider.cjs.map +1 -1
  36. package/dist/providers/BaseAccountProvider.d.cts +32 -5
  37. package/dist/providers/BaseAccountProvider.d.cts.map +1 -1
  38. package/dist/providers/BaseAccountProvider.d.mts +32 -5
  39. package/dist/providers/BaseAccountProvider.d.mts.map +1 -1
  40. package/dist/providers/BaseAccountProvider.mjs +27 -0
  41. package/dist/providers/BaseAccountProvider.mjs.map +1 -1
  42. package/dist/providers/EvmAccountProvider.cjs +36 -0
  43. package/dist/providers/EvmAccountProvider.cjs.map +1 -1
  44. package/dist/providers/EvmAccountProvider.d.cts +57 -0
  45. package/dist/providers/EvmAccountProvider.d.cts.map +1 -1
  46. package/dist/providers/EvmAccountProvider.d.mts +57 -0
  47. package/dist/providers/EvmAccountProvider.d.mts.map +1 -1
  48. package/dist/providers/EvmAccountProvider.mjs +37 -1
  49. package/dist/providers/EvmAccountProvider.mjs.map +1 -1
  50. package/dist/providers/SnapAccountProvider.cjs +27 -0
  51. package/dist/providers/SnapAccountProvider.cjs.map +1 -0
  52. package/dist/providers/SnapAccountProvider.d.cts +22 -0
  53. package/dist/providers/SnapAccountProvider.d.cts.map +1 -0
  54. package/dist/providers/SnapAccountProvider.d.mts +22 -0
  55. package/dist/providers/SnapAccountProvider.d.mts.map +1 -0
  56. package/dist/providers/SnapAccountProvider.mjs +23 -0
  57. package/dist/providers/SnapAccountProvider.mjs.map +1 -0
  58. package/dist/providers/SolAccountProvider.cjs +31 -1
  59. package/dist/providers/SolAccountProvider.cjs.map +1 -1
  60. package/dist/providers/SolAccountProvider.d.cts +14 -3
  61. package/dist/providers/SolAccountProvider.d.cts.map +1 -1
  62. package/dist/providers/SolAccountProvider.d.mts +14 -3
  63. package/dist/providers/SolAccountProvider.d.mts.map +1 -1
  64. package/dist/providers/SolAccountProvider.mjs +33 -3
  65. package/dist/providers/SolAccountProvider.mjs.map +1 -1
  66. package/dist/providers/index.cjs +22 -0
  67. package/dist/providers/index.cjs.map +1 -0
  68. package/dist/providers/index.d.cts +5 -0
  69. package/dist/providers/index.d.cts.map +1 -0
  70. package/dist/providers/index.d.mts +5 -0
  71. package/dist/providers/index.d.mts.map +1 -0
  72. package/dist/providers/index.mjs +6 -0
  73. package/dist/providers/index.mjs.map +1 -0
  74. package/dist/tests/accounts.cjs +102 -4
  75. package/dist/tests/accounts.cjs.map +1 -1
  76. package/dist/tests/accounts.d.cts +236 -36
  77. package/dist/tests/accounts.d.cts.map +1 -1
  78. package/dist/tests/accounts.d.mts +236 -36
  79. package/dist/tests/accounts.d.mts.map +1 -1
  80. package/dist/tests/accounts.mjs +101 -4
  81. package/dist/tests/accounts.mjs.map +1 -1
  82. package/dist/tests/index.cjs +1 -0
  83. package/dist/tests/index.cjs.map +1 -1
  84. package/dist/tests/index.d.cts +1 -0
  85. package/dist/tests/index.d.cts.map +1 -1
  86. package/dist/tests/index.d.mts +1 -0
  87. package/dist/tests/index.d.mts.map +1 -1
  88. package/dist/tests/index.mjs +1 -0
  89. package/dist/tests/index.mjs.map +1 -1
  90. package/dist/tests/providers.cjs +28 -0
  91. package/dist/tests/providers.cjs.map +1 -0
  92. package/dist/tests/providers.d.cts +16 -0
  93. package/dist/tests/providers.d.cts.map +1 -0
  94. package/dist/tests/providers.d.mts +16 -0
  95. package/dist/tests/providers.d.mts.map +1 -0
  96. package/dist/tests/providers.mjs +23 -0
  97. package/dist/tests/providers.mjs.map +1 -0
  98. package/dist/types.cjs.map +1 -1
  99. package/dist/types.d.cts +23 -7
  100. package/dist/types.d.cts.map +1 -1
  101. package/dist/types.d.mts +23 -7
  102. package/dist/types.d.mts.map +1 -1
  103. package/dist/types.mjs.map +1 -1
  104. package/package.json +15 -12
package/CHANGELOG.md CHANGED
@@ -7,6 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.5.0]
11
+
12
+ ### Added
13
+
14
+ - Allow for multichain account group alignment through the `align` method ([#6326](https://github.com/MetaMask/core/pull/6326))
15
+ - You can now call alignment from the group, wallet and service levels.
16
+
17
+ ### Changed
18
+
19
+ - **BREAKING:** Bump peer dependency `@metamask/accounts-controller` from `^32.0.0` to `^33.0.0` ([#6345](https://github.com/MetaMask/core/pull/6345))
20
+ - **BREAKING:** Bump peer dependency `@metamask/keyring-controller` from `^22.0.0` to `^23.0.0` ([#6345](https://github.com/MetaMask/core/pull/6345))
21
+ - Bump `@metamask/base-controller` from `^8.0.1` to `^8.1.0` ([#6284](https://github.com/MetaMask/core/pull/6284))
22
+ - Bump accounts related packages ([#6309](https://github.com/MetaMask/core/pull/6309))
23
+ - Bump `@metamask/keyring-api` from `^20.0.0` to `^20.1.0`
24
+ - Bump `@metamask/keyring-internal-api` from `^8.0.0` to `^8.1.0`
25
+ - Bump `@metamask/eth-snap-keyring` from `^16.0.0` to `^16.1.0`
26
+
27
+ ## [0.4.0]
28
+
29
+ ### Added
30
+
31
+ - Allow custom account providers ([#6231](https://github.com/MetaMask/core/pull/6231))
32
+ - You can now pass an extra option `providers` in the service's constructor.
33
+ - Add multichain account group creation support ([#6222](https://github.com/MetaMask/core/pull/6222)), ([#6238](https://github.com/MetaMask/core/pull/6238)), ([#6240](https://github.com/MetaMask/core/pull/6240))
34
+ - This includes the new actions `MultichainAccountService:createNextMultichainAccountGroup` and `MultichainAccountService:createMultichainAccountGroup`.
35
+ - Export `MultichainAccountWallet` and `MultichainAccountGroup` types ([#6220](https://github.com/MetaMask/core/pull/6220))
36
+
37
+ ### Changed
38
+
39
+ - **BREAKING:** Use `KeyringAccount` instead of `InternalAccount` ([#6227](https://github.com/MetaMask/core/pull/6227))
40
+ - **BREAKING:** Bump peer dependency `@metamask/account-api` from `^0.3.0` to `^0.9.0` ([#6214](https://github.com/MetaMask/core/pull/6214)), ([#6216](https://github.com/MetaMask/core/pull/6216)), ([#6222](https://github.com/MetaMask/core/pull/6222)), ([#6248](https://github.com/MetaMask/core/pull/6248))
41
+ - **BREAKING:** Rename `MultichainAccount` to `MultichainAccountGroup` ([#6216](https://github.com/MetaMask/core/pull/6216)), ([#6219](https://github.com/MetaMask/core/pull/6219))
42
+ - The naming was confusing and since a `MultichainAccount` is also an `AccountGroup` it makes sense to have the suffix there too.
43
+ - **BREAKING:** Rename `getMultichainAccount*` to `getMultichainAccountGroup*` ([#6216](https://github.com/MetaMask/core/pull/6216)), ([#6219](https://github.com/MetaMask/core/pull/6219))
44
+ - The naming was confusing and since a `MultichainAccount` is also an `AccountGroup` it makes sense to have the suffix there too.
45
+
10
46
  ## [0.3.0]
11
47
 
12
48
  ### Added
@@ -38,7 +74,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
38
74
  - Add `MultichainAccountService` ([#6141](https://github.com/MetaMask/core/pull/6141)), ([#6165](https://github.com/MetaMask/core/pull/6165))
39
75
  - This service manages multichain accounts/wallets.
40
76
 
41
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/multichain-account-service@0.3.0...HEAD
77
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/multichain-account-service@0.5.0...HEAD
78
+ [0.5.0]: https://github.com/MetaMask/core/compare/@metamask/multichain-account-service@0.4.0...@metamask/multichain-account-service@0.5.0
79
+ [0.4.0]: https://github.com/MetaMask/core/compare/@metamask/multichain-account-service@0.3.0...@metamask/multichain-account-service@0.4.0
42
80
  [0.3.0]: https://github.com/MetaMask/core/compare/@metamask/multichain-account-service@0.2.1...@metamask/multichain-account-service@0.3.0
43
81
  [0.2.1]: https://github.com/MetaMask/core/compare/@metamask/multichain-account-service@0.2.0...@metamask/multichain-account-service@0.2.1
44
82
  [0.2.0]: https://github.com/MetaMask/core/compare/@metamask/multichain-account-service@0.1.0...@metamask/multichain-account-service@0.2.0
@@ -0,0 +1,182 @@
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 _MultichainAccountGroup_id, _MultichainAccountGroup_wallet, _MultichainAccountGroup_groupIndex, _MultichainAccountGroup_providers, _MultichainAccountGroup_providerToAccounts, _MultichainAccountGroup_accountToProvider;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.MultichainAccountGroup = void 0;
16
+ const account_api_1 = require("@metamask/account-api");
17
+ const account_api_2 = require("@metamask/account-api");
18
+ /**
19
+ * A multichain account group that holds multiple accounts.
20
+ */
21
+ class MultichainAccountGroup {
22
+ constructor({ groupIndex, wallet, providers, }) {
23
+ _MultichainAccountGroup_id.set(this, void 0);
24
+ _MultichainAccountGroup_wallet.set(this, void 0);
25
+ _MultichainAccountGroup_groupIndex.set(this, void 0);
26
+ _MultichainAccountGroup_providers.set(this, void 0);
27
+ _MultichainAccountGroup_providerToAccounts.set(this, void 0);
28
+ _MultichainAccountGroup_accountToProvider.set(this, void 0);
29
+ __classPrivateFieldSet(this, _MultichainAccountGroup_id, (0, account_api_2.toMultichainAccountGroupId)(wallet.id, groupIndex), "f");
30
+ __classPrivateFieldSet(this, _MultichainAccountGroup_groupIndex, groupIndex, "f");
31
+ __classPrivateFieldSet(this, _MultichainAccountGroup_wallet, wallet, "f");
32
+ __classPrivateFieldSet(this, _MultichainAccountGroup_providers, providers, "f");
33
+ __classPrivateFieldSet(this, _MultichainAccountGroup_providerToAccounts, new Map(), "f");
34
+ __classPrivateFieldSet(this, _MultichainAccountGroup_accountToProvider, new Map(), "f");
35
+ this.sync();
36
+ }
37
+ /**
38
+ * Force multichain account synchronization.
39
+ *
40
+ * This can be used if account providers got new accounts that the multichain
41
+ * account doesn't know about.
42
+ */
43
+ sync() {
44
+ // Clear reverse mapping and re-construct it entirely based on the refreshed
45
+ // list of accounts from each providers.
46
+ __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").clear();
47
+ for (const provider of __classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")) {
48
+ // Filter account only for that index.
49
+ const accounts = [];
50
+ for (const account of provider.getAccounts()) {
51
+ if (account.options.entropy.id === this.wallet.entropySource &&
52
+ account.options.entropy.groupIndex === this.groupIndex) {
53
+ // We only use IDs to always fetch the latest version of accounts.
54
+ accounts.push(account.id);
55
+ }
56
+ }
57
+ __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").set(provider, accounts);
58
+ // Reverse-mapping for fast indexing.
59
+ for (const id of accounts) {
60
+ __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").set(id, provider);
61
+ }
62
+ }
63
+ }
64
+ /**
65
+ * Gets the multichain account group ID.
66
+ *
67
+ * @returns The multichain account group ID.
68
+ */
69
+ get id() {
70
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_id, "f");
71
+ }
72
+ /**
73
+ * Gets the multichain account group type.
74
+ *
75
+ * @returns The multichain account type.
76
+ */
77
+ get type() {
78
+ return account_api_1.AccountGroupType.MultichainAccount;
79
+ }
80
+ /**
81
+ * Gets the multichain account's wallet reference (parent).
82
+ *
83
+ * @returns The multichain account's wallet.
84
+ */
85
+ get wallet() {
86
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_wallet, "f");
87
+ }
88
+ /**
89
+ * Gets the multichain account group index.
90
+ *
91
+ * @returns The multichain account group index.
92
+ */
93
+ get groupIndex() {
94
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_groupIndex, "f");
95
+ }
96
+ /**
97
+ * Checks if there's any underlying accounts for this multichain accounts.
98
+ *
99
+ * @returns True if there's any underlying accounts, false otherwise.
100
+ */
101
+ hasAccounts() {
102
+ // If there's anything in the reverse-map, it means we have some accounts.
103
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").size > 0;
104
+ }
105
+ /**
106
+ * Gets the accounts for this multichain account.
107
+ *
108
+ * @returns The accounts.
109
+ */
110
+ getAccounts() {
111
+ const allAccounts = [];
112
+ for (const [provider, accounts] of __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").entries()) {
113
+ for (const id of accounts) {
114
+ const account = provider.getAccount(id);
115
+ if (account) {
116
+ // If for some reason we cannot get this account from the provider, it
117
+ // might means it has been deleted or something, so we just filter it
118
+ // out.
119
+ allAccounts.push(account);
120
+ }
121
+ }
122
+ }
123
+ return allAccounts;
124
+ }
125
+ /**
126
+ * Gets the account for a given account ID.
127
+ *
128
+ * @param id - Account ID.
129
+ * @returns The account or undefined if not found.
130
+ */
131
+ getAccount(id) {
132
+ const provider = __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").get(id);
133
+ // If there's nothing in the map, it means we tried to get an account
134
+ // that does not belong to this multichain account.
135
+ if (!provider) {
136
+ return undefined;
137
+ }
138
+ return provider.getAccount(id);
139
+ }
140
+ /**
141
+ * Query an account matching the selector.
142
+ *
143
+ * @param selector - Query selector.
144
+ * @returns The account matching the selector or undefined if not matching.
145
+ * @throws If multiple accounts match the selector.
146
+ */
147
+ get(selector) {
148
+ return (0, account_api_1.selectOne)(this.getAccounts(), selector);
149
+ }
150
+ /**
151
+ * Query accounts matching the selector.
152
+ *
153
+ * @param selector - Query selector.
154
+ * @returns The accounts matching the selector.
155
+ */
156
+ select(selector) {
157
+ return (0, account_api_1.select)(this.getAccounts(), selector);
158
+ }
159
+ /**
160
+ * Align the multichain account group.
161
+ *
162
+ * This will create accounts for providers that don't have any accounts yet.
163
+ */
164
+ async align() {
165
+ const results = await Promise.allSettled(__classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f").map((provider) => {
166
+ const accounts = __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").get(provider);
167
+ if (!accounts || accounts.length === 0) {
168
+ return provider.createAccounts({
169
+ entropySource: this.wallet.entropySource,
170
+ groupIndex: this.groupIndex,
171
+ });
172
+ }
173
+ return Promise.resolve();
174
+ }));
175
+ if (results.some((result) => result.status === 'rejected')) {
176
+ console.warn(`Failed to fully align multichain account group for entropy ID: ${this.wallet.entropySource} and group index: ${this.groupIndex}, some accounts might be missing`);
177
+ }
178
+ }
179
+ }
180
+ exports.MultichainAccountGroup = MultichainAccountGroup;
181
+ _MultichainAccountGroup_id = new WeakMap(), _MultichainAccountGroup_wallet = new WeakMap(), _MultichainAccountGroup_groupIndex = new WeakMap(), _MultichainAccountGroup_providers = new WeakMap(), _MultichainAccountGroup_providerToAccounts = new WeakMap(), _MultichainAccountGroup_accountToProvider = new WeakMap();
182
+ //# sourceMappingURL=MultichainAccountGroup.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MultichainAccountGroup.cjs","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccountGroupType, select, selectOne } from '@metamask/account-api';\nimport {\n toMultichainAccountGroupId,\n type MultichainAccountGroupId,\n type MultichainAccountGroup as MultichainAccountGroupDefinition,\n} from '@metamask/account-api';\nimport type { Bip44Account } from '@metamask/account-api';\nimport type { AccountSelector } from '@metamask/account-api';\nimport type { AccountProvider } from '@metamask/account-api';\nimport { type KeyringAccount } from '@metamask/keyring-api';\n\nimport type { MultichainAccountWallet } from './MultichainAccountWallet';\n\n/**\n * A multichain account group that holds multiple accounts.\n */\nexport class MultichainAccountGroup<\n Account extends Bip44Account<KeyringAccount>,\n> implements MultichainAccountGroupDefinition<Account>\n{\n readonly #id: MultichainAccountGroupId;\n\n readonly #wallet: MultichainAccountWallet<Account>;\n\n readonly #groupIndex: number;\n\n readonly #providers: AccountProvider<Account>[];\n\n readonly #providerToAccounts: Map<AccountProvider<Account>, Account['id'][]>;\n\n readonly #accountToProvider: Map<Account['id'], AccountProvider<Account>>;\n\n constructor({\n groupIndex,\n wallet,\n providers,\n }: {\n groupIndex: number;\n wallet: MultichainAccountWallet<Account>;\n providers: AccountProvider<Account>[];\n }) {\n this.#id = toMultichainAccountGroupId(wallet.id, groupIndex);\n this.#groupIndex = groupIndex;\n this.#wallet = wallet;\n this.#providers = providers;\n this.#providerToAccounts = new Map();\n this.#accountToProvider = new Map();\n\n this.sync();\n }\n\n /**\n * Force multichain account synchronization.\n *\n * This can be used if account providers got new accounts that the multichain\n * account doesn't know about.\n */\n sync(): void {\n // Clear reverse mapping and re-construct it entirely based on the refreshed\n // list of accounts from each providers.\n this.#accountToProvider.clear();\n\n for (const provider of this.#providers) {\n // Filter account only for that index.\n const accounts = [];\n for (const account of provider.getAccounts()) {\n if (\n account.options.entropy.id === this.wallet.entropySource &&\n account.options.entropy.groupIndex === this.groupIndex\n ) {\n // We only use IDs to always fetch the latest version of accounts.\n accounts.push(account.id);\n }\n }\n this.#providerToAccounts.set(provider, accounts);\n\n // Reverse-mapping for fast indexing.\n for (const id of accounts) {\n this.#accountToProvider.set(id, provider);\n }\n }\n }\n\n /**\n * Gets the multichain account group ID.\n *\n * @returns The multichain account group ID.\n */\n get id(): MultichainAccountGroupId {\n return this.#id;\n }\n\n /**\n * Gets the multichain account group type.\n *\n * @returns The multichain account type.\n */\n get type(): AccountGroupType.MultichainAccount {\n return AccountGroupType.MultichainAccount;\n }\n\n /**\n * Gets the multichain account's wallet reference (parent).\n *\n * @returns The multichain account's wallet.\n */\n get wallet(): MultichainAccountWallet<Account> {\n return this.#wallet;\n }\n\n /**\n * Gets the multichain account group index.\n *\n * @returns The multichain account group index.\n */\n get groupIndex(): number {\n return this.#groupIndex;\n }\n\n /**\n * Checks if there's any underlying accounts for this multichain accounts.\n *\n * @returns True if there's any underlying accounts, false otherwise.\n */\n hasAccounts(): boolean {\n // If there's anything in the reverse-map, it means we have some accounts.\n return this.#accountToProvider.size > 0;\n }\n\n /**\n * Gets the accounts for this multichain account.\n *\n * @returns The accounts.\n */\n getAccounts(): Account[] {\n const allAccounts: Account[] = [];\n\n for (const [provider, accounts] of this.#providerToAccounts.entries()) {\n for (const id of accounts) {\n const account = provider.getAccount(id);\n\n if (account) {\n // If for some reason we cannot get this account from the provider, it\n // might means it has been deleted or something, so we just filter it\n // out.\n allAccounts.push(account);\n }\n }\n }\n\n return allAccounts;\n }\n\n /**\n * Gets the account for a given account ID.\n *\n * @param id - Account ID.\n * @returns The account or undefined if not found.\n */\n getAccount(id: Account['id']): Account | undefined {\n const provider = this.#accountToProvider.get(id);\n\n // If there's nothing in the map, it means we tried to get an account\n // that does not belong to this multichain account.\n if (!provider) {\n return undefined;\n }\n return provider.getAccount(id);\n }\n\n /**\n * Query an account matching the selector.\n *\n * @param selector - Query selector.\n * @returns The account matching the selector or undefined if not matching.\n * @throws If multiple accounts match the selector.\n */\n get(selector: AccountSelector<Account>): Account | undefined {\n return selectOne(this.getAccounts(), selector);\n }\n\n /**\n * Query accounts matching the selector.\n *\n * @param selector - Query selector.\n * @returns The accounts matching the selector.\n */\n select(selector: AccountSelector<Account>): Account[] {\n return select(this.getAccounts(), selector);\n }\n\n /**\n * Align the multichain account group.\n *\n * This will create accounts for providers that don't have any accounts yet.\n */\n async align(): Promise<void> {\n const results = await Promise.allSettled(\n this.#providers.map((provider) => {\n const accounts = this.#providerToAccounts.get(provider);\n if (!accounts || accounts.length === 0) {\n return provider.createAccounts({\n entropySource: this.wallet.entropySource,\n groupIndex: this.groupIndex,\n });\n }\n return Promise.resolve();\n }),\n );\n\n if (results.some((result) => result.status === 'rejected')) {\n console.warn(\n `Failed to fully align multichain account group for entropy ID: ${this.wallet.entropySource} and group index: ${this.groupIndex}, some accounts might be missing`,\n );\n }\n }\n}\n"]}
@@ -0,0 +1,90 @@
1
+ import { AccountGroupType } from "@metamask/account-api";
2
+ import { type MultichainAccountGroupId, type MultichainAccountGroup as MultichainAccountGroupDefinition } from "@metamask/account-api";
3
+ import type { Bip44Account } from "@metamask/account-api";
4
+ import type { AccountSelector } from "@metamask/account-api";
5
+ import type { AccountProvider } from "@metamask/account-api";
6
+ import { type KeyringAccount } from "@metamask/keyring-api";
7
+ import type { MultichainAccountWallet } from "./MultichainAccountWallet.cjs";
8
+ /**
9
+ * A multichain account group that holds multiple accounts.
10
+ */
11
+ export declare class MultichainAccountGroup<Account extends Bip44Account<KeyringAccount>> implements MultichainAccountGroupDefinition<Account> {
12
+ #private;
13
+ constructor({ groupIndex, wallet, providers, }: {
14
+ groupIndex: number;
15
+ wallet: MultichainAccountWallet<Account>;
16
+ providers: AccountProvider<Account>[];
17
+ });
18
+ /**
19
+ * Force multichain account synchronization.
20
+ *
21
+ * This can be used if account providers got new accounts that the multichain
22
+ * account doesn't know about.
23
+ */
24
+ sync(): void;
25
+ /**
26
+ * Gets the multichain account group ID.
27
+ *
28
+ * @returns The multichain account group ID.
29
+ */
30
+ get id(): MultichainAccountGroupId;
31
+ /**
32
+ * Gets the multichain account group type.
33
+ *
34
+ * @returns The multichain account type.
35
+ */
36
+ get type(): AccountGroupType.MultichainAccount;
37
+ /**
38
+ * Gets the multichain account's wallet reference (parent).
39
+ *
40
+ * @returns The multichain account's wallet.
41
+ */
42
+ get wallet(): MultichainAccountWallet<Account>;
43
+ /**
44
+ * Gets the multichain account group index.
45
+ *
46
+ * @returns The multichain account group index.
47
+ */
48
+ get groupIndex(): number;
49
+ /**
50
+ * Checks if there's any underlying accounts for this multichain accounts.
51
+ *
52
+ * @returns True if there's any underlying accounts, false otherwise.
53
+ */
54
+ hasAccounts(): boolean;
55
+ /**
56
+ * Gets the accounts for this multichain account.
57
+ *
58
+ * @returns The accounts.
59
+ */
60
+ getAccounts(): Account[];
61
+ /**
62
+ * Gets the account for a given account ID.
63
+ *
64
+ * @param id - Account ID.
65
+ * @returns The account or undefined if not found.
66
+ */
67
+ getAccount(id: Account['id']): Account | undefined;
68
+ /**
69
+ * Query an account matching the selector.
70
+ *
71
+ * @param selector - Query selector.
72
+ * @returns The account matching the selector or undefined if not matching.
73
+ * @throws If multiple accounts match the selector.
74
+ */
75
+ get(selector: AccountSelector<Account>): Account | undefined;
76
+ /**
77
+ * Query accounts matching the selector.
78
+ *
79
+ * @param selector - Query selector.
80
+ * @returns The accounts matching the selector.
81
+ */
82
+ select(selector: AccountSelector<Account>): Account[];
83
+ /**
84
+ * Align the multichain account group.
85
+ *
86
+ * This will create accounts for providers that don't have any accounts yet.
87
+ */
88
+ align(): Promise<void>;
89
+ }
90
+ //# sourceMappingURL=MultichainAccountGroup.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MultichainAccountGroup.d.cts","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAqB,8BAA8B;AAC5E,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,IAAI,gCAAgC,EAChE,8BAA8B;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,EAAE,KAAK,cAAc,EAAE,8BAA8B;AAE5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAkC;AAEzE;;GAEG;AACH,qBAAa,sBAAsB,CACjC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,gCAAgC,CAAC,OAAO,CAAC;;gBAcxC,EACV,UAAU,EACV,MAAM,EACN,SAAS,GACV,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,uBAAuB,CAAC,OAAO,CAAC,CAAC;QACzC,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;KACvC;IAWD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IA0BZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,wBAAwB,CAEjC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,gBAAgB,CAAC,iBAAiB,CAE7C;IAED;;;;OAIG;IACH,IAAI,MAAM,IAAI,uBAAuB,CAAC,OAAO,CAAC,CAE7C;IAED;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;;OAIG;IACH,WAAW,IAAI,OAAO;IAKtB;;;;OAIG;IACH,WAAW,IAAI,OAAO,EAAE;IAmBxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,GAAG,SAAS;IAWlD;;;;;;OAMG;IACH,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,SAAS;IAI5D;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,EAAE;IAIrD;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAoB7B"}
@@ -0,0 +1,90 @@
1
+ import { AccountGroupType } from "@metamask/account-api";
2
+ import { type MultichainAccountGroupId, type MultichainAccountGroup as MultichainAccountGroupDefinition } from "@metamask/account-api";
3
+ import type { Bip44Account } from "@metamask/account-api";
4
+ import type { AccountSelector } from "@metamask/account-api";
5
+ import type { AccountProvider } from "@metamask/account-api";
6
+ import { type KeyringAccount } from "@metamask/keyring-api";
7
+ import type { MultichainAccountWallet } from "./MultichainAccountWallet.mjs";
8
+ /**
9
+ * A multichain account group that holds multiple accounts.
10
+ */
11
+ export declare class MultichainAccountGroup<Account extends Bip44Account<KeyringAccount>> implements MultichainAccountGroupDefinition<Account> {
12
+ #private;
13
+ constructor({ groupIndex, wallet, providers, }: {
14
+ groupIndex: number;
15
+ wallet: MultichainAccountWallet<Account>;
16
+ providers: AccountProvider<Account>[];
17
+ });
18
+ /**
19
+ * Force multichain account synchronization.
20
+ *
21
+ * This can be used if account providers got new accounts that the multichain
22
+ * account doesn't know about.
23
+ */
24
+ sync(): void;
25
+ /**
26
+ * Gets the multichain account group ID.
27
+ *
28
+ * @returns The multichain account group ID.
29
+ */
30
+ get id(): MultichainAccountGroupId;
31
+ /**
32
+ * Gets the multichain account group type.
33
+ *
34
+ * @returns The multichain account type.
35
+ */
36
+ get type(): AccountGroupType.MultichainAccount;
37
+ /**
38
+ * Gets the multichain account's wallet reference (parent).
39
+ *
40
+ * @returns The multichain account's wallet.
41
+ */
42
+ get wallet(): MultichainAccountWallet<Account>;
43
+ /**
44
+ * Gets the multichain account group index.
45
+ *
46
+ * @returns The multichain account group index.
47
+ */
48
+ get groupIndex(): number;
49
+ /**
50
+ * Checks if there's any underlying accounts for this multichain accounts.
51
+ *
52
+ * @returns True if there's any underlying accounts, false otherwise.
53
+ */
54
+ hasAccounts(): boolean;
55
+ /**
56
+ * Gets the accounts for this multichain account.
57
+ *
58
+ * @returns The accounts.
59
+ */
60
+ getAccounts(): Account[];
61
+ /**
62
+ * Gets the account for a given account ID.
63
+ *
64
+ * @param id - Account ID.
65
+ * @returns The account or undefined if not found.
66
+ */
67
+ getAccount(id: Account['id']): Account | undefined;
68
+ /**
69
+ * Query an account matching the selector.
70
+ *
71
+ * @param selector - Query selector.
72
+ * @returns The account matching the selector or undefined if not matching.
73
+ * @throws If multiple accounts match the selector.
74
+ */
75
+ get(selector: AccountSelector<Account>): Account | undefined;
76
+ /**
77
+ * Query accounts matching the selector.
78
+ *
79
+ * @param selector - Query selector.
80
+ * @returns The accounts matching the selector.
81
+ */
82
+ select(selector: AccountSelector<Account>): Account[];
83
+ /**
84
+ * Align the multichain account group.
85
+ *
86
+ * This will create accounts for providers that don't have any accounts yet.
87
+ */
88
+ align(): Promise<void>;
89
+ }
90
+ //# sourceMappingURL=MultichainAccountGroup.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MultichainAccountGroup.d.mts","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAqB,8BAA8B;AAC5E,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,IAAI,gCAAgC,EAChE,8BAA8B;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,EAAE,KAAK,cAAc,EAAE,8BAA8B;AAE5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAkC;AAEzE;;GAEG;AACH,qBAAa,sBAAsB,CACjC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,gCAAgC,CAAC,OAAO,CAAC;;gBAcxC,EACV,UAAU,EACV,MAAM,EACN,SAAS,GACV,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,uBAAuB,CAAC,OAAO,CAAC,CAAC;QACzC,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;KACvC;IAWD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IA0BZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,wBAAwB,CAEjC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,gBAAgB,CAAC,iBAAiB,CAE7C;IAED;;;;OAIG;IACH,IAAI,MAAM,IAAI,uBAAuB,CAAC,OAAO,CAAC,CAE7C;IAED;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;;OAIG;IACH,WAAW,IAAI,OAAO;IAKtB;;;;OAIG;IACH,WAAW,IAAI,OAAO,EAAE;IAmBxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,GAAG,SAAS;IAWlD;;;;;;OAMG;IACH,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,SAAS;IAI5D;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,EAAE;IAIrD;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAoB7B"}
@@ -0,0 +1,178 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ 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");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ 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");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _MultichainAccountGroup_id, _MultichainAccountGroup_wallet, _MultichainAccountGroup_groupIndex, _MultichainAccountGroup_providers, _MultichainAccountGroup_providerToAccounts, _MultichainAccountGroup_accountToProvider;
13
+ import { AccountGroupType, select, selectOne } from "@metamask/account-api";
14
+ import { toMultichainAccountGroupId } from "@metamask/account-api";
15
+ /**
16
+ * A multichain account group that holds multiple accounts.
17
+ */
18
+ export class MultichainAccountGroup {
19
+ constructor({ groupIndex, wallet, providers, }) {
20
+ _MultichainAccountGroup_id.set(this, void 0);
21
+ _MultichainAccountGroup_wallet.set(this, void 0);
22
+ _MultichainAccountGroup_groupIndex.set(this, void 0);
23
+ _MultichainAccountGroup_providers.set(this, void 0);
24
+ _MultichainAccountGroup_providerToAccounts.set(this, void 0);
25
+ _MultichainAccountGroup_accountToProvider.set(this, void 0);
26
+ __classPrivateFieldSet(this, _MultichainAccountGroup_id, toMultichainAccountGroupId(wallet.id, groupIndex), "f");
27
+ __classPrivateFieldSet(this, _MultichainAccountGroup_groupIndex, groupIndex, "f");
28
+ __classPrivateFieldSet(this, _MultichainAccountGroup_wallet, wallet, "f");
29
+ __classPrivateFieldSet(this, _MultichainAccountGroup_providers, providers, "f");
30
+ __classPrivateFieldSet(this, _MultichainAccountGroup_providerToAccounts, new Map(), "f");
31
+ __classPrivateFieldSet(this, _MultichainAccountGroup_accountToProvider, new Map(), "f");
32
+ this.sync();
33
+ }
34
+ /**
35
+ * Force multichain account synchronization.
36
+ *
37
+ * This can be used if account providers got new accounts that the multichain
38
+ * account doesn't know about.
39
+ */
40
+ sync() {
41
+ // Clear reverse mapping and re-construct it entirely based on the refreshed
42
+ // list of accounts from each providers.
43
+ __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").clear();
44
+ for (const provider of __classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")) {
45
+ // Filter account only for that index.
46
+ const accounts = [];
47
+ for (const account of provider.getAccounts()) {
48
+ if (account.options.entropy.id === this.wallet.entropySource &&
49
+ account.options.entropy.groupIndex === this.groupIndex) {
50
+ // We only use IDs to always fetch the latest version of accounts.
51
+ accounts.push(account.id);
52
+ }
53
+ }
54
+ __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").set(provider, accounts);
55
+ // Reverse-mapping for fast indexing.
56
+ for (const id of accounts) {
57
+ __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").set(id, provider);
58
+ }
59
+ }
60
+ }
61
+ /**
62
+ * Gets the multichain account group ID.
63
+ *
64
+ * @returns The multichain account group ID.
65
+ */
66
+ get id() {
67
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_id, "f");
68
+ }
69
+ /**
70
+ * Gets the multichain account group type.
71
+ *
72
+ * @returns The multichain account type.
73
+ */
74
+ get type() {
75
+ return AccountGroupType.MultichainAccount;
76
+ }
77
+ /**
78
+ * Gets the multichain account's wallet reference (parent).
79
+ *
80
+ * @returns The multichain account's wallet.
81
+ */
82
+ get wallet() {
83
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_wallet, "f");
84
+ }
85
+ /**
86
+ * Gets the multichain account group index.
87
+ *
88
+ * @returns The multichain account group index.
89
+ */
90
+ get groupIndex() {
91
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_groupIndex, "f");
92
+ }
93
+ /**
94
+ * Checks if there's any underlying accounts for this multichain accounts.
95
+ *
96
+ * @returns True if there's any underlying accounts, false otherwise.
97
+ */
98
+ hasAccounts() {
99
+ // If there's anything in the reverse-map, it means we have some accounts.
100
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").size > 0;
101
+ }
102
+ /**
103
+ * Gets the accounts for this multichain account.
104
+ *
105
+ * @returns The accounts.
106
+ */
107
+ getAccounts() {
108
+ const allAccounts = [];
109
+ for (const [provider, accounts] of __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").entries()) {
110
+ for (const id of accounts) {
111
+ const account = provider.getAccount(id);
112
+ if (account) {
113
+ // If for some reason we cannot get this account from the provider, it
114
+ // might means it has been deleted or something, so we just filter it
115
+ // out.
116
+ allAccounts.push(account);
117
+ }
118
+ }
119
+ }
120
+ return allAccounts;
121
+ }
122
+ /**
123
+ * Gets the account for a given account ID.
124
+ *
125
+ * @param id - Account ID.
126
+ * @returns The account or undefined if not found.
127
+ */
128
+ getAccount(id) {
129
+ const provider = __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").get(id);
130
+ // If there's nothing in the map, it means we tried to get an account
131
+ // that does not belong to this multichain account.
132
+ if (!provider) {
133
+ return undefined;
134
+ }
135
+ return provider.getAccount(id);
136
+ }
137
+ /**
138
+ * Query an account matching the selector.
139
+ *
140
+ * @param selector - Query selector.
141
+ * @returns The account matching the selector or undefined if not matching.
142
+ * @throws If multiple accounts match the selector.
143
+ */
144
+ get(selector) {
145
+ return selectOne(this.getAccounts(), selector);
146
+ }
147
+ /**
148
+ * Query accounts matching the selector.
149
+ *
150
+ * @param selector - Query selector.
151
+ * @returns The accounts matching the selector.
152
+ */
153
+ select(selector) {
154
+ return select(this.getAccounts(), selector);
155
+ }
156
+ /**
157
+ * Align the multichain account group.
158
+ *
159
+ * This will create accounts for providers that don't have any accounts yet.
160
+ */
161
+ async align() {
162
+ const results = await Promise.allSettled(__classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f").map((provider) => {
163
+ const accounts = __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").get(provider);
164
+ if (!accounts || accounts.length === 0) {
165
+ return provider.createAccounts({
166
+ entropySource: this.wallet.entropySource,
167
+ groupIndex: this.groupIndex,
168
+ });
169
+ }
170
+ return Promise.resolve();
171
+ }));
172
+ if (results.some((result) => result.status === 'rejected')) {
173
+ console.warn(`Failed to fully align multichain account group for entropy ID: ${this.wallet.entropySource} and group index: ${this.groupIndex}, some accounts might be missing`);
174
+ }
175
+ }
176
+ }
177
+ _MultichainAccountGroup_id = new WeakMap(), _MultichainAccountGroup_wallet = new WeakMap(), _MultichainAccountGroup_groupIndex = new WeakMap(), _MultichainAccountGroup_providers = new WeakMap(), _MultichainAccountGroup_providerToAccounts = new WeakMap(), _MultichainAccountGroup_accountToProvider = new WeakMap();
178
+ //# sourceMappingURL=MultichainAccountGroup.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MultichainAccountGroup.mjs","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccountGroupType, select, selectOne } from '@metamask/account-api';\nimport {\n toMultichainAccountGroupId,\n type MultichainAccountGroupId,\n type MultichainAccountGroup as MultichainAccountGroupDefinition,\n} from '@metamask/account-api';\nimport type { Bip44Account } from '@metamask/account-api';\nimport type { AccountSelector } from '@metamask/account-api';\nimport type { AccountProvider } from '@metamask/account-api';\nimport { type KeyringAccount } from '@metamask/keyring-api';\n\nimport type { MultichainAccountWallet } from './MultichainAccountWallet';\n\n/**\n * A multichain account group that holds multiple accounts.\n */\nexport class MultichainAccountGroup<\n Account extends Bip44Account<KeyringAccount>,\n> implements MultichainAccountGroupDefinition<Account>\n{\n readonly #id: MultichainAccountGroupId;\n\n readonly #wallet: MultichainAccountWallet<Account>;\n\n readonly #groupIndex: number;\n\n readonly #providers: AccountProvider<Account>[];\n\n readonly #providerToAccounts: Map<AccountProvider<Account>, Account['id'][]>;\n\n readonly #accountToProvider: Map<Account['id'], AccountProvider<Account>>;\n\n constructor({\n groupIndex,\n wallet,\n providers,\n }: {\n groupIndex: number;\n wallet: MultichainAccountWallet<Account>;\n providers: AccountProvider<Account>[];\n }) {\n this.#id = toMultichainAccountGroupId(wallet.id, groupIndex);\n this.#groupIndex = groupIndex;\n this.#wallet = wallet;\n this.#providers = providers;\n this.#providerToAccounts = new Map();\n this.#accountToProvider = new Map();\n\n this.sync();\n }\n\n /**\n * Force multichain account synchronization.\n *\n * This can be used if account providers got new accounts that the multichain\n * account doesn't know about.\n */\n sync(): void {\n // Clear reverse mapping and re-construct it entirely based on the refreshed\n // list of accounts from each providers.\n this.#accountToProvider.clear();\n\n for (const provider of this.#providers) {\n // Filter account only for that index.\n const accounts = [];\n for (const account of provider.getAccounts()) {\n if (\n account.options.entropy.id === this.wallet.entropySource &&\n account.options.entropy.groupIndex === this.groupIndex\n ) {\n // We only use IDs to always fetch the latest version of accounts.\n accounts.push(account.id);\n }\n }\n this.#providerToAccounts.set(provider, accounts);\n\n // Reverse-mapping for fast indexing.\n for (const id of accounts) {\n this.#accountToProvider.set(id, provider);\n }\n }\n }\n\n /**\n * Gets the multichain account group ID.\n *\n * @returns The multichain account group ID.\n */\n get id(): MultichainAccountGroupId {\n return this.#id;\n }\n\n /**\n * Gets the multichain account group type.\n *\n * @returns The multichain account type.\n */\n get type(): AccountGroupType.MultichainAccount {\n return AccountGroupType.MultichainAccount;\n }\n\n /**\n * Gets the multichain account's wallet reference (parent).\n *\n * @returns The multichain account's wallet.\n */\n get wallet(): MultichainAccountWallet<Account> {\n return this.#wallet;\n }\n\n /**\n * Gets the multichain account group index.\n *\n * @returns The multichain account group index.\n */\n get groupIndex(): number {\n return this.#groupIndex;\n }\n\n /**\n * Checks if there's any underlying accounts for this multichain accounts.\n *\n * @returns True if there's any underlying accounts, false otherwise.\n */\n hasAccounts(): boolean {\n // If there's anything in the reverse-map, it means we have some accounts.\n return this.#accountToProvider.size > 0;\n }\n\n /**\n * Gets the accounts for this multichain account.\n *\n * @returns The accounts.\n */\n getAccounts(): Account[] {\n const allAccounts: Account[] = [];\n\n for (const [provider, accounts] of this.#providerToAccounts.entries()) {\n for (const id of accounts) {\n const account = provider.getAccount(id);\n\n if (account) {\n // If for some reason we cannot get this account from the provider, it\n // might means it has been deleted or something, so we just filter it\n // out.\n allAccounts.push(account);\n }\n }\n }\n\n return allAccounts;\n }\n\n /**\n * Gets the account for a given account ID.\n *\n * @param id - Account ID.\n * @returns The account or undefined if not found.\n */\n getAccount(id: Account['id']): Account | undefined {\n const provider = this.#accountToProvider.get(id);\n\n // If there's nothing in the map, it means we tried to get an account\n // that does not belong to this multichain account.\n if (!provider) {\n return undefined;\n }\n return provider.getAccount(id);\n }\n\n /**\n * Query an account matching the selector.\n *\n * @param selector - Query selector.\n * @returns The account matching the selector or undefined if not matching.\n * @throws If multiple accounts match the selector.\n */\n get(selector: AccountSelector<Account>): Account | undefined {\n return selectOne(this.getAccounts(), selector);\n }\n\n /**\n * Query accounts matching the selector.\n *\n * @param selector - Query selector.\n * @returns The accounts matching the selector.\n */\n select(selector: AccountSelector<Account>): Account[] {\n return select(this.getAccounts(), selector);\n }\n\n /**\n * Align the multichain account group.\n *\n * This will create accounts for providers that don't have any accounts yet.\n */\n async align(): Promise<void> {\n const results = await Promise.allSettled(\n this.#providers.map((provider) => {\n const accounts = this.#providerToAccounts.get(provider);\n if (!accounts || accounts.length === 0) {\n return provider.createAccounts({\n entropySource: this.wallet.entropySource,\n groupIndex: this.groupIndex,\n });\n }\n return Promise.resolve();\n }),\n );\n\n if (results.some((result) => result.status === 'rejected')) {\n console.warn(\n `Failed to fully align multichain account group for entropy ID: ${this.wallet.entropySource} and group index: ${this.groupIndex}, some accounts might be missing`,\n );\n }\n }\n}\n"]}