@metamask/multichain-account-service 7.0.0 → 8.0.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.
- package/CHANGELOG.md +63 -1
- package/dist/MultichainAccountGroup.cjs +4 -69
- package/dist/MultichainAccountGroup.cjs.map +1 -1
- package/dist/MultichainAccountGroup.d.cts +0 -6
- package/dist/MultichainAccountGroup.d.cts.map +1 -1
- package/dist/MultichainAccountGroup.d.mts +0 -6
- package/dist/MultichainAccountGroup.d.mts.map +1 -1
- package/dist/MultichainAccountGroup.mjs +5 -70
- package/dist/MultichainAccountGroup.mjs.map +1 -1
- package/dist/MultichainAccountService-method-action-types.cjs +7 -0
- package/dist/MultichainAccountService-method-action-types.cjs.map +1 -0
- package/dist/MultichainAccountService-method-action-types.d.cts +177 -0
- package/dist/MultichainAccountService-method-action-types.d.cts.map +1 -0
- package/dist/MultichainAccountService-method-action-types.d.mts +177 -0
- package/dist/MultichainAccountService-method-action-types.d.mts.map +1 -0
- package/dist/MultichainAccountService-method-action-types.mjs +6 -0
- package/dist/MultichainAccountService-method-action-types.mjs.map +1 -0
- package/dist/MultichainAccountService.cjs +59 -28
- package/dist/MultichainAccountService.cjs.map +1 -1
- package/dist/MultichainAccountService.d.cts +24 -2
- package/dist/MultichainAccountService.d.cts.map +1 -1
- package/dist/MultichainAccountService.d.mts +24 -2
- package/dist/MultichainAccountService.d.mts.map +1 -1
- package/dist/MultichainAccountService.mjs +60 -29
- package/dist/MultichainAccountService.mjs.map +1 -1
- package/dist/MultichainAccountWallet.cjs +302 -164
- package/dist/MultichainAccountWallet.cjs.map +1 -1
- package/dist/MultichainAccountWallet.d.cts +27 -7
- package/dist/MultichainAccountWallet.d.cts.map +1 -1
- package/dist/MultichainAccountWallet.d.mts +27 -7
- package/dist/MultichainAccountWallet.d.mts.map +1 -1
- package/dist/MultichainAccountWallet.mjs +303 -165
- package/dist/MultichainAccountWallet.mjs.map +1 -1
- package/dist/analytics/perf.cjs +65 -0
- package/dist/analytics/perf.cjs.map +1 -0
- package/dist/analytics/perf.d.cts +34 -0
- package/dist/analytics/perf.d.cts.map +1 -0
- package/dist/analytics/perf.d.mts +34 -0
- package/dist/analytics/perf.d.mts.map +1 -0
- package/dist/analytics/perf.mjs +59 -0
- package/dist/analytics/perf.mjs.map +1 -0
- package/dist/analytics/timer.cjs +14 -0
- package/dist/analytics/timer.cjs.map +1 -0
- package/dist/analytics/timer.d.cts +8 -0
- package/dist/analytics/timer.d.cts.map +1 -0
- package/dist/analytics/timer.d.mts +8 -0
- package/dist/analytics/timer.d.mts.map +1 -0
- package/dist/analytics/timer.mjs +10 -0
- package/dist/analytics/timer.mjs.map +1 -0
- package/dist/analytics/traces.cjs +49 -1
- package/dist/analytics/traces.cjs.map +1 -1
- package/dist/analytics/traces.d.cts +28 -0
- package/dist/analytics/traces.d.cts.map +1 -1
- package/dist/analytics/traces.d.mts +28 -0
- package/dist/analytics/traces.d.mts.map +1 -1
- package/dist/analytics/traces.mjs +46 -0
- package/dist/analytics/traces.mjs.map +1 -1
- package/dist/errors.cjs +32 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +16 -0
- package/dist/errors.d.cts.map +1 -0
- package/dist/errors.d.mts +16 -0
- package/dist/errors.d.mts.map +1 -0
- package/dist/errors.mjs +28 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/logger.cjs +14 -1
- package/dist/logger.cjs.map +1 -1
- package/dist/logger.d.cts +8 -0
- package/dist/logger.d.cts.map +1 -1
- package/dist/logger.d.mts +8 -0
- package/dist/logger.d.mts.map +1 -1
- package/dist/logger.mjs +12 -0
- package/dist/logger.mjs.map +1 -1
- package/dist/providers/AccountProviderWrapper.cjs +5 -6
- package/dist/providers/AccountProviderWrapper.cjs.map +1 -1
- package/dist/providers/AccountProviderWrapper.d.cts +5 -4
- package/dist/providers/AccountProviderWrapper.d.cts.map +1 -1
- package/dist/providers/AccountProviderWrapper.d.mts +5 -4
- package/dist/providers/AccountProviderWrapper.d.mts.map +1 -1
- package/dist/providers/AccountProviderWrapper.mjs +5 -6
- package/dist/providers/AccountProviderWrapper.mjs.map +1 -1
- package/dist/providers/BaseBip44AccountProvider.cjs +0 -10
- package/dist/providers/BaseBip44AccountProvider.cjs.map +1 -1
- package/dist/providers/BaseBip44AccountProvider.d.cts +1 -17
- package/dist/providers/BaseBip44AccountProvider.d.cts.map +1 -1
- package/dist/providers/BaseBip44AccountProvider.d.mts +1 -17
- package/dist/providers/BaseBip44AccountProvider.d.mts.map +1 -1
- package/dist/providers/BaseBip44AccountProvider.mjs +0 -10
- package/dist/providers/BaseBip44AccountProvider.mjs.map +1 -1
- package/dist/providers/BtcAccountProvider.cjs +15 -33
- package/dist/providers/BtcAccountProvider.cjs.map +1 -1
- package/dist/providers/BtcAccountProvider.d.cts +6 -4
- package/dist/providers/BtcAccountProvider.d.cts.map +1 -1
- package/dist/providers/BtcAccountProvider.d.mts +6 -4
- package/dist/providers/BtcAccountProvider.d.mts.map +1 -1
- package/dist/providers/BtcAccountProvider.mjs +16 -34
- package/dist/providers/BtcAccountProvider.mjs.map +1 -1
- package/dist/providers/EvmAccountProvider.cjs +44 -3
- package/dist/providers/EvmAccountProvider.cjs.map +1 -1
- package/dist/providers/EvmAccountProvider.d.cts.map +1 -1
- package/dist/providers/EvmAccountProvider.d.mts.map +1 -1
- package/dist/providers/EvmAccountProvider.mjs +44 -3
- package/dist/providers/EvmAccountProvider.mjs.map +1 -1
- package/dist/providers/SnapAccountProvider.cjs +111 -21
- package/dist/providers/SnapAccountProvider.cjs.map +1 -1
- package/dist/providers/SnapAccountProvider.d.cts +33 -2
- package/dist/providers/SnapAccountProvider.d.cts.map +1 -1
- package/dist/providers/SnapAccountProvider.d.mts +33 -2
- package/dist/providers/SnapAccountProvider.d.mts.map +1 -1
- package/dist/providers/SnapAccountProvider.mjs +113 -23
- package/dist/providers/SnapAccountProvider.mjs.map +1 -1
- package/dist/providers/SolAccountProvider.cjs +31 -39
- package/dist/providers/SolAccountProvider.cjs.map +1 -1
- package/dist/providers/SolAccountProvider.d.cts +10 -3
- package/dist/providers/SolAccountProvider.d.cts.map +1 -1
- package/dist/providers/SolAccountProvider.d.mts +10 -3
- package/dist/providers/SolAccountProvider.d.mts.map +1 -1
- package/dist/providers/SolAccountProvider.mjs +32 -40
- package/dist/providers/SolAccountProvider.mjs.map +1 -1
- package/dist/providers/TrxAccountProvider.cjs +15 -37
- package/dist/providers/TrxAccountProvider.cjs.map +1 -1
- package/dist/providers/TrxAccountProvider.d.cts +6 -4
- package/dist/providers/TrxAccountProvider.d.cts.map +1 -1
- package/dist/providers/TrxAccountProvider.d.mts +6 -4
- package/dist/providers/TrxAccountProvider.d.mts.map +1 -1
- package/dist/providers/TrxAccountProvider.mjs +16 -38
- package/dist/providers/TrxAccountProvider.mjs.map +1 -1
- package/dist/providers/index.cjs +2 -1
- package/dist/providers/index.cjs.map +1 -1
- package/dist/providers/index.d.cts +1 -1
- package/dist/providers/index.d.cts.map +1 -1
- package/dist/providers/index.d.mts +1 -1
- package/dist/providers/index.d.mts.map +1 -1
- package/dist/providers/index.mjs +1 -1
- package/dist/providers/index.mjs.map +1 -1
- package/dist/providers/utils.cjs +15 -5
- package/dist/providers/utils.cjs.map +1 -1
- package/dist/providers/utils.d.cts +9 -2
- package/dist/providers/utils.d.cts.map +1 -1
- package/dist/providers/utils.d.mts +9 -2
- package/dist/providers/utils.d.mts.map +1 -1
- package/dist/providers/utils.mjs +13 -4
- package/dist/providers/utils.mjs.map +1 -1
- package/dist/snaps/SnapPlatformWatcher.cjs +72 -8
- package/dist/snaps/SnapPlatformWatcher.cjs.map +1 -1
- package/dist/snaps/SnapPlatformWatcher.d.cts +15 -1
- package/dist/snaps/SnapPlatformWatcher.d.cts.map +1 -1
- package/dist/snaps/SnapPlatformWatcher.d.mts +15 -1
- package/dist/snaps/SnapPlatformWatcher.d.mts.map +1 -1
- package/dist/snaps/SnapPlatformWatcher.mjs +72 -8
- package/dist/snaps/SnapPlatformWatcher.mjs.map +1 -1
- package/dist/tests/accounts.cjs +7 -1
- package/dist/tests/accounts.cjs.map +1 -1
- package/dist/tests/accounts.d.cts +9 -0
- package/dist/tests/accounts.d.cts.map +1 -1
- package/dist/tests/accounts.d.mts +9 -0
- package/dist/tests/accounts.d.mts.map +1 -1
- package/dist/tests/accounts.mjs +6 -0
- package/dist/tests/accounts.mjs.map +1 -1
- package/dist/tests/index.cjs.map +1 -1
- package/dist/tests/index.d.cts +1 -0
- package/dist/tests/index.d.cts.map +1 -1
- package/dist/tests/index.d.mts +1 -0
- package/dist/tests/index.d.mts.map +1 -1
- package/dist/tests/index.mjs.map +1 -1
- package/dist/tests/providers.cjs +14 -16
- package/dist/tests/providers.cjs.map +1 -1
- package/dist/tests/providers.d.cts +11 -0
- package/dist/tests/providers.d.cts.map +1 -1
- package/dist/tests/providers.d.mts +11 -0
- package/dist/tests/providers.d.mts.map +1 -1
- package/dist/tests/providers.mjs +14 -17
- package/dist/tests/providers.mjs.map +1 -1
- package/dist/tests/types.cjs +3 -0
- package/dist/tests/types.cjs.map +1 -0
- package/dist/tests/types.d.cts +7 -0
- package/dist/tests/types.d.cts.map +1 -0
- package/dist/tests/types.d.mts +7 -0
- package/dist/tests/types.d.mts.map +1 -0
- package/dist/tests/types.mjs +2 -0
- package/dist/tests/types.mjs.map +1 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +13 -54
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +13 -54
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils.cjs +49 -5
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +32 -5
- package/dist/utils.d.cts.map +1 -1
- package/dist/utils.d.mts +32 -5
- package/dist/utils.d.mts.map +1 -1
- package/dist/utils.mjs +45 -4
- package/dist/utils.mjs.map +1 -1
- package/package.json +9 -7
- package/dist/constants/traces.cjs +0 -9
- package/dist/constants/traces.cjs.map +0 -1
- package/dist/constants/traces.d.cts +0 -5
- package/dist/constants/traces.d.cts.map +0 -1
- package/dist/constants/traces.d.mts +0 -5
- package/dist/constants/traces.d.mts.map +0 -1
- package/dist/constants/traces.mjs +0 -6
- package/dist/constants/traces.mjs.map +0 -1
|
@@ -21,7 +21,7 @@ const utils_1 = require("@metamask/utils");
|
|
|
21
21
|
const BaseBip44AccountProvider_1 = require("./BaseBip44AccountProvider.cjs");
|
|
22
22
|
const utils_2 = require("./utils.cjs");
|
|
23
23
|
const analytics_1 = require("../analytics/index.cjs");
|
|
24
|
-
const traces_1 = require("../
|
|
24
|
+
const traces_1 = require("../analytics/traces.cjs");
|
|
25
25
|
const logger_1 = require("../logger.cjs");
|
|
26
26
|
const ETH_MAINNET_CHAIN_ID = '0x1';
|
|
27
27
|
/**
|
|
@@ -53,6 +53,7 @@ class EvmAccountProvider extends BaseBip44AccountProvider_1.BaseBip44AccountProv
|
|
|
53
53
|
scopes: [keyring_api_1.EthScope.Eoa],
|
|
54
54
|
bip44: {
|
|
55
55
|
deriveIndex: true,
|
|
56
|
+
deriveIndexRange: true,
|
|
56
57
|
},
|
|
57
58
|
};
|
|
58
59
|
__classPrivateFieldSet(this, _EvmAccountProvider_config, {
|
|
@@ -90,8 +91,48 @@ class EvmAccountProvider extends BaseBip44AccountProvider_1.BaseBip44AccountProv
|
|
|
90
91
|
async createAccounts(options) {
|
|
91
92
|
(0, keyring_api_1.assertCreateAccountOptionIsSupported)(options, [
|
|
92
93
|
`${keyring_api_1.AccountCreationType.Bip44DeriveIndex}`,
|
|
94
|
+
`${keyring_api_1.AccountCreationType.Bip44DeriveIndexRange}`,
|
|
93
95
|
]);
|
|
94
|
-
const { entropySource
|
|
96
|
+
const { entropySource } = options;
|
|
97
|
+
if (options.type === keyring_api_1.AccountCreationType.Bip44DeriveIndexRange) {
|
|
98
|
+
const { range } = options;
|
|
99
|
+
// Use a single withKeyring call for the entire range.
|
|
100
|
+
const accountIds = await this.withKeyring({ id: entropySource }, async ({ keyring }) => {
|
|
101
|
+
const existing = await keyring.getAccounts();
|
|
102
|
+
// Validate no gaps: we can only create accounts starting from existing.length.
|
|
103
|
+
if (range.from > existing.length) {
|
|
104
|
+
throw new Error(`Bad account creation request, group index range would create gaps (${range.from} (from) > ${existing.length} (next available index))`);
|
|
105
|
+
}
|
|
106
|
+
const result = [];
|
|
107
|
+
// Collect existing accounts within the range.
|
|
108
|
+
for (let groupIndex = range.from; groupIndex <= range.to; groupIndex++) {
|
|
109
|
+
if (groupIndex < existing.length) {
|
|
110
|
+
// Account already exists.
|
|
111
|
+
result.push(__classPrivateFieldGet(this, _EvmAccountProvider_instances, "m", _EvmAccountProvider_getAccountId).call(this, existing[groupIndex]));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Determine if we need to create new accounts.
|
|
115
|
+
const from = Math.max(range.from, existing.length);
|
|
116
|
+
if (from <= range.to) {
|
|
117
|
+
// Calculate how many new accounts to create.
|
|
118
|
+
const accountsToCreate = range.to - existing.length + 1;
|
|
119
|
+
// Create all new accounts in one call.
|
|
120
|
+
const newAccounts = await keyring.addAccounts(accountsToCreate);
|
|
121
|
+
result.push(...newAccounts.map((address) => __classPrivateFieldGet(this, _EvmAccountProvider_instances, "m", _EvmAccountProvider_getAccountId).call(this, address)));
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
});
|
|
125
|
+
const accounts = [];
|
|
126
|
+
for (const account of this.messenger.call('AccountsController:getAccounts', accountIds)) {
|
|
127
|
+
assertInternalAccountExists(account);
|
|
128
|
+
this.accounts.add(account.id);
|
|
129
|
+
accounts.push(account);
|
|
130
|
+
}
|
|
131
|
+
(0, BaseBip44AccountProvider_1.assertAreBip44Accounts)(accounts);
|
|
132
|
+
return accounts;
|
|
133
|
+
}
|
|
134
|
+
// Handle Bip44DeriveIndex (single account creation).
|
|
135
|
+
const { groupIndex } = options;
|
|
95
136
|
const [address] = await __classPrivateFieldGet(this, _EvmAccountProvider_instances, "m", _EvmAccountProvider_createAccount).call(this, {
|
|
96
137
|
entropySource,
|
|
97
138
|
groupIndex,
|
|
@@ -191,7 +232,7 @@ async function _EvmAccountProvider_createAccount({ entropySource, groupIndex, th
|
|
|
191
232
|
*/
|
|
192
233
|
async function _EvmAccountProvider_getTransactionCount(provider, address) {
|
|
193
234
|
const method = 'eth_getTransactionCount';
|
|
194
|
-
const response = await (0, utils_2.withRetry)(() => (0, utils_2.withTimeout)(provider.request({
|
|
235
|
+
const response = await (0, utils_2.withRetry)(() => (0, utils_2.withTimeout)(() => provider.request({
|
|
195
236
|
method,
|
|
196
237
|
params: [address, 'latest'],
|
|
197
238
|
}), __classPrivateFieldGet(this, _EvmAccountProvider_config, "f").discovery.timeoutMs), {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EvmAccountProvider.cjs","sourceRoot":"","sources":["../../src/providers/EvmAccountProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { publicToAddress } from '@ethereumjs/util';\nimport type { Bip44Account } from '@metamask/account-api';\nimport { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type { HdKeyring } from '@metamask/eth-hd-keyring';\nimport type {\n CreateAccountOptions,\n EntropySourceId,\n KeyringAccount,\n KeyringCapabilities,\n} from '@metamask/keyring-api';\nimport {\n AccountCreationType,\n assertCreateAccountOptionIsSupported,\n EthAccountType,\n EthScope,\n} from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type {\n EthKeyring,\n InternalAccount,\n} from '@metamask/keyring-internal-api';\nimport type { Provider } from '@metamask/network-controller';\nimport { add0x, assert, bytesToHex, isStrictHexString } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n assertAreBip44Accounts,\n assertIsBip44Account,\n BaseBip44AccountProvider,\n} from './BaseBip44AccountProvider';\nimport { withRetry, withTimeout } from './utils';\nimport { traceFallback } from '../analytics';\nimport { TraceName } from '../constants/traces';\nimport { projectLogger as log, WARNING_PREFIX } from '../logger';\nimport type { MultichainAccountServiceMessenger } from '../types';\n\nconst ETH_MAINNET_CHAIN_ID = '0x1';\n\n/**\n * Asserts an internal account exists.\n *\n * @param account - The internal account to check.\n * @throws An error if the internal account does not exist.\n */\nfunction assertInternalAccountExists(\n account: InternalAccount | undefined,\n): asserts account is InternalAccount {\n if (!account) {\n throw new Error('Internal account does not exist');\n }\n}\n\nexport type EvmAccountProviderConfig = {\n discovery: {\n enabled?: boolean;\n maxAttempts: number;\n timeoutMs: number;\n backOffMs: number;\n };\n};\n\nexport const EVM_ACCOUNT_PROVIDER_NAME = 'EVM';\n\nexport const EVM_ACCOUNT_PROVIDER_DEFAULT_CONFIG = {\n discovery: {\n maxAttempts: 3,\n timeoutMs: 500,\n backOffMs: 500,\n },\n};\n\nexport class EvmAccountProvider extends BaseBip44AccountProvider {\n static NAME = EVM_ACCOUNT_PROVIDER_NAME;\n\n readonly #config: EvmAccountProviderConfig;\n\n readonly #trace: TraceCallback;\n\n readonly capabilities: KeyringCapabilities = {\n scopes: [EthScope.Eoa],\n bip44: {\n deriveIndex: true,\n },\n };\n\n constructor(\n messenger: MultichainAccountServiceMessenger,\n config: EvmAccountProviderConfig = EVM_ACCOUNT_PROVIDER_DEFAULT_CONFIG,\n trace?: TraceCallback,\n ) {\n super(messenger);\n this.#config = {\n ...config,\n discovery: {\n ...config.discovery,\n enabled: config.discovery.enabled ?? true,\n },\n };\n this.#trace = trace ?? traceFallback;\n }\n\n isAccountCompatible(account: Bip44Account<InternalAccount>): boolean {\n return (\n account.type === EthAccountType.Eoa &&\n account.metadata.keyring.type === (KeyringTypes.hd as string)\n );\n }\n\n getName(): string {\n return EvmAccountProvider.NAME;\n }\n\n /**\n * Get the EVM provider.\n *\n * @returns The EVM provider.\n */\n getEvmProvider(): Provider {\n const networkClientId = this.messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n ETH_MAINNET_CHAIN_ID,\n );\n const { provider } = this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n return provider;\n }\n\n /**\n * Get the account ID for an EVM account.\n *\n * Note: Since the account ID is deterministic at the AccountsController level,\n * we can use this method to get the account ID from the address.\n *\n * @param address - The address of the account.\n * @returns The account ID.\n */\n #getAccountId(address: Hex): string {\n return getUUIDFromAddressOfNormalAccount(address);\n }\n\n /**\n * Create an EVM account.\n *\n * @param opts - The options for the creation of the account.\n * @param opts.entropySource - The entropy source to use for the creation of the account.\n * @param opts.groupIndex - The index of the group to create the account for.\n * @param opts.throwOnGap - Whether to throw an error if the account index is not contiguous.\n * @returns The account ID and a boolean indicating if the account was created.\n */\n async #createAccount({\n entropySource,\n groupIndex,\n throwOnGap = false,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n throwOnGap?: boolean;\n }): Promise<[Hex, boolean]> {\n const result = await this.withKeyring<EthKeyring, [Hex, boolean]>(\n { id: entropySource },\n async ({ keyring }) => {\n const existing = await keyring.getAccounts();\n if (groupIndex < existing.length) {\n return [existing[groupIndex], false];\n }\n\n // If the throwOnGap flag is set, we throw an error to prevent index gaps.\n if (throwOnGap && groupIndex !== existing.length) {\n throw new Error('Trying to create too many accounts');\n }\n\n const [added] = await keyring.addAccounts(1);\n return [added, true];\n },\n );\n\n return result;\n }\n\n /**\n * Create accounts for the EVM provider.\n *\n * @param options - The options for the creation of the accounts.\n * @returns The accounts for the EVM provider.\n */\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n assertCreateAccountOptionIsSupported(options, [\n `${AccountCreationType.Bip44DeriveIndex}`,\n ]);\n\n const { entropySource, groupIndex } = options;\n\n const [address] = await this.#createAccount({\n entropySource,\n groupIndex,\n throwOnGap: true,\n });\n\n const accountId = this.#getAccountId(address);\n\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n accountId,\n );\n\n // We MUST have the associated internal account.\n assertInternalAccountExists(account);\n\n const accountsArray = [account];\n assertAreBip44Accounts(accountsArray);\n\n this.accounts.add(account.id);\n return accountsArray;\n }\n\n /**\n * Get the transaction count for an EVM account.\n * This method uses a retry and timeout mechanism to handle transient failures.\n *\n * @param provider - The provider to use for the transaction count.\n * @param address - The address of the account.\n * @returns The transaction count.\n */\n async #getTransactionCount(\n provider: Provider,\n address: Hex,\n ): Promise<number> {\n const method = 'eth_getTransactionCount';\n\n const response = await withRetry(\n () =>\n withTimeout(\n provider.request({\n method,\n params: [address, 'latest'],\n }),\n this.#config.discovery.timeoutMs,\n ),\n {\n maxAttempts: this.#config.discovery.maxAttempts,\n backOffMs: this.#config.discovery.backOffMs,\n },\n );\n\n // Make sure we got the right response format, if not, we fallback to \"0x0\", to avoid having to deal with `NaN`.\n if (!isStrictHexString(response)) {\n const message = `Received invalid hex response from \"${method}\" request: ${JSON.stringify(response)}`;\n\n log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n\n return 0;\n }\n\n return parseInt(response, 16);\n }\n\n async #getAddressFromGroupIndex({\n entropySource,\n groupIndex,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Hex> {\n // NOTE: To avoid exposing this function at keyring level, we just re-use its internal state\n // and compute the derivation here.\n return await this.withKeyring<HdKeyring, Hex>(\n { id: entropySource },\n async ({ keyring }) => {\n // If the account already exist, do not re-derive and just re-use that account.\n const existing = await keyring.getAccounts();\n if (groupIndex < existing.length) {\n return existing[groupIndex];\n }\n\n // If not, then we just \"peek\" the next address to avoid creating the account.\n assert(keyring.root, 'Expected HD keyring.root to be set');\n const hdKey = keyring.root.deriveChild(groupIndex);\n assert(hdKey.publicKey, 'Expected public key to be set');\n\n return add0x(\n bytesToHex(publicToAddress(hdKey.publicKey, true)).toLowerCase(),\n );\n },\n );\n }\n\n /**\n * Discover and create accounts for the EVM provider.\n *\n * @param opts - The options for the discovery and creation of accounts.\n * @param opts.entropySource - The entropy source to use for the discovery and creation of accounts.\n * @param opts.groupIndex - The index of the group to create the accounts for.\n * @returns The accounts for the EVM provider.\n */\n async discoverAccounts(opts: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Bip44Account<KeyringAccount>[]> {\n return this.#trace(\n {\n name: TraceName.EvmDiscoverAccounts,\n data: {\n provider: this.getName(),\n },\n },\n async () => {\n if (!this.#config.discovery.enabled) {\n return [];\n }\n\n const provider = this.getEvmProvider();\n const { entropySource, groupIndex } = opts;\n\n const addressFromGroupIndex = await this.#getAddressFromGroupIndex({\n entropySource,\n groupIndex,\n });\n\n const count = await this.#getTransactionCount(\n provider,\n addressFromGroupIndex,\n );\n if (count === 0) {\n return [];\n }\n\n // We have some activity on this address, we try to create the account.\n const [address] = await this.#createAccount({\n entropySource,\n groupIndex,\n });\n assert(\n addressFromGroupIndex === address,\n 'Created account does not match address from group index.',\n );\n\n const accoundId = this.#getAccountId(address);\n\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n accoundId,\n );\n assertInternalAccountExists(account);\n assertIsBip44Account(account);\n this.accounts.add(account.id);\n return [account];\n },\n );\n }\n\n async resyncAccounts(): Promise<void> {\n // No-op for the EVM account provider, since keyring accounts are already on\n // the MetaMask side.\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"EvmAccountProvider.cjs","sourceRoot":"","sources":["../../src/providers/EvmAccountProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { publicToAddress } from '@ethereumjs/util';\nimport type { Bip44Account } from '@metamask/account-api';\nimport { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type { HdKeyring } from '@metamask/eth-hd-keyring';\nimport type {\n CreateAccountOptions,\n EntropySourceId,\n KeyringAccount,\n KeyringCapabilities,\n} from '@metamask/keyring-api';\nimport {\n AccountCreationType,\n assertCreateAccountOptionIsSupported,\n EthAccountType,\n EthScope,\n} from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type {\n EthKeyring,\n InternalAccount,\n} from '@metamask/keyring-internal-api';\nimport { AccountId } from '@metamask/keyring-utils';\nimport type { Provider } from '@metamask/network-controller';\nimport { add0x, assert, bytesToHex, isStrictHexString } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n assertAreBip44Accounts,\n assertIsBip44Account,\n BaseBip44AccountProvider,\n} from './BaseBip44AccountProvider';\nimport { withRetry, withTimeout } from './utils';\nimport { traceFallback } from '../analytics';\nimport { TraceName } from '../analytics/traces';\nimport { projectLogger as log, WARNING_PREFIX } from '../logger';\nimport type { MultichainAccountServiceMessenger } from '../types';\n\nconst ETH_MAINNET_CHAIN_ID = '0x1';\n\n/**\n * Asserts an internal account exists.\n *\n * @param account - The internal account to check.\n * @throws An error if the internal account does not exist.\n */\nfunction assertInternalAccountExists(\n account: InternalAccount | undefined,\n): asserts account is InternalAccount {\n if (!account) {\n throw new Error('Internal account does not exist');\n }\n}\n\nexport type EvmAccountProviderConfig = {\n discovery: {\n enabled?: boolean;\n maxAttempts: number;\n timeoutMs: number;\n backOffMs: number;\n };\n};\n\nexport const EVM_ACCOUNT_PROVIDER_NAME = 'EVM';\n\nexport const EVM_ACCOUNT_PROVIDER_DEFAULT_CONFIG = {\n discovery: {\n maxAttempts: 3,\n timeoutMs: 500,\n backOffMs: 500,\n },\n};\n\nexport class EvmAccountProvider extends BaseBip44AccountProvider {\n static NAME = EVM_ACCOUNT_PROVIDER_NAME;\n\n readonly #config: EvmAccountProviderConfig;\n\n readonly #trace: TraceCallback;\n\n readonly capabilities: KeyringCapabilities = {\n scopes: [EthScope.Eoa],\n bip44: {\n deriveIndex: true,\n deriveIndexRange: true,\n },\n };\n\n constructor(\n messenger: MultichainAccountServiceMessenger,\n config: EvmAccountProviderConfig = EVM_ACCOUNT_PROVIDER_DEFAULT_CONFIG,\n trace?: TraceCallback,\n ) {\n super(messenger);\n this.#config = {\n ...config,\n discovery: {\n ...config.discovery,\n enabled: config.discovery.enabled ?? true,\n },\n };\n this.#trace = trace ?? traceFallback;\n }\n\n isAccountCompatible(account: Bip44Account<InternalAccount>): boolean {\n return (\n account.type === EthAccountType.Eoa &&\n account.metadata.keyring.type === (KeyringTypes.hd as string)\n );\n }\n\n getName(): string {\n return EvmAccountProvider.NAME;\n }\n\n /**\n * Get the EVM provider.\n *\n * @returns The EVM provider.\n */\n getEvmProvider(): Provider {\n const networkClientId = this.messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n ETH_MAINNET_CHAIN_ID,\n );\n const { provider } = this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n return provider;\n }\n\n /**\n * Get the account ID for an EVM account.\n *\n * Note: Since the account ID is deterministic at the AccountsController level,\n * we can use this method to get the account ID from the address.\n *\n * @param address - The address of the account.\n * @returns The account ID.\n */\n #getAccountId(address: Hex): string {\n return getUUIDFromAddressOfNormalAccount(address);\n }\n\n /**\n * Create an EVM account.\n *\n * @param opts - The options for the creation of the account.\n * @param opts.entropySource - The entropy source to use for the creation of the account.\n * @param opts.groupIndex - The index of the group to create the account for.\n * @param opts.throwOnGap - Whether to throw an error if the account index is not contiguous.\n * @returns The account ID and a boolean indicating if the account was created.\n */\n async #createAccount({\n entropySource,\n groupIndex,\n throwOnGap = false,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n throwOnGap?: boolean;\n }): Promise<[Hex, boolean]> {\n const result = await this.withKeyring<EthKeyring, [Hex, boolean]>(\n { id: entropySource },\n async ({ keyring }) => {\n const existing = await keyring.getAccounts();\n if (groupIndex < existing.length) {\n return [existing[groupIndex], false];\n }\n\n // If the throwOnGap flag is set, we throw an error to prevent index gaps.\n if (throwOnGap && groupIndex !== existing.length) {\n throw new Error('Trying to create too many accounts');\n }\n\n const [added] = await keyring.addAccounts(1);\n return [added, true];\n },\n );\n\n return result;\n }\n\n /**\n * Create accounts for the EVM provider.\n *\n * @param options - The options for the creation of the accounts.\n * @returns The accounts for the EVM provider.\n */\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n assertCreateAccountOptionIsSupported(options, [\n `${AccountCreationType.Bip44DeriveIndex}`,\n `${AccountCreationType.Bip44DeriveIndexRange}`,\n ]);\n\n const { entropySource } = options;\n\n if (options.type === AccountCreationType.Bip44DeriveIndexRange) {\n const { range } = options;\n\n // Use a single withKeyring call for the entire range.\n const accountIds = await this.withKeyring<EthKeyring, AccountId[]>(\n { id: entropySource },\n async ({ keyring }) => {\n const existing = await keyring.getAccounts();\n\n // Validate no gaps: we can only create accounts starting from existing.length.\n if (range.from > existing.length) {\n throw new Error(\n `Bad account creation request, group index range would create gaps (${range.from} (from) > ${existing.length} (next available index))`,\n );\n }\n\n const result: AccountId[] = [];\n\n // Collect existing accounts within the range.\n for (\n let groupIndex = range.from;\n groupIndex <= range.to;\n groupIndex++\n ) {\n if (groupIndex < existing.length) {\n // Account already exists.\n result.push(this.#getAccountId(existing[groupIndex]));\n }\n }\n\n // Determine if we need to create new accounts.\n const from = Math.max(range.from, existing.length);\n if (from <= range.to) {\n // Calculate how many new accounts to create.\n const accountsToCreate = range.to - existing.length + 1;\n\n // Create all new accounts in one call.\n const newAccounts = await keyring.addAccounts(accountsToCreate);\n result.push(\n ...newAccounts.map((address) => this.#getAccountId(address)),\n );\n }\n\n return result;\n },\n );\n\n const accounts: InternalAccount[] = [];\n for (const account of this.messenger.call(\n 'AccountsController:getAccounts',\n accountIds,\n )) {\n assertInternalAccountExists(account);\n this.accounts.add(account.id);\n accounts.push(account);\n }\n\n assertAreBip44Accounts(accounts);\n return accounts;\n }\n\n // Handle Bip44DeriveIndex (single account creation).\n const { groupIndex } = options;\n\n const [address] = await this.#createAccount({\n entropySource,\n groupIndex,\n throwOnGap: true,\n });\n\n const accountId = this.#getAccountId(address);\n\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n accountId,\n );\n\n // We MUST have the associated internal account.\n assertInternalAccountExists(account);\n\n const accountsArray = [account];\n assertAreBip44Accounts(accountsArray);\n\n this.accounts.add(account.id);\n return accountsArray;\n }\n\n /**\n * Get the transaction count for an EVM account.\n * This method uses a retry and timeout mechanism to handle transient failures.\n *\n * @param provider - The provider to use for the transaction count.\n * @param address - The address of the account.\n * @returns The transaction count.\n */\n async #getTransactionCount(\n provider: Provider,\n address: Hex,\n ): Promise<number> {\n const method = 'eth_getTransactionCount';\n\n const response = await withRetry(\n () =>\n withTimeout(\n () =>\n provider.request({\n method,\n params: [address, 'latest'],\n }),\n this.#config.discovery.timeoutMs,\n ),\n {\n maxAttempts: this.#config.discovery.maxAttempts,\n backOffMs: this.#config.discovery.backOffMs,\n },\n );\n\n // Make sure we got the right response format, if not, we fallback to \"0x0\", to avoid having to deal with `NaN`.\n if (!isStrictHexString(response)) {\n const message = `Received invalid hex response from \"${method}\" request: ${JSON.stringify(response)}`;\n\n log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n\n return 0;\n }\n\n return parseInt(response, 16);\n }\n\n async #getAddressFromGroupIndex({\n entropySource,\n groupIndex,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Hex> {\n // NOTE: To avoid exposing this function at keyring level, we just re-use its internal state\n // and compute the derivation here.\n return await this.withKeyring<HdKeyring, Hex>(\n { id: entropySource },\n async ({ keyring }) => {\n // If the account already exist, do not re-derive and just re-use that account.\n const existing = await keyring.getAccounts();\n if (groupIndex < existing.length) {\n return existing[groupIndex];\n }\n\n // If not, then we just \"peek\" the next address to avoid creating the account.\n assert(keyring.root, 'Expected HD keyring.root to be set');\n const hdKey = keyring.root.deriveChild(groupIndex);\n assert(hdKey.publicKey, 'Expected public key to be set');\n\n return add0x(\n bytesToHex(publicToAddress(hdKey.publicKey, true)).toLowerCase(),\n );\n },\n );\n }\n\n /**\n * Discover and create accounts for the EVM provider.\n *\n * @param opts - The options for the discovery and creation of accounts.\n * @param opts.entropySource - The entropy source to use for the discovery and creation of accounts.\n * @param opts.groupIndex - The index of the group to create the accounts for.\n * @returns The accounts for the EVM provider.\n */\n async discoverAccounts(opts: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Bip44Account<KeyringAccount>[]> {\n return this.#trace(\n {\n name: TraceName.EvmDiscoverAccounts,\n data: {\n provider: this.getName(),\n },\n },\n async () => {\n if (!this.#config.discovery.enabled) {\n return [];\n }\n\n const provider = this.getEvmProvider();\n const { entropySource, groupIndex } = opts;\n\n const addressFromGroupIndex = await this.#getAddressFromGroupIndex({\n entropySource,\n groupIndex,\n });\n\n const count = await this.#getTransactionCount(\n provider,\n addressFromGroupIndex,\n );\n if (count === 0) {\n return [];\n }\n\n // We have some activity on this address, we try to create the account.\n const [address] = await this.#createAccount({\n entropySource,\n groupIndex,\n });\n assert(\n addressFromGroupIndex === address,\n 'Created account does not match address from group index.',\n );\n\n const accoundId = this.#getAccountId(address);\n\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n accoundId,\n );\n assertInternalAccountExists(account);\n assertIsBip44Account(account);\n this.accounts.add(account.id);\n return [account];\n },\n );\n }\n\n async resyncAccounts(): Promise<void> {\n // No-op for the EVM account provider, since keyring accounts are already on\n // the MetaMask side.\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EvmAccountProvider.d.cts","sourceRoot":"","sources":["../../src/providers/EvmAccountProvider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAEhE,OAAO,KAAK,EACV,oBAAoB,EACpB,eAAe,EACf,cAAc,EACd,mBAAmB,EACpB,8BAA8B;AAQ/B,OAAO,KAAK,EAEV,eAAe,EAChB,uCAAuC;
|
|
1
|
+
{"version":3,"file":"EvmAccountProvider.d.cts","sourceRoot":"","sources":["../../src/providers/EvmAccountProvider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAEhE,OAAO,KAAK,EACV,oBAAoB,EACpB,eAAe,EACf,cAAc,EACd,mBAAmB,EACpB,8BAA8B;AAQ/B,OAAO,KAAK,EAEV,eAAe,EAChB,uCAAuC;AAExC,OAAO,KAAK,EAAE,QAAQ,EAAE,qCAAqC;AAI7D,OAAO,EAGL,wBAAwB,EACzB,uCAAmC;AAKpC,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAiB;AAkBlE,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE;QACT,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAQ,CAAC;AAE/C,eAAO,MAAM,mCAAmC;;;;;;CAM/C,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,wBAAwB;;IAC9D,MAAM,CAAC,IAAI,SAA6B;IAMxC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAMxC;gBAGA,SAAS,EAAE,iCAAiC,EAC5C,MAAM,GAAE,wBAA8D,EACtE,KAAK,CAAC,EAAE,aAAa;IAavB,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,eAAe,CAAC,GAAG,OAAO;IAOpE,OAAO,IAAI,MAAM;IAIjB;;;;OAIG;IACH,cAAc,IAAI,QAAQ;IAgE1B;;;;;OAKG;IACG,cAAc,CAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAwK1C;;;;;;;OAOG;IACG,gBAAgB,CAAC,IAAI,EAAE;QAC3B,aAAa,EAAE,eAAe,CAAC;QAC/B,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAqDrC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAItC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EvmAccountProvider.d.mts","sourceRoot":"","sources":["../../src/providers/EvmAccountProvider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAEhE,OAAO,KAAK,EACV,oBAAoB,EACpB,eAAe,EACf,cAAc,EACd,mBAAmB,EACpB,8BAA8B;AAQ/B,OAAO,KAAK,EAEV,eAAe,EAChB,uCAAuC;
|
|
1
|
+
{"version":3,"file":"EvmAccountProvider.d.mts","sourceRoot":"","sources":["../../src/providers/EvmAccountProvider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAEhE,OAAO,KAAK,EACV,oBAAoB,EACpB,eAAe,EACf,cAAc,EACd,mBAAmB,EACpB,8BAA8B;AAQ/B,OAAO,KAAK,EAEV,eAAe,EAChB,uCAAuC;AAExC,OAAO,KAAK,EAAE,QAAQ,EAAE,qCAAqC;AAI7D,OAAO,EAGL,wBAAwB,EACzB,uCAAmC;AAKpC,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAiB;AAkBlE,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE;QACT,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAQ,CAAC;AAE/C,eAAO,MAAM,mCAAmC;;;;;;CAM/C,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,wBAAwB;;IAC9D,MAAM,CAAC,IAAI,SAA6B;IAMxC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAMxC;gBAGA,SAAS,EAAE,iCAAiC,EAC5C,MAAM,GAAE,wBAA8D,EACtE,KAAK,CAAC,EAAE,aAAa;IAavB,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,eAAe,CAAC,GAAG,OAAO;IAOpE,OAAO,IAAI,MAAM;IAIjB;;;;OAIG;IACH,cAAc,IAAI,QAAQ;IAgE1B;;;;;OAKG;IACG,cAAc,CAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAwK1C;;;;;;;OAOG;IACG,gBAAgB,CAAC,IAAI,EAAE;QAC3B,aAAa,EAAE,eAAe,CAAC;QAC/B,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAqDrC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAItC"}
|
|
@@ -18,7 +18,7 @@ import { add0x, assert, bytesToHex, isStrictHexString } from "@metamask/utils";
|
|
|
18
18
|
import { assertAreBip44Accounts, assertIsBip44Account, BaseBip44AccountProvider } from "./BaseBip44AccountProvider.mjs";
|
|
19
19
|
import { withRetry, withTimeout } from "./utils.mjs";
|
|
20
20
|
import { traceFallback } from "../analytics/index.mjs";
|
|
21
|
-
import { TraceName } from "../
|
|
21
|
+
import { TraceName } from "../analytics/traces.mjs";
|
|
22
22
|
import { projectLogger as log, WARNING_PREFIX } from "../logger.mjs";
|
|
23
23
|
const ETH_MAINNET_CHAIN_ID = '0x1';
|
|
24
24
|
/**
|
|
@@ -50,6 +50,7 @@ export class EvmAccountProvider extends BaseBip44AccountProvider {
|
|
|
50
50
|
scopes: [EthScope.Eoa],
|
|
51
51
|
bip44: {
|
|
52
52
|
deriveIndex: true,
|
|
53
|
+
deriveIndexRange: true,
|
|
53
54
|
},
|
|
54
55
|
};
|
|
55
56
|
__classPrivateFieldSet(this, _EvmAccountProvider_config, {
|
|
@@ -87,8 +88,48 @@ export class EvmAccountProvider extends BaseBip44AccountProvider {
|
|
|
87
88
|
async createAccounts(options) {
|
|
88
89
|
assertCreateAccountOptionIsSupported(options, [
|
|
89
90
|
`${AccountCreationType.Bip44DeriveIndex}`,
|
|
91
|
+
`${AccountCreationType.Bip44DeriveIndexRange}`,
|
|
90
92
|
]);
|
|
91
|
-
const { entropySource
|
|
93
|
+
const { entropySource } = options;
|
|
94
|
+
if (options.type === AccountCreationType.Bip44DeriveIndexRange) {
|
|
95
|
+
const { range } = options;
|
|
96
|
+
// Use a single withKeyring call for the entire range.
|
|
97
|
+
const accountIds = await this.withKeyring({ id: entropySource }, async ({ keyring }) => {
|
|
98
|
+
const existing = await keyring.getAccounts();
|
|
99
|
+
// Validate no gaps: we can only create accounts starting from existing.length.
|
|
100
|
+
if (range.from > existing.length) {
|
|
101
|
+
throw new Error(`Bad account creation request, group index range would create gaps (${range.from} (from) > ${existing.length} (next available index))`);
|
|
102
|
+
}
|
|
103
|
+
const result = [];
|
|
104
|
+
// Collect existing accounts within the range.
|
|
105
|
+
for (let groupIndex = range.from; groupIndex <= range.to; groupIndex++) {
|
|
106
|
+
if (groupIndex < existing.length) {
|
|
107
|
+
// Account already exists.
|
|
108
|
+
result.push(__classPrivateFieldGet(this, _EvmAccountProvider_instances, "m", _EvmAccountProvider_getAccountId).call(this, existing[groupIndex]));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Determine if we need to create new accounts.
|
|
112
|
+
const from = Math.max(range.from, existing.length);
|
|
113
|
+
if (from <= range.to) {
|
|
114
|
+
// Calculate how many new accounts to create.
|
|
115
|
+
const accountsToCreate = range.to - existing.length + 1;
|
|
116
|
+
// Create all new accounts in one call.
|
|
117
|
+
const newAccounts = await keyring.addAccounts(accountsToCreate);
|
|
118
|
+
result.push(...newAccounts.map((address) => __classPrivateFieldGet(this, _EvmAccountProvider_instances, "m", _EvmAccountProvider_getAccountId).call(this, address)));
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
});
|
|
122
|
+
const accounts = [];
|
|
123
|
+
for (const account of this.messenger.call('AccountsController:getAccounts', accountIds)) {
|
|
124
|
+
assertInternalAccountExists(account);
|
|
125
|
+
this.accounts.add(account.id);
|
|
126
|
+
accounts.push(account);
|
|
127
|
+
}
|
|
128
|
+
assertAreBip44Accounts(accounts);
|
|
129
|
+
return accounts;
|
|
130
|
+
}
|
|
131
|
+
// Handle Bip44DeriveIndex (single account creation).
|
|
132
|
+
const { groupIndex } = options;
|
|
92
133
|
const [address] = await __classPrivateFieldGet(this, _EvmAccountProvider_instances, "m", _EvmAccountProvider_createAccount).call(this, {
|
|
93
134
|
entropySource,
|
|
94
135
|
groupIndex,
|
|
@@ -187,7 +228,7 @@ async function _EvmAccountProvider_createAccount({ entropySource, groupIndex, th
|
|
|
187
228
|
*/
|
|
188
229
|
async function _EvmAccountProvider_getTransactionCount(provider, address) {
|
|
189
230
|
const method = 'eth_getTransactionCount';
|
|
190
|
-
const response = await withRetry(() => withTimeout(provider.request({
|
|
231
|
+
const response = await withRetry(() => withTimeout(() => provider.request({
|
|
191
232
|
method,
|
|
192
233
|
params: [address, 'latest'],
|
|
193
234
|
}), __classPrivateFieldGet(this, _EvmAccountProvider_config, "f").discovery.timeoutMs), {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EvmAccountProvider.mjs","sourceRoot":"","sources":["../../src/providers/EvmAccountProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { publicToAddress } from '@ethereumjs/util';\nimport type { Bip44Account } from '@metamask/account-api';\nimport { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type { HdKeyring } from '@metamask/eth-hd-keyring';\nimport type {\n CreateAccountOptions,\n EntropySourceId,\n KeyringAccount,\n KeyringCapabilities,\n} from '@metamask/keyring-api';\nimport {\n AccountCreationType,\n assertCreateAccountOptionIsSupported,\n EthAccountType,\n EthScope,\n} from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type {\n EthKeyring,\n InternalAccount,\n} from '@metamask/keyring-internal-api';\nimport type { Provider } from '@metamask/network-controller';\nimport { add0x, assert, bytesToHex, isStrictHexString } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n assertAreBip44Accounts,\n assertIsBip44Account,\n BaseBip44AccountProvider,\n} from './BaseBip44AccountProvider';\nimport { withRetry, withTimeout } from './utils';\nimport { traceFallback } from '../analytics';\nimport { TraceName } from '../constants/traces';\nimport { projectLogger as log, WARNING_PREFIX } from '../logger';\nimport type { MultichainAccountServiceMessenger } from '../types';\n\nconst ETH_MAINNET_CHAIN_ID = '0x1';\n\n/**\n * Asserts an internal account exists.\n *\n * @param account - The internal account to check.\n * @throws An error if the internal account does not exist.\n */\nfunction assertInternalAccountExists(\n account: InternalAccount | undefined,\n): asserts account is InternalAccount {\n if (!account) {\n throw new Error('Internal account does not exist');\n }\n}\n\nexport type EvmAccountProviderConfig = {\n discovery: {\n enabled?: boolean;\n maxAttempts: number;\n timeoutMs: number;\n backOffMs: number;\n };\n};\n\nexport const EVM_ACCOUNT_PROVIDER_NAME = 'EVM';\n\nexport const EVM_ACCOUNT_PROVIDER_DEFAULT_CONFIG = {\n discovery: {\n maxAttempts: 3,\n timeoutMs: 500,\n backOffMs: 500,\n },\n};\n\nexport class EvmAccountProvider extends BaseBip44AccountProvider {\n static NAME = EVM_ACCOUNT_PROVIDER_NAME;\n\n readonly #config: EvmAccountProviderConfig;\n\n readonly #trace: TraceCallback;\n\n readonly capabilities: KeyringCapabilities = {\n scopes: [EthScope.Eoa],\n bip44: {\n deriveIndex: true,\n },\n };\n\n constructor(\n messenger: MultichainAccountServiceMessenger,\n config: EvmAccountProviderConfig = EVM_ACCOUNT_PROVIDER_DEFAULT_CONFIG,\n trace?: TraceCallback,\n ) {\n super(messenger);\n this.#config = {\n ...config,\n discovery: {\n ...config.discovery,\n enabled: config.discovery.enabled ?? true,\n },\n };\n this.#trace = trace ?? traceFallback;\n }\n\n isAccountCompatible(account: Bip44Account<InternalAccount>): boolean {\n return (\n account.type === EthAccountType.Eoa &&\n account.metadata.keyring.type === (KeyringTypes.hd as string)\n );\n }\n\n getName(): string {\n return EvmAccountProvider.NAME;\n }\n\n /**\n * Get the EVM provider.\n *\n * @returns The EVM provider.\n */\n getEvmProvider(): Provider {\n const networkClientId = this.messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n ETH_MAINNET_CHAIN_ID,\n );\n const { provider } = this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n return provider;\n }\n\n /**\n * Get the account ID for an EVM account.\n *\n * Note: Since the account ID is deterministic at the AccountsController level,\n * we can use this method to get the account ID from the address.\n *\n * @param address - The address of the account.\n * @returns The account ID.\n */\n #getAccountId(address: Hex): string {\n return getUUIDFromAddressOfNormalAccount(address);\n }\n\n /**\n * Create an EVM account.\n *\n * @param opts - The options for the creation of the account.\n * @param opts.entropySource - The entropy source to use for the creation of the account.\n * @param opts.groupIndex - The index of the group to create the account for.\n * @param opts.throwOnGap - Whether to throw an error if the account index is not contiguous.\n * @returns The account ID and a boolean indicating if the account was created.\n */\n async #createAccount({\n entropySource,\n groupIndex,\n throwOnGap = false,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n throwOnGap?: boolean;\n }): Promise<[Hex, boolean]> {\n const result = await this.withKeyring<EthKeyring, [Hex, boolean]>(\n { id: entropySource },\n async ({ keyring }) => {\n const existing = await keyring.getAccounts();\n if (groupIndex < existing.length) {\n return [existing[groupIndex], false];\n }\n\n // If the throwOnGap flag is set, we throw an error to prevent index gaps.\n if (throwOnGap && groupIndex !== existing.length) {\n throw new Error('Trying to create too many accounts');\n }\n\n const [added] = await keyring.addAccounts(1);\n return [added, true];\n },\n );\n\n return result;\n }\n\n /**\n * Create accounts for the EVM provider.\n *\n * @param options - The options for the creation of the accounts.\n * @returns The accounts for the EVM provider.\n */\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n assertCreateAccountOptionIsSupported(options, [\n `${AccountCreationType.Bip44DeriveIndex}`,\n ]);\n\n const { entropySource, groupIndex } = options;\n\n const [address] = await this.#createAccount({\n entropySource,\n groupIndex,\n throwOnGap: true,\n });\n\n const accountId = this.#getAccountId(address);\n\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n accountId,\n );\n\n // We MUST have the associated internal account.\n assertInternalAccountExists(account);\n\n const accountsArray = [account];\n assertAreBip44Accounts(accountsArray);\n\n this.accounts.add(account.id);\n return accountsArray;\n }\n\n /**\n * Get the transaction count for an EVM account.\n * This method uses a retry and timeout mechanism to handle transient failures.\n *\n * @param provider - The provider to use for the transaction count.\n * @param address - The address of the account.\n * @returns The transaction count.\n */\n async #getTransactionCount(\n provider: Provider,\n address: Hex,\n ): Promise<number> {\n const method = 'eth_getTransactionCount';\n\n const response = await withRetry(\n () =>\n withTimeout(\n provider.request({\n method,\n params: [address, 'latest'],\n }),\n this.#config.discovery.timeoutMs,\n ),\n {\n maxAttempts: this.#config.discovery.maxAttempts,\n backOffMs: this.#config.discovery.backOffMs,\n },\n );\n\n // Make sure we got the right response format, if not, we fallback to \"0x0\", to avoid having to deal with `NaN`.\n if (!isStrictHexString(response)) {\n const message = `Received invalid hex response from \"${method}\" request: ${JSON.stringify(response)}`;\n\n log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n\n return 0;\n }\n\n return parseInt(response, 16);\n }\n\n async #getAddressFromGroupIndex({\n entropySource,\n groupIndex,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Hex> {\n // NOTE: To avoid exposing this function at keyring level, we just re-use its internal state\n // and compute the derivation here.\n return await this.withKeyring<HdKeyring, Hex>(\n { id: entropySource },\n async ({ keyring }) => {\n // If the account already exist, do not re-derive and just re-use that account.\n const existing = await keyring.getAccounts();\n if (groupIndex < existing.length) {\n return existing[groupIndex];\n }\n\n // If not, then we just \"peek\" the next address to avoid creating the account.\n assert(keyring.root, 'Expected HD keyring.root to be set');\n const hdKey = keyring.root.deriveChild(groupIndex);\n assert(hdKey.publicKey, 'Expected public key to be set');\n\n return add0x(\n bytesToHex(publicToAddress(hdKey.publicKey, true)).toLowerCase(),\n );\n },\n );\n }\n\n /**\n * Discover and create accounts for the EVM provider.\n *\n * @param opts - The options for the discovery and creation of accounts.\n * @param opts.entropySource - The entropy source to use for the discovery and creation of accounts.\n * @param opts.groupIndex - The index of the group to create the accounts for.\n * @returns The accounts for the EVM provider.\n */\n async discoverAccounts(opts: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Bip44Account<KeyringAccount>[]> {\n return this.#trace(\n {\n name: TraceName.EvmDiscoverAccounts,\n data: {\n provider: this.getName(),\n },\n },\n async () => {\n if (!this.#config.discovery.enabled) {\n return [];\n }\n\n const provider = this.getEvmProvider();\n const { entropySource, groupIndex } = opts;\n\n const addressFromGroupIndex = await this.#getAddressFromGroupIndex({\n entropySource,\n groupIndex,\n });\n\n const count = await this.#getTransactionCount(\n provider,\n addressFromGroupIndex,\n );\n if (count === 0) {\n return [];\n }\n\n // We have some activity on this address, we try to create the account.\n const [address] = await this.#createAccount({\n entropySource,\n groupIndex,\n });\n assert(\n addressFromGroupIndex === address,\n 'Created account does not match address from group index.',\n );\n\n const accoundId = this.#getAccountId(address);\n\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n accoundId,\n );\n assertInternalAccountExists(account);\n assertIsBip44Account(account);\n this.accounts.add(account.id);\n return [account];\n },\n );\n }\n\n async resyncAccounts(): Promise<void> {\n // No-op for the EVM account provider, since keyring accounts are already on\n // the MetaMask side.\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"EvmAccountProvider.mjs","sourceRoot":"","sources":["../../src/providers/EvmAccountProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { publicToAddress } from '@ethereumjs/util';\nimport type { Bip44Account } from '@metamask/account-api';\nimport { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type { HdKeyring } from '@metamask/eth-hd-keyring';\nimport type {\n CreateAccountOptions,\n EntropySourceId,\n KeyringAccount,\n KeyringCapabilities,\n} from '@metamask/keyring-api';\nimport {\n AccountCreationType,\n assertCreateAccountOptionIsSupported,\n EthAccountType,\n EthScope,\n} from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type {\n EthKeyring,\n InternalAccount,\n} from '@metamask/keyring-internal-api';\nimport { AccountId } from '@metamask/keyring-utils';\nimport type { Provider } from '@metamask/network-controller';\nimport { add0x, assert, bytesToHex, isStrictHexString } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n assertAreBip44Accounts,\n assertIsBip44Account,\n BaseBip44AccountProvider,\n} from './BaseBip44AccountProvider';\nimport { withRetry, withTimeout } from './utils';\nimport { traceFallback } from '../analytics';\nimport { TraceName } from '../analytics/traces';\nimport { projectLogger as log, WARNING_PREFIX } from '../logger';\nimport type { MultichainAccountServiceMessenger } from '../types';\n\nconst ETH_MAINNET_CHAIN_ID = '0x1';\n\n/**\n * Asserts an internal account exists.\n *\n * @param account - The internal account to check.\n * @throws An error if the internal account does not exist.\n */\nfunction assertInternalAccountExists(\n account: InternalAccount | undefined,\n): asserts account is InternalAccount {\n if (!account) {\n throw new Error('Internal account does not exist');\n }\n}\n\nexport type EvmAccountProviderConfig = {\n discovery: {\n enabled?: boolean;\n maxAttempts: number;\n timeoutMs: number;\n backOffMs: number;\n };\n};\n\nexport const EVM_ACCOUNT_PROVIDER_NAME = 'EVM';\n\nexport const EVM_ACCOUNT_PROVIDER_DEFAULT_CONFIG = {\n discovery: {\n maxAttempts: 3,\n timeoutMs: 500,\n backOffMs: 500,\n },\n};\n\nexport class EvmAccountProvider extends BaseBip44AccountProvider {\n static NAME = EVM_ACCOUNT_PROVIDER_NAME;\n\n readonly #config: EvmAccountProviderConfig;\n\n readonly #trace: TraceCallback;\n\n readonly capabilities: KeyringCapabilities = {\n scopes: [EthScope.Eoa],\n bip44: {\n deriveIndex: true,\n deriveIndexRange: true,\n },\n };\n\n constructor(\n messenger: MultichainAccountServiceMessenger,\n config: EvmAccountProviderConfig = EVM_ACCOUNT_PROVIDER_DEFAULT_CONFIG,\n trace?: TraceCallback,\n ) {\n super(messenger);\n this.#config = {\n ...config,\n discovery: {\n ...config.discovery,\n enabled: config.discovery.enabled ?? true,\n },\n };\n this.#trace = trace ?? traceFallback;\n }\n\n isAccountCompatible(account: Bip44Account<InternalAccount>): boolean {\n return (\n account.type === EthAccountType.Eoa &&\n account.metadata.keyring.type === (KeyringTypes.hd as string)\n );\n }\n\n getName(): string {\n return EvmAccountProvider.NAME;\n }\n\n /**\n * Get the EVM provider.\n *\n * @returns The EVM provider.\n */\n getEvmProvider(): Provider {\n const networkClientId = this.messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n ETH_MAINNET_CHAIN_ID,\n );\n const { provider } = this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n return provider;\n }\n\n /**\n * Get the account ID for an EVM account.\n *\n * Note: Since the account ID is deterministic at the AccountsController level,\n * we can use this method to get the account ID from the address.\n *\n * @param address - The address of the account.\n * @returns The account ID.\n */\n #getAccountId(address: Hex): string {\n return getUUIDFromAddressOfNormalAccount(address);\n }\n\n /**\n * Create an EVM account.\n *\n * @param opts - The options for the creation of the account.\n * @param opts.entropySource - The entropy source to use for the creation of the account.\n * @param opts.groupIndex - The index of the group to create the account for.\n * @param opts.throwOnGap - Whether to throw an error if the account index is not contiguous.\n * @returns The account ID and a boolean indicating if the account was created.\n */\n async #createAccount({\n entropySource,\n groupIndex,\n throwOnGap = false,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n throwOnGap?: boolean;\n }): Promise<[Hex, boolean]> {\n const result = await this.withKeyring<EthKeyring, [Hex, boolean]>(\n { id: entropySource },\n async ({ keyring }) => {\n const existing = await keyring.getAccounts();\n if (groupIndex < existing.length) {\n return [existing[groupIndex], false];\n }\n\n // If the throwOnGap flag is set, we throw an error to prevent index gaps.\n if (throwOnGap && groupIndex !== existing.length) {\n throw new Error('Trying to create too many accounts');\n }\n\n const [added] = await keyring.addAccounts(1);\n return [added, true];\n },\n );\n\n return result;\n }\n\n /**\n * Create accounts for the EVM provider.\n *\n * @param options - The options for the creation of the accounts.\n * @returns The accounts for the EVM provider.\n */\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n assertCreateAccountOptionIsSupported(options, [\n `${AccountCreationType.Bip44DeriveIndex}`,\n `${AccountCreationType.Bip44DeriveIndexRange}`,\n ]);\n\n const { entropySource } = options;\n\n if (options.type === AccountCreationType.Bip44DeriveIndexRange) {\n const { range } = options;\n\n // Use a single withKeyring call for the entire range.\n const accountIds = await this.withKeyring<EthKeyring, AccountId[]>(\n { id: entropySource },\n async ({ keyring }) => {\n const existing = await keyring.getAccounts();\n\n // Validate no gaps: we can only create accounts starting from existing.length.\n if (range.from > existing.length) {\n throw new Error(\n `Bad account creation request, group index range would create gaps (${range.from} (from) > ${existing.length} (next available index))`,\n );\n }\n\n const result: AccountId[] = [];\n\n // Collect existing accounts within the range.\n for (\n let groupIndex = range.from;\n groupIndex <= range.to;\n groupIndex++\n ) {\n if (groupIndex < existing.length) {\n // Account already exists.\n result.push(this.#getAccountId(existing[groupIndex]));\n }\n }\n\n // Determine if we need to create new accounts.\n const from = Math.max(range.from, existing.length);\n if (from <= range.to) {\n // Calculate how many new accounts to create.\n const accountsToCreate = range.to - existing.length + 1;\n\n // Create all new accounts in one call.\n const newAccounts = await keyring.addAccounts(accountsToCreate);\n result.push(\n ...newAccounts.map((address) => this.#getAccountId(address)),\n );\n }\n\n return result;\n },\n );\n\n const accounts: InternalAccount[] = [];\n for (const account of this.messenger.call(\n 'AccountsController:getAccounts',\n accountIds,\n )) {\n assertInternalAccountExists(account);\n this.accounts.add(account.id);\n accounts.push(account);\n }\n\n assertAreBip44Accounts(accounts);\n return accounts;\n }\n\n // Handle Bip44DeriveIndex (single account creation).\n const { groupIndex } = options;\n\n const [address] = await this.#createAccount({\n entropySource,\n groupIndex,\n throwOnGap: true,\n });\n\n const accountId = this.#getAccountId(address);\n\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n accountId,\n );\n\n // We MUST have the associated internal account.\n assertInternalAccountExists(account);\n\n const accountsArray = [account];\n assertAreBip44Accounts(accountsArray);\n\n this.accounts.add(account.id);\n return accountsArray;\n }\n\n /**\n * Get the transaction count for an EVM account.\n * This method uses a retry and timeout mechanism to handle transient failures.\n *\n * @param provider - The provider to use for the transaction count.\n * @param address - The address of the account.\n * @returns The transaction count.\n */\n async #getTransactionCount(\n provider: Provider,\n address: Hex,\n ): Promise<number> {\n const method = 'eth_getTransactionCount';\n\n const response = await withRetry(\n () =>\n withTimeout(\n () =>\n provider.request({\n method,\n params: [address, 'latest'],\n }),\n this.#config.discovery.timeoutMs,\n ),\n {\n maxAttempts: this.#config.discovery.maxAttempts,\n backOffMs: this.#config.discovery.backOffMs,\n },\n );\n\n // Make sure we got the right response format, if not, we fallback to \"0x0\", to avoid having to deal with `NaN`.\n if (!isStrictHexString(response)) {\n const message = `Received invalid hex response from \"${method}\" request: ${JSON.stringify(response)}`;\n\n log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n\n return 0;\n }\n\n return parseInt(response, 16);\n }\n\n async #getAddressFromGroupIndex({\n entropySource,\n groupIndex,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Hex> {\n // NOTE: To avoid exposing this function at keyring level, we just re-use its internal state\n // and compute the derivation here.\n return await this.withKeyring<HdKeyring, Hex>(\n { id: entropySource },\n async ({ keyring }) => {\n // If the account already exist, do not re-derive and just re-use that account.\n const existing = await keyring.getAccounts();\n if (groupIndex < existing.length) {\n return existing[groupIndex];\n }\n\n // If not, then we just \"peek\" the next address to avoid creating the account.\n assert(keyring.root, 'Expected HD keyring.root to be set');\n const hdKey = keyring.root.deriveChild(groupIndex);\n assert(hdKey.publicKey, 'Expected public key to be set');\n\n return add0x(\n bytesToHex(publicToAddress(hdKey.publicKey, true)).toLowerCase(),\n );\n },\n );\n }\n\n /**\n * Discover and create accounts for the EVM provider.\n *\n * @param opts - The options for the discovery and creation of accounts.\n * @param opts.entropySource - The entropy source to use for the discovery and creation of accounts.\n * @param opts.groupIndex - The index of the group to create the accounts for.\n * @returns The accounts for the EVM provider.\n */\n async discoverAccounts(opts: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Bip44Account<KeyringAccount>[]> {\n return this.#trace(\n {\n name: TraceName.EvmDiscoverAccounts,\n data: {\n provider: this.getName(),\n },\n },\n async () => {\n if (!this.#config.discovery.enabled) {\n return [];\n }\n\n const provider = this.getEvmProvider();\n const { entropySource, groupIndex } = opts;\n\n const addressFromGroupIndex = await this.#getAddressFromGroupIndex({\n entropySource,\n groupIndex,\n });\n\n const count = await this.#getTransactionCount(\n provider,\n addressFromGroupIndex,\n );\n if (count === 0) {\n return [];\n }\n\n // We have some activity on this address, we try to create the account.\n const [address] = await this.#createAccount({\n entropySource,\n groupIndex,\n });\n assert(\n addressFromGroupIndex === address,\n 'Created account does not match address from group index.',\n );\n\n const accoundId = this.#getAccountId(address);\n\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n accoundId,\n );\n assertInternalAccountExists(account);\n assertIsBip44Account(account);\n this.accounts.add(account.id);\n return [account];\n },\n );\n }\n\n async resyncAccounts(): Promise<void> {\n // No-op for the EVM account provider, since keyring accounts are already on\n // the MetaMask side.\n }\n}\n"]}
|
|
@@ -13,14 +13,17 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
13
13
|
var _SnapAccountProvider_instances, _SnapAccountProvider_client, _SnapAccountProvider_queue, _SnapAccountProvider_trace, _SnapAccountProvider_getRestrictedSnapKeyring, _SnapAccountProvider_getKeyringClientFromSnapId, _SnapAccountProvider_withSnapKeyring;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.isSnapAccountProvider = exports.SnapAccountProvider = void 0;
|
|
16
|
+
const account_api_1 = require("@metamask/account-api");
|
|
16
17
|
const keyring_api_1 = require("@metamask/keyring-api");
|
|
17
18
|
const keyring_controller_1 = require("@metamask/keyring-controller");
|
|
18
19
|
const keyring_snap_client_1 = require("@metamask/keyring-snap-client");
|
|
19
20
|
const snaps_utils_1 = require("@metamask/snaps-utils");
|
|
20
21
|
const async_mutex_1 = require("async-mutex");
|
|
21
22
|
const BaseBip44AccountProvider_1 = require("./BaseBip44AccountProvider.cjs");
|
|
23
|
+
const utils_1 = require("./utils.cjs");
|
|
22
24
|
const analytics_1 = require("../analytics/index.cjs");
|
|
23
|
-
const
|
|
25
|
+
const errors_1 = require("../errors.cjs");
|
|
26
|
+
const logger_1 = require("../logger.cjs");
|
|
24
27
|
class SnapAccountProvider extends BaseBip44AccountProvider_1.BaseBip44AccountProvider {
|
|
25
28
|
constructor(snapId, messenger, config,
|
|
26
29
|
/* istanbul ignore next */
|
|
@@ -80,24 +83,35 @@ class SnapAccountProvider extends BaseBip44AccountProvider_1.BaseBip44AccountPro
|
|
|
80
83
|
// NOTE: This should never happen, but if it does, we recover by deleting the
|
|
81
84
|
// extra accounts from the Snap to bring it back in sync with MetaMask.
|
|
82
85
|
if (localSnapAccounts.length < snapAccounts.size) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
const autoRemoveExtraSnapAccounts = this.config.resyncAccounts?.autoRemoveExtraSnapAccounts ?? true;
|
|
87
|
+
if (autoRemoveExtraSnapAccounts) {
|
|
88
|
+
// Build a set of local account IDs for quick lookup
|
|
89
|
+
const localAccountIds = new Set(localSnapAccounts.map((account) => account.id));
|
|
90
|
+
// Find and delete accounts that exist in Snap but not in MetaMask
|
|
91
|
+
await Promise.all([...snapAccounts].map(async (snapAccountId) => {
|
|
92
|
+
try {
|
|
93
|
+
if (!localAccountIds.has(snapAccountId)) {
|
|
94
|
+
// This account exists in the Snap but not in MetaMask, delete it from
|
|
95
|
+
// the Snap.
|
|
96
|
+
await __classPrivateFieldGet(this, _SnapAccountProvider_client, "f").deleteAccount(snapAccountId);
|
|
97
|
+
// Update the local Set so subsequent checks use the correct size
|
|
98
|
+
snapAccounts.delete(snapAccountId);
|
|
99
|
+
}
|
|
94
100
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
+
catch (error) {
|
|
102
|
+
(0, errors_1.reportError)(this.messenger, `Unable to delete de-synced Snap account: ${this.snapId}`, error, {
|
|
103
|
+
provider: this.getName(),
|
|
104
|
+
snapAccountId,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const message = `Snap "${this.snapId}" has de-synced accounts, Snap has more accounts than MetaMask! (${localSnapAccounts.length} < ${snapAccounts.size})`;
|
|
111
|
+
(0, logger_1.projectLogger)(`${logger_1.WARNING_PREFIX} ${message}`);
|
|
112
|
+
console.warn(message);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
101
115
|
}
|
|
102
116
|
// We want this part to be fast, so we only check for sizes, but we might need
|
|
103
117
|
// to make a real "diff" between the 2 states to not miss any de-sync.
|
|
@@ -120,11 +134,10 @@ class SnapAccountProvider extends BaseBip44AccountProvider_1.BaseBip44AccountPro
|
|
|
120
134
|
}
|
|
121
135
|
}
|
|
122
136
|
catch (error) {
|
|
123
|
-
|
|
137
|
+
(0, errors_1.reportError)(this.messenger, 'Unable to re-sync accounts', error, {
|
|
124
138
|
provider: this.getName(),
|
|
125
139
|
groupIndex,
|
|
126
140
|
});
|
|
127
|
-
this.messenger.captureException?.(sentryError);
|
|
128
141
|
}
|
|
129
142
|
}));
|
|
130
143
|
}
|
|
@@ -137,6 +150,79 @@ class SnapAccountProvider extends BaseBip44AccountProvider_1.BaseBip44AccountPro
|
|
|
137
150
|
keyring: await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_getRestrictedSnapKeyring).call(this),
|
|
138
151
|
});
|
|
139
152
|
}
|
|
153
|
+
toBip44Account(account, _options) {
|
|
154
|
+
(0, account_api_1.assertIsBip44Account)(account);
|
|
155
|
+
return account;
|
|
156
|
+
}
|
|
157
|
+
async createBip44Accounts(keyring, options) {
|
|
158
|
+
return this.withMaxConcurrency(async () => {
|
|
159
|
+
let groupIndexOffset = 0;
|
|
160
|
+
let snapAccounts = [];
|
|
161
|
+
const batched = this.config.createAccounts.batched ?? false;
|
|
162
|
+
const { entropySource } = options;
|
|
163
|
+
const createAccountV1 = async (groupIndex) => await (0, utils_1.withTimeout)(() => this.trace({
|
|
164
|
+
name: analytics_1.TraceName.ProviderCreateAccountV1,
|
|
165
|
+
data: {
|
|
166
|
+
provider: this.getName(),
|
|
167
|
+
groupIndex,
|
|
168
|
+
},
|
|
169
|
+
}, () => this.createAccountV1(keyring, { entropySource, groupIndex })), this.config.createAccounts.timeoutMs);
|
|
170
|
+
const createAccountsV2 = async (optionsV2) => await (0, utils_1.withTimeout)(() => this.trace({
|
|
171
|
+
name: analytics_1.TraceName.ProviderCreateAccounts,
|
|
172
|
+
data: {
|
|
173
|
+
provider: this.getName(),
|
|
174
|
+
...(0, analytics_1.toCreateAccountsV2DataTraces)(optionsV2),
|
|
175
|
+
},
|
|
176
|
+
}, () => keyring.createAccounts(optionsV2)), this.config.createAccounts.timeoutMs);
|
|
177
|
+
if (options.type === `${keyring_api_1.AccountCreationType.Bip44DeriveIndexRange}`) {
|
|
178
|
+
if (batched) {
|
|
179
|
+
// Batch account creations.
|
|
180
|
+
snapAccounts = await createAccountsV2(options);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
const { range } = options;
|
|
184
|
+
// Create accounts one by one.
|
|
185
|
+
for (let groupIndex = range.from; groupIndex <= range.to; groupIndex++) {
|
|
186
|
+
const snapAccount = await createAccountV1(groupIndex);
|
|
187
|
+
snapAccounts.push(snapAccount);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Group indices are sequential, so we just need the starting index.
|
|
191
|
+
groupIndexOffset = options.range.from;
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
if (batched) {
|
|
195
|
+
// Create account using new v2-like flow (no async flow + no Snap keyring events).
|
|
196
|
+
snapAccounts = await createAccountsV2(options);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
const { groupIndex } = options;
|
|
200
|
+
// Create account using the existing v1 flow.
|
|
201
|
+
const snapAccount = await createAccountV1(groupIndex);
|
|
202
|
+
snapAccounts = [snapAccount];
|
|
203
|
+
}
|
|
204
|
+
// For single account, there will only be 1 account, so we can use the
|
|
205
|
+
// provided group index directly.
|
|
206
|
+
groupIndexOffset = options.groupIndex;
|
|
207
|
+
}
|
|
208
|
+
return snapAccounts.map((snapAccount, index) => {
|
|
209
|
+
const groupIndex = groupIndexOffset + index;
|
|
210
|
+
const account = this.toBip44Account(snapAccount, {
|
|
211
|
+
entropySource,
|
|
212
|
+
groupIndex,
|
|
213
|
+
});
|
|
214
|
+
this.accounts.add(snapAccount.id);
|
|
215
|
+
return account;
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
async createAccounts(options) {
|
|
220
|
+
(0, keyring_api_1.assertCreateAccountOptionIsSupported)(options, [
|
|
221
|
+
`${keyring_api_1.AccountCreationType.Bip44DeriveIndex}`,
|
|
222
|
+
`${keyring_api_1.AccountCreationType.Bip44DeriveIndexRange}`,
|
|
223
|
+
]);
|
|
224
|
+
return this.withSnap(async ({ keyring }) => this.createBip44Accounts(keyring, options));
|
|
225
|
+
}
|
|
140
226
|
}
|
|
141
227
|
exports.SnapAccountProvider = SnapAccountProvider;
|
|
142
228
|
_SnapAccountProvider_client = new WeakMap(), _SnapAccountProvider_queue = new WeakMap(), _SnapAccountProvider_trace = new WeakMap(), _SnapAccountProvider_instances = new WeakSet(), _SnapAccountProvider_getRestrictedSnapKeyring = async function _SnapAccountProvider_getRestrictedSnapKeyring() {
|
|
@@ -146,7 +232,10 @@ _SnapAccountProvider_client = new WeakMap(), _SnapAccountProvider_queue = new We
|
|
|
146
232
|
// Also, creating account that way won't invalidate the Snap keyring state. The
|
|
147
233
|
// account will get created and persisted properly with the Snap account creation
|
|
148
234
|
// flow "asynchronously" (with `notify:accountCreated`).
|
|
149
|
-
const createAccount = await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_withSnapKeyring).call(this, async ({ keyring }) =>
|
|
235
|
+
const { createAccount, createAccounts } = await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_withSnapKeyring).call(this, async ({ keyring }) => ({
|
|
236
|
+
createAccount: keyring.createAccount.bind(keyring),
|
|
237
|
+
createAccounts: keyring.createAccounts.bind(keyring),
|
|
238
|
+
}));
|
|
150
239
|
return {
|
|
151
240
|
createAccount: async (options) =>
|
|
152
241
|
// We use the "unguarded" account creation here (see explanation above).
|
|
@@ -155,6 +244,7 @@ _SnapAccountProvider_client = new WeakMap(), _SnapAccountProvider_queue = new We
|
|
|
155
244
|
displayConfirmation: false,
|
|
156
245
|
setSelectedAccount: false,
|
|
157
246
|
}),
|
|
247
|
+
createAccounts: async (options) => await createAccounts(this.snapId, options),
|
|
158
248
|
removeAccount: async (address) =>
|
|
159
249
|
// Though, when removing account, we can use the normal flow.
|
|
160
250
|
await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_withSnapKeyring).call(this, async ({ keyring }) => {
|