@metamask-previews/multichain-account-service 0.3.0-preview-0910ff0 → 0.3.0-preview-98faf75a

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 (88) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/MultichainAccountGroup.cjs +192 -0
  3. package/dist/MultichainAccountGroup.cjs.map +1 -0
  4. package/dist/MultichainAccountGroup.d.cts +84 -0
  5. package/dist/MultichainAccountGroup.d.cts.map +1 -0
  6. package/dist/MultichainAccountGroup.d.mts +84 -0
  7. package/dist/MultichainAccountGroup.d.mts.map +1 -0
  8. package/dist/MultichainAccountGroup.mjs +188 -0
  9. package/dist/MultichainAccountGroup.mjs.map +1 -0
  10. package/dist/MultichainAccountService.cjs +36 -23
  11. package/dist/MultichainAccountService.cjs.map +1 -1
  12. package/dist/MultichainAccountService.d.cts +26 -15
  13. package/dist/MultichainAccountService.d.cts.map +1 -1
  14. package/dist/MultichainAccountService.d.mts +26 -15
  15. package/dist/MultichainAccountService.d.mts.map +1 -1
  16. package/dist/MultichainAccountService.mjs +35 -22
  17. package/dist/MultichainAccountService.mjs.map +1 -1
  18. package/dist/MultichainAccountWallet.cjs +237 -0
  19. package/dist/MultichainAccountWallet.cjs.map +1 -0
  20. package/dist/MultichainAccountWallet.d.cts +91 -0
  21. package/dist/MultichainAccountWallet.d.cts.map +1 -0
  22. package/dist/MultichainAccountWallet.d.mts +91 -0
  23. package/dist/MultichainAccountWallet.d.mts.map +1 -0
  24. package/dist/MultichainAccountWallet.mjs +233 -0
  25. package/dist/MultichainAccountWallet.mjs.map +1 -0
  26. package/dist/index.cjs +5 -1
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +3 -1
  29. package/dist/index.d.cts.map +1 -1
  30. package/dist/index.d.mts +3 -1
  31. package/dist/index.d.mts.map +1 -1
  32. package/dist/index.mjs +2 -0
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/providers/BaseAccountProvider.cjs +20 -1
  35. package/dist/providers/BaseAccountProvider.cjs.map +1 -1
  36. package/dist/providers/BaseAccountProvider.d.cts +25 -5
  37. package/dist/providers/BaseAccountProvider.d.cts.map +1 -1
  38. package/dist/providers/BaseAccountProvider.d.mts +25 -5
  39. package/dist/providers/BaseAccountProvider.d.mts.map +1 -1
  40. package/dist/providers/BaseAccountProvider.mjs +18 -0
  41. package/dist/providers/BaseAccountProvider.mjs.map +1 -1
  42. package/dist/providers/EvmAccountProvider.cjs +35 -0
  43. package/dist/providers/EvmAccountProvider.cjs.map +1 -1
  44. package/dist/providers/EvmAccountProvider.d.cts +66 -0
  45. package/dist/providers/EvmAccountProvider.d.cts.map +1 -1
  46. package/dist/providers/EvmAccountProvider.d.mts +66 -0
  47. package/dist/providers/EvmAccountProvider.d.mts.map +1 -1
  48. package/dist/providers/EvmAccountProvider.mjs +36 -1
  49. package/dist/providers/EvmAccountProvider.mjs.map +1 -1
  50. package/dist/providers/SolAccountProvider.cjs +35 -0
  51. package/dist/providers/SolAccountProvider.cjs.map +1 -1
  52. package/dist/providers/SolAccountProvider.d.cts +27 -1
  53. package/dist/providers/SolAccountProvider.d.cts.map +1 -1
  54. package/dist/providers/SolAccountProvider.d.mts +27 -1
  55. package/dist/providers/SolAccountProvider.d.mts.map +1 -1
  56. package/dist/providers/SolAccountProvider.mjs +37 -2
  57. package/dist/providers/SolAccountProvider.mjs.map +1 -1
  58. package/dist/tests/accounts.cjs +89 -4
  59. package/dist/tests/accounts.cjs.map +1 -1
  60. package/dist/tests/accounts.d.cts +235 -36
  61. package/dist/tests/accounts.d.cts.map +1 -1
  62. package/dist/tests/accounts.d.mts +235 -36
  63. package/dist/tests/accounts.d.mts.map +1 -1
  64. package/dist/tests/accounts.mjs +89 -4
  65. package/dist/tests/accounts.mjs.map +1 -1
  66. package/dist/tests/index.cjs +1 -0
  67. package/dist/tests/index.cjs.map +1 -1
  68. package/dist/tests/index.d.cts +1 -0
  69. package/dist/tests/index.d.cts.map +1 -1
  70. package/dist/tests/index.d.mts +1 -0
  71. package/dist/tests/index.d.mts.map +1 -1
  72. package/dist/tests/index.mjs +1 -0
  73. package/dist/tests/index.mjs.map +1 -1
  74. package/dist/tests/providers.cjs +28 -0
  75. package/dist/tests/providers.cjs.map +1 -0
  76. package/dist/tests/providers.d.cts +16 -0
  77. package/dist/tests/providers.d.cts.map +1 -0
  78. package/dist/tests/providers.d.mts +16 -0
  79. package/dist/tests/providers.d.mts.map +1 -0
  80. package/dist/tests/providers.mjs +23 -0
  81. package/dist/tests/providers.mjs.map +1 -0
  82. package/dist/types.cjs.map +1 -1
  83. package/dist/types.d.cts +11 -7
  84. package/dist/types.d.cts.map +1 -1
  85. package/dist/types.d.mts +11 -7
  86. package/dist/types.d.mts.map +1 -1
  87. package/dist/types.mjs.map +1 -1
  88. package/package.json +7 -4
package/CHANGELOG.md CHANGED
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+
12
+ - Add multichain account group creation support ([#6222](https://github.com/MetaMask/core/pull/6222))
13
+ - This also includes the new action `MultichainAccountService:createNextMultichainAccount`.
14
+ - Export `MultichainAccountWallet` and `MultichainAccountGroup` types ([#6220](https://github.com/MetaMask/core/pull/6220))
15
+
16
+ ### Changed
17
+
18
+ - **BREAKING:** Use `KeyringAccount` instead of `InternalAccount` ([#6227](https://github.com/MetaMask/core/pull/6227))
19
+ - **BREAKING:** Bump peer dependency `@metamask/account-api` from `^0.3.0` to `^0.7.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))
20
+ - **BREAKING:** Rename `MultichainAccount` to `MultichainAccountGroup` ([#6216](https://github.com/MetaMask/core/pull/6216)), ([#6219](https://github.com/MetaMask/core/pull/6219))
21
+ - The naming was confusing and since a `MultichainAccount` is also an `AccountGroup` it makes sense to have the suffix there too.
22
+ - **BREAKING:** Rename `getMultichainAccount*` to `getMultichainAccountGroup*` ([#6216](https://github.com/MetaMask/core/pull/6216)), ([#6219](https://github.com/MetaMask/core/pull/6219))
23
+ - The naming was confusing and since a `MultichainAccount` is also an `AccountGroup` it makes sense to have the suffix there too.
24
+
10
25
  ## [0.3.0]
11
26
 
12
27
  ### Added
@@ -0,0 +1,192 @@
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_index, _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
+ const keyring_utils_1 = require("@metamask/keyring-utils");
19
+ /**
20
+ * A multichain account group that holds multiple accounts.
21
+ */
22
+ class MultichainAccountGroup {
23
+ constructor({ groupIndex, wallet, providers, }) {
24
+ _MultichainAccountGroup_id.set(this, void 0);
25
+ _MultichainAccountGroup_wallet.set(this, void 0);
26
+ _MultichainAccountGroup_index.set(this, void 0);
27
+ _MultichainAccountGroup_providers.set(this, void 0);
28
+ _MultichainAccountGroup_providerToAccounts.set(this, void 0);
29
+ _MultichainAccountGroup_accountToProvider.set(this, void 0);
30
+ __classPrivateFieldSet(this, _MultichainAccountGroup_id, (0, account_api_2.toMultichainAccountGroupId)(wallet.id, groupIndex), "f");
31
+ __classPrivateFieldSet(this, _MultichainAccountGroup_index, groupIndex, "f");
32
+ __classPrivateFieldSet(this, _MultichainAccountGroup_wallet, wallet, "f");
33
+ __classPrivateFieldSet(this, _MultichainAccountGroup_providers, providers, "f");
34
+ __classPrivateFieldSet(this, _MultichainAccountGroup_providerToAccounts, new Map(), "f");
35
+ __classPrivateFieldSet(this, _MultichainAccountGroup_accountToProvider, new Map(), "f");
36
+ this.sync();
37
+ }
38
+ /**
39
+ * Force multichain account synchronization.
40
+ *
41
+ * This can be used if account providers got new accounts that the multichain
42
+ * account doesn't know about.
43
+ */
44
+ sync() {
45
+ // Clear reverse mapping and re-construct it entirely based on the refreshed
46
+ // list of accounts from each providers.
47
+ __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").clear();
48
+ for (const provider of __classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")) {
49
+ // Filter account only for that index.
50
+ const accounts = [];
51
+ for (const account of provider.getAccounts()) {
52
+ if (account.options.entropy.id === this.wallet.entropySource &&
53
+ account.options.entropy.groupIndex === this.index) {
54
+ // We only use IDs to always fetch the latest version of accounts.
55
+ accounts.push(account.id);
56
+ }
57
+ }
58
+ __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").set(provider, accounts);
59
+ // Reverse-mapping for fast indexing.
60
+ for (const id of accounts) {
61
+ __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").set(id, provider);
62
+ }
63
+ }
64
+ }
65
+ /**
66
+ * Gets the multichain account group ID.
67
+ *
68
+ * @returns The multichain account group ID.
69
+ */
70
+ get id() {
71
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_id, "f");
72
+ }
73
+ /**
74
+ * Gets the multichain account group type.
75
+ *
76
+ * @returns The multichain account type.
77
+ */
78
+ get type() {
79
+ return account_api_1.AccountGroupType.MultichainAccount;
80
+ }
81
+ /**
82
+ * Gets the multichain account's wallet reference (parent).
83
+ *
84
+ * @returns The multichain account's wallet.
85
+ */
86
+ get wallet() {
87
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_wallet, "f");
88
+ }
89
+ /**
90
+ * Gets the multichain account group index.
91
+ *
92
+ * @returns The multichain account group index.
93
+ */
94
+ get index() {
95
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_index, "f");
96
+ }
97
+ /**
98
+ * Checks if there's any underlying accounts for this multichain accounts.
99
+ *
100
+ * @returns True if there's any underlying accounts, false otherwise.
101
+ */
102
+ hasAccounts() {
103
+ // If there's anything in the reverse-map, it means we have some accounts.
104
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").size > 0;
105
+ }
106
+ /**
107
+ * Gets the accounts for this multichain account.
108
+ *
109
+ * @returns The accounts.
110
+ */
111
+ getAccounts() {
112
+ const allAccounts = [];
113
+ for (const [provider, accounts] of __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").entries()) {
114
+ for (const id of accounts) {
115
+ const account = provider.getAccount(id);
116
+ if (account) {
117
+ // If for some reason we cannot get this account from the provider, it
118
+ // might means it has been deleted or something, so we just filter it
119
+ // out.
120
+ allAccounts.push(account);
121
+ }
122
+ }
123
+ }
124
+ return allAccounts;
125
+ }
126
+ /**
127
+ * Gets the account for a given account ID.
128
+ *
129
+ * @param id - Account ID.
130
+ * @returns The account or undefined if not found.
131
+ */
132
+ getAccount(id) {
133
+ const provider = __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").get(id);
134
+ // If there's nothing in the map, it means we tried to get an account
135
+ // that does not belong to this multichain account.
136
+ if (!provider) {
137
+ return undefined;
138
+ }
139
+ return provider.getAccount(id);
140
+ }
141
+ /**
142
+ * Query an account matching the selector.
143
+ *
144
+ * @param selector - Query selector.
145
+ * @returns The account matching the selector or undefined if not matching.
146
+ * @throws If multiple accounts match the selector.
147
+ */
148
+ get(selector) {
149
+ const accounts = this.select(selector);
150
+ if (accounts.length > 1) {
151
+ throw new Error(`Too many account candidates, expected 1, got: ${accounts.length}`);
152
+ }
153
+ if (accounts.length === 0) {
154
+ return undefined;
155
+ }
156
+ return accounts[0]; // This is safe, see checks above.
157
+ }
158
+ /**
159
+ * Query accounts matching the selector.
160
+ *
161
+ * @param selector - Query selector.
162
+ * @returns The accounts matching the selector.
163
+ */
164
+ select(selector) {
165
+ return this.getAccounts().filter((account) => {
166
+ let selected = true;
167
+ if (selector.id) {
168
+ selected && (selected = account.id === selector.id);
169
+ }
170
+ if (selector.address) {
171
+ selected && (selected = account.address === selector.address);
172
+ }
173
+ if (selector.type) {
174
+ selected && (selected = account.type === selector.type);
175
+ }
176
+ if (selector.methods !== undefined) {
177
+ selected && (selected = selector.methods.some((method) => account.methods.includes(method)));
178
+ }
179
+ if (selector.scopes !== undefined) {
180
+ selected && (selected = selector.scopes.some((scope) => {
181
+ return (
182
+ // This will cover specific EVM EOA scopes as well.
183
+ (0, keyring_utils_1.isScopeEqualToAny)(scope, account.scopes));
184
+ }));
185
+ }
186
+ return selected;
187
+ });
188
+ }
189
+ }
190
+ exports.MultichainAccountGroup = MultichainAccountGroup;
191
+ _MultichainAccountGroup_id = new WeakMap(), _MultichainAccountGroup_wallet = new WeakMap(), _MultichainAccountGroup_index = new WeakMap(), _MultichainAccountGroup_providers = new WeakMap(), _MultichainAccountGroup_providerToAccounts = new WeakMap(), _MultichainAccountGroup_accountToProvider = new WeakMap();
192
+ //# 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 } 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';\nimport { isScopeEqualToAny } from '@metamask/keyring-utils';\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 #index: 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.#index = 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.index\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 index(): number {\n return this.#index;\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 const accounts = this.select(selector);\n\n if (accounts.length > 1) {\n throw new Error(\n `Too many account candidates, expected 1, got: ${accounts.length}`,\n );\n }\n\n if (accounts.length === 0) {\n return undefined;\n }\n\n return accounts[0]; // This is safe, see checks above.\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 this.getAccounts().filter((account) => {\n let selected = true;\n\n if (selector.id) {\n selected &&= account.id === selector.id;\n }\n if (selector.address) {\n selected &&= account.address === selector.address;\n }\n if (selector.type) {\n selected &&= account.type === selector.type;\n }\n if (selector.methods !== undefined) {\n selected &&= selector.methods.some((method) =>\n account.methods.includes(method),\n );\n }\n if (selector.scopes !== undefined) {\n selected &&= selector.scopes.some((scope) => {\n return (\n // This will cover specific EVM EOA scopes as well.\n isScopeEqualToAny(scope, account.scopes)\n );\n });\n }\n\n return selected;\n });\n }\n}\n"]}
@@ -0,0 +1,84 @@
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 index(): 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
+ //# 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,EAAE,8BAA8B;AACzD,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;AAG5D,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,KAAK,IAAI,MAAM,CAElB;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;IAgB5D;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,EAAE;CA8BtD"}
@@ -0,0 +1,84 @@
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 index(): 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
+ //# 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,EAAE,8BAA8B;AACzD,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;AAG5D,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,KAAK,IAAI,MAAM,CAElB;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;IAgB5D;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,EAAE;CA8BtD"}
@@ -0,0 +1,188 @@
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_index, _MultichainAccountGroup_providers, _MultichainAccountGroup_providerToAccounts, _MultichainAccountGroup_accountToProvider;
13
+ import { AccountGroupType } from "@metamask/account-api";
14
+ import { toMultichainAccountGroupId } from "@metamask/account-api";
15
+ import { isScopeEqualToAny } from "@metamask/keyring-utils";
16
+ /**
17
+ * A multichain account group that holds multiple accounts.
18
+ */
19
+ export class MultichainAccountGroup {
20
+ constructor({ groupIndex, wallet, providers, }) {
21
+ _MultichainAccountGroup_id.set(this, void 0);
22
+ _MultichainAccountGroup_wallet.set(this, void 0);
23
+ _MultichainAccountGroup_index.set(this, void 0);
24
+ _MultichainAccountGroup_providers.set(this, void 0);
25
+ _MultichainAccountGroup_providerToAccounts.set(this, void 0);
26
+ _MultichainAccountGroup_accountToProvider.set(this, void 0);
27
+ __classPrivateFieldSet(this, _MultichainAccountGroup_id, toMultichainAccountGroupId(wallet.id, groupIndex), "f");
28
+ __classPrivateFieldSet(this, _MultichainAccountGroup_index, groupIndex, "f");
29
+ __classPrivateFieldSet(this, _MultichainAccountGroup_wallet, wallet, "f");
30
+ __classPrivateFieldSet(this, _MultichainAccountGroup_providers, providers, "f");
31
+ __classPrivateFieldSet(this, _MultichainAccountGroup_providerToAccounts, new Map(), "f");
32
+ __classPrivateFieldSet(this, _MultichainAccountGroup_accountToProvider, new Map(), "f");
33
+ this.sync();
34
+ }
35
+ /**
36
+ * Force multichain account synchronization.
37
+ *
38
+ * This can be used if account providers got new accounts that the multichain
39
+ * account doesn't know about.
40
+ */
41
+ sync() {
42
+ // Clear reverse mapping and re-construct it entirely based on the refreshed
43
+ // list of accounts from each providers.
44
+ __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").clear();
45
+ for (const provider of __classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")) {
46
+ // Filter account only for that index.
47
+ const accounts = [];
48
+ for (const account of provider.getAccounts()) {
49
+ if (account.options.entropy.id === this.wallet.entropySource &&
50
+ account.options.entropy.groupIndex === this.index) {
51
+ // We only use IDs to always fetch the latest version of accounts.
52
+ accounts.push(account.id);
53
+ }
54
+ }
55
+ __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").set(provider, accounts);
56
+ // Reverse-mapping for fast indexing.
57
+ for (const id of accounts) {
58
+ __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").set(id, provider);
59
+ }
60
+ }
61
+ }
62
+ /**
63
+ * Gets the multichain account group ID.
64
+ *
65
+ * @returns The multichain account group ID.
66
+ */
67
+ get id() {
68
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_id, "f");
69
+ }
70
+ /**
71
+ * Gets the multichain account group type.
72
+ *
73
+ * @returns The multichain account type.
74
+ */
75
+ get type() {
76
+ return AccountGroupType.MultichainAccount;
77
+ }
78
+ /**
79
+ * Gets the multichain account's wallet reference (parent).
80
+ *
81
+ * @returns The multichain account's wallet.
82
+ */
83
+ get wallet() {
84
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_wallet, "f");
85
+ }
86
+ /**
87
+ * Gets the multichain account group index.
88
+ *
89
+ * @returns The multichain account group index.
90
+ */
91
+ get index() {
92
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_index, "f");
93
+ }
94
+ /**
95
+ * Checks if there's any underlying accounts for this multichain accounts.
96
+ *
97
+ * @returns True if there's any underlying accounts, false otherwise.
98
+ */
99
+ hasAccounts() {
100
+ // If there's anything in the reverse-map, it means we have some accounts.
101
+ return __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").size > 0;
102
+ }
103
+ /**
104
+ * Gets the accounts for this multichain account.
105
+ *
106
+ * @returns The accounts.
107
+ */
108
+ getAccounts() {
109
+ const allAccounts = [];
110
+ for (const [provider, accounts] of __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").entries()) {
111
+ for (const id of accounts) {
112
+ const account = provider.getAccount(id);
113
+ if (account) {
114
+ // If for some reason we cannot get this account from the provider, it
115
+ // might means it has been deleted or something, so we just filter it
116
+ // out.
117
+ allAccounts.push(account);
118
+ }
119
+ }
120
+ }
121
+ return allAccounts;
122
+ }
123
+ /**
124
+ * Gets the account for a given account ID.
125
+ *
126
+ * @param id - Account ID.
127
+ * @returns The account or undefined if not found.
128
+ */
129
+ getAccount(id) {
130
+ const provider = __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").get(id);
131
+ // If there's nothing in the map, it means we tried to get an account
132
+ // that does not belong to this multichain account.
133
+ if (!provider) {
134
+ return undefined;
135
+ }
136
+ return provider.getAccount(id);
137
+ }
138
+ /**
139
+ * Query an account matching the selector.
140
+ *
141
+ * @param selector - Query selector.
142
+ * @returns The account matching the selector or undefined if not matching.
143
+ * @throws If multiple accounts match the selector.
144
+ */
145
+ get(selector) {
146
+ const accounts = this.select(selector);
147
+ if (accounts.length > 1) {
148
+ throw new Error(`Too many account candidates, expected 1, got: ${accounts.length}`);
149
+ }
150
+ if (accounts.length === 0) {
151
+ return undefined;
152
+ }
153
+ return accounts[0]; // This is safe, see checks above.
154
+ }
155
+ /**
156
+ * Query accounts matching the selector.
157
+ *
158
+ * @param selector - Query selector.
159
+ * @returns The accounts matching the selector.
160
+ */
161
+ select(selector) {
162
+ return this.getAccounts().filter((account) => {
163
+ let selected = true;
164
+ if (selector.id) {
165
+ selected && (selected = account.id === selector.id);
166
+ }
167
+ if (selector.address) {
168
+ selected && (selected = account.address === selector.address);
169
+ }
170
+ if (selector.type) {
171
+ selected && (selected = account.type === selector.type);
172
+ }
173
+ if (selector.methods !== undefined) {
174
+ selected && (selected = selector.methods.some((method) => account.methods.includes(method)));
175
+ }
176
+ if (selector.scopes !== undefined) {
177
+ selected && (selected = selector.scopes.some((scope) => {
178
+ return (
179
+ // This will cover specific EVM EOA scopes as well.
180
+ isScopeEqualToAny(scope, account.scopes));
181
+ }));
182
+ }
183
+ return selected;
184
+ });
185
+ }
186
+ }
187
+ _MultichainAccountGroup_id = new WeakMap(), _MultichainAccountGroup_wallet = new WeakMap(), _MultichainAccountGroup_index = new WeakMap(), _MultichainAccountGroup_providers = new WeakMap(), _MultichainAccountGroup_providerToAccounts = new WeakMap(), _MultichainAccountGroup_accountToProvider = new WeakMap();
188
+ //# 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 } 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';\nimport { isScopeEqualToAny } from '@metamask/keyring-utils';\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 #index: 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.#index = 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.index\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 index(): number {\n return this.#index;\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 const accounts = this.select(selector);\n\n if (accounts.length > 1) {\n throw new Error(\n `Too many account candidates, expected 1, got: ${accounts.length}`,\n );\n }\n\n if (accounts.length === 0) {\n return undefined;\n }\n\n return accounts[0]; // This is safe, see checks above.\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 this.getAccounts().filter((account) => {\n let selected = true;\n\n if (selector.id) {\n selected &&= account.id === selector.id;\n }\n if (selector.address) {\n selected &&= account.address === selector.address;\n }\n if (selector.type) {\n selected &&= account.type === selector.type;\n }\n if (selector.methods !== undefined) {\n selected &&= selector.methods.some((method) =>\n account.methods.includes(method),\n );\n }\n if (selector.scopes !== undefined) {\n selected &&= selector.scopes.some((scope) => {\n return (\n // This will cover specific EVM EOA scopes as well.\n isScopeEqualToAny(scope, account.scopes)\n );\n });\n }\n\n return selected;\n });\n }\n}\n"]}