@metamask/multichain-account-service 8.0.0 → 9.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 +45 -12
- package/dist/MultichainAccountGroup.cjs.map +1 -1
- package/dist/MultichainAccountGroup.d.cts.map +1 -1
- package/dist/MultichainAccountGroup.d.mts.map +1 -1
- package/dist/MultichainAccountGroup.mjs.map +1 -1
- package/dist/MultichainAccountService-method-action-types.cjs.map +1 -1
- package/dist/MultichainAccountService-method-action-types.d.cts +9 -1
- package/dist/MultichainAccountService-method-action-types.d.cts.map +1 -1
- package/dist/MultichainAccountService-method-action-types.d.mts +9 -1
- package/dist/MultichainAccountService-method-action-types.d.mts.map +1 -1
- package/dist/MultichainAccountService-method-action-types.mjs.map +1 -1
- package/dist/MultichainAccountService.cjs +1 -0
- package/dist/MultichainAccountService.cjs.map +1 -1
- package/dist/MultichainAccountService.d.cts.map +1 -1
- package/dist/MultichainAccountService.d.mts.map +1 -1
- package/dist/MultichainAccountService.mjs +1 -0
- package/dist/MultichainAccountService.mjs.map +1 -1
- package/dist/MultichainAccountWallet.cjs.map +1 -1
- package/dist/MultichainAccountWallet.d.cts.map +1 -1
- package/dist/MultichainAccountWallet.d.mts.map +1 -1
- package/dist/MultichainAccountWallet.mjs.map +1 -1
- package/dist/analytics/perf.cjs +1 -1
- package/dist/analytics/perf.cjs.map +1 -1
- package/dist/analytics/perf.mjs +1 -1
- package/dist/analytics/perf.mjs.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts.map +1 -1
- package/dist/errors.d.mts.map +1 -1
- package/dist/errors.mjs +2 -2
- package/dist/errors.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/providers/AccountProviderWrapper.cjs.map +1 -1
- package/dist/providers/AccountProviderWrapper.d.cts +3 -2
- package/dist/providers/AccountProviderWrapper.d.cts.map +1 -1
- package/dist/providers/AccountProviderWrapper.d.mts +3 -2
- package/dist/providers/AccountProviderWrapper.d.mts.map +1 -1
- package/dist/providers/AccountProviderWrapper.mjs.map +1 -1
- package/dist/providers/BaseBip44AccountProvider.cjs +29 -0
- package/dist/providers/BaseBip44AccountProvider.cjs.map +1 -1
- package/dist/providers/BaseBip44AccountProvider.d.cts +29 -2
- package/dist/providers/BaseBip44AccountProvider.d.cts.map +1 -1
- package/dist/providers/BaseBip44AccountProvider.d.mts +29 -2
- package/dist/providers/BaseBip44AccountProvider.d.mts.map +1 -1
- package/dist/providers/BaseBip44AccountProvider.mjs +29 -0
- package/dist/providers/BaseBip44AccountProvider.mjs.map +1 -1
- package/dist/providers/BtcAccountProvider.cjs +2 -2
- package/dist/providers/BtcAccountProvider.cjs.map +1 -1
- package/dist/providers/BtcAccountProvider.d.cts +3 -2
- package/dist/providers/BtcAccountProvider.d.cts.map +1 -1
- package/dist/providers/BtcAccountProvider.d.mts +3 -2
- package/dist/providers/BtcAccountProvider.d.mts.map +1 -1
- package/dist/providers/BtcAccountProvider.mjs +2 -2
- package/dist/providers/BtcAccountProvider.mjs.map +1 -1
- package/dist/providers/EvmAccountProvider.cjs +63 -46
- package/dist/providers/EvmAccountProvider.cjs.map +1 -1
- package/dist/providers/EvmAccountProvider.d.cts +3 -2
- package/dist/providers/EvmAccountProvider.d.cts.map +1 -1
- package/dist/providers/EvmAccountProvider.d.mts +3 -2
- package/dist/providers/EvmAccountProvider.d.mts.map +1 -1
- package/dist/providers/EvmAccountProvider.mjs +63 -46
- package/dist/providers/EvmAccountProvider.mjs.map +1 -1
- package/dist/providers/SnapAccountProvider.cjs +2 -2
- package/dist/providers/SnapAccountProvider.cjs.map +1 -1
- package/dist/providers/SnapAccountProvider.d.cts +1 -1
- package/dist/providers/SnapAccountProvider.d.cts.map +1 -1
- package/dist/providers/SnapAccountProvider.d.mts +1 -1
- package/dist/providers/SnapAccountProvider.d.mts.map +1 -1
- package/dist/providers/SnapAccountProvider.mjs +2 -2
- package/dist/providers/SnapAccountProvider.mjs.map +1 -1
- package/dist/providers/SolAccountProvider.cjs +2 -2
- package/dist/providers/SolAccountProvider.cjs.map +1 -1
- package/dist/providers/SolAccountProvider.d.cts +3 -2
- package/dist/providers/SolAccountProvider.d.cts.map +1 -1
- package/dist/providers/SolAccountProvider.d.mts +3 -2
- package/dist/providers/SolAccountProvider.d.mts.map +1 -1
- package/dist/providers/SolAccountProvider.mjs +2 -2
- package/dist/providers/SolAccountProvider.mjs.map +1 -1
- package/dist/providers/TrxAccountProvider.cjs +2 -2
- package/dist/providers/TrxAccountProvider.cjs.map +1 -1
- package/dist/providers/TrxAccountProvider.d.cts +3 -2
- package/dist/providers/TrxAccountProvider.d.cts.map +1 -1
- package/dist/providers/TrxAccountProvider.d.mts +3 -2
- package/dist/providers/TrxAccountProvider.d.mts.map +1 -1
- package/dist/providers/TrxAccountProvider.mjs +2 -2
- package/dist/providers/TrxAccountProvider.mjs.map +1 -1
- package/dist/providers/utils.cjs +13 -1
- package/dist/providers/utils.cjs.map +1 -1
- package/dist/providers/utils.d.cts +7 -0
- package/dist/providers/utils.d.cts.map +1 -1
- package/dist/providers/utils.d.mts +7 -0
- package/dist/providers/utils.d.mts.map +1 -1
- package/dist/providers/utils.mjs +11 -0
- package/dist/providers/utils.mjs.map +1 -1
- package/dist/tests/accounts.cjs +4 -6
- package/dist/tests/accounts.cjs.map +1 -1
- package/dist/tests/accounts.d.cts +8 -21
- package/dist/tests/accounts.d.cts.map +1 -1
- package/dist/tests/accounts.d.mts +8 -21
- package/dist/tests/accounts.d.mts.map +1 -1
- package/dist/tests/accounts.mjs +4 -6
- package/dist/tests/accounts.mjs.map +1 -1
- package/dist/tests/messenger.cjs +1 -0
- package/dist/tests/messenger.cjs.map +1 -1
- package/dist/tests/messenger.d.cts.map +1 -1
- package/dist/tests/messenger.d.mts.map +1 -1
- package/dist/tests/messenger.mjs +1 -0
- package/dist/tests/messenger.mjs.map +1 -1
- package/dist/tests/providers.cjs.map +1 -1
- package/dist/tests/providers.d.cts +2 -1
- package/dist/tests/providers.d.cts.map +1 -1
- package/dist/tests/providers.d.mts +2 -1
- package/dist/tests/providers.d.mts.map +1 -1
- package/dist/tests/providers.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +4 -4
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +4 -4
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +32 -31
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BtcAccountProvider.d.mts","sourceRoot":"","sources":["../../src/providers/BtcAccountProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAChE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"BtcAccountProvider.d.mts","sourceRoot":"","sources":["../../src/providers/BtcAccountProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,8BAA8B;AAM7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,iCAAiC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,MAAM,EAAE,4BAA4B;AAIlD,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAiB;AAClE,OAAO,EAAE,mBAAmB,EAAE,kCAA8B;AAC5D,OAAO,KAAK,EACV,qBAAqB,EACrB,yBAAyB,EAC1B,kCAA8B;AAG/B,MAAM,MAAM,wBAAwB,GAAG,yBAAyB,CAAC;AAEjE,eAAO,MAAM,yBAAyB,YAAY,CAAC;AAEnD,eAAO,MAAM,mCAAmC,EAAE,wBAejD,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,mBAAmB;IACzD,MAAM,CAAC,IAAI,SAA6B;IAExC,MAAM,CAAC,WAAW,SAAiD;IAEnE,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAMxC;gBAGA,SAAS,EAAE,iCAAiC,EAC5C,MAAM,GAAE,wBAA8D,EACtE,KAAK,GAAE,aAA6B;IAKtC,OAAO,IAAI,MAAM;IAIjB,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,eAAe,CAAC,GAAG,OAAO;cAOjD,eAAe,CAChC,OAAO,EAAE,qBAAqB,EAC9B,EACE,aAAa,EACb,UAAU,GACX,EAAE;QAAE,aAAa,EAAE,eAAe,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GACxD,OAAO,CAAC,cAAc,CAAC;IASpB,gBAAgB,CAAC,EACrB,aAAa,EACb,UAAU,GACX,EAAE;QACD,aAAa,EAAE,eAAe,CAAC;QAC/B,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;CA+C5C"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { AccountCreationType, BtcAccountType, BtcScope } from "@metamask/keyring-api";
|
|
2
|
-
import { SnapAccountProvider } from "./SnapAccountProvider.mjs";
|
|
3
|
-
import { withRetry, withTimeout } from "./utils.mjs";
|
|
4
2
|
import { traceFallback } from "../analytics/index.mjs";
|
|
5
3
|
import { TraceName } from "../analytics/traces.mjs";
|
|
4
|
+
import { SnapAccountProvider } from "./SnapAccountProvider.mjs";
|
|
5
|
+
import { withRetry, withTimeout } from "./utils.mjs";
|
|
6
6
|
export const BTC_ACCOUNT_PROVIDER_NAME = 'Bitcoin';
|
|
7
7
|
export const BTC_ACCOUNT_PROVIDER_DEFAULT_CONFIG = {
|
|
8
8
|
maxConcurrency: 3,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BtcAccountProvider.mjs","sourceRoot":"","sources":["../../src/providers/BtcAccountProvider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BtcAccountProvider.mjs","sourceRoot":"","sources":["../../src/providers/BtcAccountProvider.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,QAAQ,EACT,8BAA8B;AAK/B,OAAO,EAAE,aAAa,EAAE,+BAAqB;AAC7C,OAAO,EAAE,SAAS,EAAE,gCAA4B;AAEhD,OAAO,EAAE,mBAAmB,EAAE,kCAA8B;AAK5D,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,oBAAgB;AAIjD,MAAM,CAAC,MAAM,yBAAyB,GAAG,SAAS,CAAC;AAEnD,MAAM,CAAC,MAAM,mCAAmC,GAA6B;IAC3E,cAAc,EAAE,CAAC;IACjB,cAAc,EAAE;QACd,OAAO,EAAE,KAAK,EAAE,+CAA+C;QAC/D,SAAS,EAAE,IAAI;KAChB;IACD,SAAS,EAAE;QACT,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,CAAC;QACd,SAAS,EAAE,IAAI;KAChB;IACD,cAAc,EAAE;QACd,2BAA2B,EAAE,IAAI;KAClC;CACF,CAAC;AAEF,MAAM,OAAO,kBAAmB,SAAQ,mBAAmB;IAazD,YACE,SAA4C,EAC5C,SAAmC,mCAAmC,EACtE,QAAuB,aAAa;QAEpC,KAAK,CAAC,kBAAkB,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAbzD,iBAAY,GAAwB;YAC3C,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC;YAC5C,KAAK,EAAE;gBACL,WAAW,EAAE,IAAI;gBACjB,gBAAgB,EAAE,IAAI;aACvB;SACF,CAAC;IAQF,CAAC;IAED,OAAO;QACL,OAAO,kBAAkB,CAAC,IAAI,CAAC;IACjC,CAAC;IAED,mBAAmB,CAAC,OAAsC;QACxD,OAAO,CACL,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,MAAM;YACtC,MAAM,CAAC,MAAM,CAAS,cAAc,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAC7D,CAAC;IACJ,CAAC;IAEkB,eAAe,CAChC,OAA8B,EAC9B,EACE,aAAa,EACb,UAAU,GAC6C;QAEzD,OAAO,OAAO,CAAC,aAAa,CAAC;YAC3B,aAAa;YACb,KAAK,EAAE,UAAU;YACjB,WAAW,EAAE,cAAc,CAAC,MAAM;YAClC,KAAK,EAAE,QAAQ,CAAC,OAAO;SACxB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,EACrB,aAAa,EACb,UAAU,GAIX;QACC,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;YACjD,OAAO,MAAM,KAAK,CAAC,KAAK,CACtB;gBACE,IAAI,EAAE,SAAS,CAAC,oBAAoB;gBACpC,IAAI,EAAE;oBACJ,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE;iBACzB;aACF,EACD,KAAK,IAAI,EAAE;gBACT,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;oBACnC,OAAO,EAAE,CAAC;gBACZ,CAAC;gBAED,MAAM,kBAAkB,GAAG,MAAM,SAAS,CACxC,GAAG,EAAE,CACH,WAAW,CACT,GAAG,EAAE,CACH,MAAM,CAAC,gBAAgB,CACrB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAClB,aAAa,EACb,UAAU,CACX,EACH,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAChC,EACH;oBACE,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW;oBAC9C,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS;iBAC3C,CACF,CAAC;gBAEF,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC;oBAClC,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAC/B,CAAC;oBACD,OAAO,EAAE,CAAC;gBACZ,CAAC;gBAED,OAAO,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE;oBAC7C,IAAI,EAAE,mBAAmB,CAAC,gBAAgB;oBAC1C,aAAa;oBACb,UAAU;iBACX,CAAC,CAAC;YACL,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;;AAlGM,uBAAI,GAAG,yBAAyB,AAA5B,CAA6B;AAEjC,8BAAW,GAAG,mCAA6C,AAAhD,CAAiD","sourcesContent":["import type { Bip44Account } from '@metamask/account-api';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type { EntropySourceId, KeyringAccount } from '@metamask/keyring-api';\nimport {\n AccountCreationType,\n BtcAccountType,\n BtcScope,\n} from '@metamask/keyring-api';\nimport type { KeyringCapabilities } from '@metamask/keyring-api/v2';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { SnapId } from '@metamask/snaps-sdk';\n\nimport { traceFallback } from '../analytics';\nimport { TraceName } from '../analytics/traces';\nimport type { MultichainAccountServiceMessenger } from '../types';\nimport { SnapAccountProvider } from './SnapAccountProvider';\nimport type {\n RestrictedSnapKeyring,\n SnapAccountProviderConfig,\n} from './SnapAccountProvider';\nimport { withRetry, withTimeout } from './utils';\n\nexport type BtcAccountProviderConfig = SnapAccountProviderConfig;\n\nexport const BTC_ACCOUNT_PROVIDER_NAME = 'Bitcoin';\n\nexport const BTC_ACCOUNT_PROVIDER_DEFAULT_CONFIG: BtcAccountProviderConfig = {\n maxConcurrency: 3,\n createAccounts: {\n batched: false, // For now, the Snap is not fully v2 compliant.\n timeoutMs: 3000,\n },\n discovery: {\n enabled: true,\n timeoutMs: 2000,\n maxAttempts: 3,\n backOffMs: 1000,\n },\n resyncAccounts: {\n autoRemoveExtraSnapAccounts: true,\n },\n};\n\nexport class BtcAccountProvider extends SnapAccountProvider {\n static NAME = BTC_ACCOUNT_PROVIDER_NAME;\n\n static BTC_SNAP_ID = 'npm:@metamask/bitcoin-wallet-snap' as SnapId;\n\n readonly capabilities: KeyringCapabilities = {\n scopes: [BtcScope.Mainnet, BtcScope.Testnet],\n bip44: {\n deriveIndex: true,\n deriveIndexRange: true,\n },\n };\n\n constructor(\n messenger: MultichainAccountServiceMessenger,\n config: BtcAccountProviderConfig = BTC_ACCOUNT_PROVIDER_DEFAULT_CONFIG,\n trace: TraceCallback = traceFallback,\n ) {\n super(BtcAccountProvider.BTC_SNAP_ID, messenger, config, trace);\n }\n\n getName(): string {\n return BtcAccountProvider.NAME;\n }\n\n isAccountCompatible(account: Bip44Account<InternalAccount>): boolean {\n return (\n account.type === BtcAccountType.P2wpkh &&\n Object.values<string>(BtcAccountType).includes(account.type)\n );\n }\n\n protected override createAccountV1(\n keyring: RestrictedSnapKeyring,\n {\n entropySource,\n groupIndex,\n }: { entropySource: EntropySourceId; groupIndex: number },\n ): Promise<KeyringAccount> {\n return keyring.createAccount({\n entropySource,\n index: groupIndex,\n addressType: BtcAccountType.P2wpkh,\n scope: BtcScope.Mainnet,\n });\n }\n\n async discoverAccounts({\n entropySource,\n groupIndex,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Bip44Account<KeyringAccount>[]> {\n return this.withSnap(async ({ client, keyring }) => {\n return await super.trace(\n {\n name: TraceName.SnapDiscoverAccounts,\n data: {\n provider: this.getName(),\n },\n },\n async () => {\n if (!this.config.discovery.enabled) {\n return [];\n }\n\n const discoveredAccounts = await withRetry(\n () =>\n withTimeout(\n () =>\n client.discoverAccounts(\n [BtcScope.Mainnet],\n entropySource,\n groupIndex,\n ),\n this.config.discovery.timeoutMs,\n ),\n {\n maxAttempts: this.config.discovery.maxAttempts,\n backOffMs: this.config.discovery.backOffMs,\n },\n );\n\n if (\n !Array.isArray(discoveredAccounts) ||\n discoveredAccounts.length === 0\n ) {\n return [];\n }\n\n return await this.createBip44Accounts(keyring, {\n type: AccountCreationType.Bip44DeriveIndex,\n entropySource,\n groupIndex,\n });\n },\n );\n });\n }\n}\n"]}
|
|
@@ -10,19 +10,18 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
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
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var _EvmAccountProvider_instances, _EvmAccountProvider_config, _EvmAccountProvider_trace,
|
|
13
|
+
var _EvmAccountProvider_instances, _EvmAccountProvider_config, _EvmAccountProvider_trace, _EvmAccountProvider_createAccount, _EvmAccountProvider_getAddressFromGroupIndex, _EvmAccountProvider_getTransactionCount;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.EvmAccountProvider = exports.EVM_ACCOUNT_PROVIDER_DEFAULT_CONFIG = exports.EVM_ACCOUNT_PROVIDER_NAME = void 0;
|
|
16
16
|
const util_1 = require("@ethereumjs/util");
|
|
17
|
-
const accounts_controller_1 = require("@metamask/accounts-controller");
|
|
18
17
|
const keyring_api_1 = require("@metamask/keyring-api");
|
|
19
18
|
const keyring_controller_1 = require("@metamask/keyring-controller");
|
|
20
19
|
const utils_1 = require("@metamask/utils");
|
|
21
|
-
const BaseBip44AccountProvider_1 = require("./BaseBip44AccountProvider.cjs");
|
|
22
|
-
const utils_2 = require("./utils.cjs");
|
|
23
20
|
const analytics_1 = require("../analytics/index.cjs");
|
|
24
21
|
const traces_1 = require("../analytics/traces.cjs");
|
|
25
22
|
const logger_1 = require("../logger.cjs");
|
|
23
|
+
const BaseBip44AccountProvider_1 = require("./BaseBip44AccountProvider.cjs");
|
|
24
|
+
const utils_2 = require("./utils.cjs");
|
|
26
25
|
const ETH_MAINNET_CHAIN_ID = '0x1';
|
|
27
26
|
/**
|
|
28
27
|
* Asserts an internal account exists.
|
|
@@ -97,7 +96,7 @@ class EvmAccountProvider extends BaseBip44AccountProvider_1.BaseBip44AccountProv
|
|
|
97
96
|
if (options.type === keyring_api_1.AccountCreationType.Bip44DeriveIndexRange) {
|
|
98
97
|
const { range } = options;
|
|
99
98
|
// Use a single withKeyring call for the entire range.
|
|
100
|
-
const accountIds = await this.
|
|
99
|
+
const accountIds = await this.withKeyringV2({ id: entropySource }, async ({ keyring }) => {
|
|
101
100
|
const existing = await keyring.getAccounts();
|
|
102
101
|
// Validate no gaps: we can only create accounts starting from existing.length.
|
|
103
102
|
if (range.from > existing.length) {
|
|
@@ -108,17 +107,19 @@ class EvmAccountProvider extends BaseBip44AccountProvider_1.BaseBip44AccountProv
|
|
|
108
107
|
for (let groupIndex = range.from; groupIndex <= range.to; groupIndex++) {
|
|
109
108
|
if (groupIndex < existing.length) {
|
|
110
109
|
// Account already exists.
|
|
111
|
-
result.push(
|
|
110
|
+
result.push(existing[groupIndex].id);
|
|
112
111
|
}
|
|
113
112
|
}
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
113
|
+
// Create new accounts one-by-one since HdKeyringV2 only supports
|
|
114
|
+
// bip44:derive-index (not bip44:derive-index-range).
|
|
115
|
+
for (let groupIndex = Math.max(range.from, existing.length); groupIndex <= range.to; groupIndex++) {
|
|
116
|
+
const [created] = await keyring.createAccounts({
|
|
117
|
+
type: keyring_api_1.AccountCreationType.Bip44DeriveIndex,
|
|
118
|
+
entropySource,
|
|
119
|
+
groupIndex,
|
|
120
|
+
});
|
|
121
|
+
(0, utils_1.assert)(created, 'Account creation failed');
|
|
122
|
+
result.push(created.id);
|
|
122
123
|
}
|
|
123
124
|
return result;
|
|
124
125
|
});
|
|
@@ -133,13 +134,13 @@ class EvmAccountProvider extends BaseBip44AccountProvider_1.BaseBip44AccountProv
|
|
|
133
134
|
}
|
|
134
135
|
// Handle Bip44DeriveIndex (single account creation).
|
|
135
136
|
const { groupIndex } = options;
|
|
136
|
-
const [
|
|
137
|
+
const [created] = await __classPrivateFieldGet(this, _EvmAccountProvider_instances, "m", _EvmAccountProvider_createAccount).call(this, {
|
|
137
138
|
entropySource,
|
|
138
139
|
groupIndex,
|
|
139
140
|
throwOnGap: true,
|
|
140
141
|
});
|
|
141
|
-
|
|
142
|
-
const account = this.messenger.call('AccountsController:getAccount',
|
|
142
|
+
(0, utils_1.assert)(created, 'Account creation failed');
|
|
143
|
+
const account = this.messenger.call('AccountsController:getAccount', created.id);
|
|
143
144
|
// We MUST have the associated internal account.
|
|
144
145
|
assertInternalAccountExists(account);
|
|
145
146
|
const accountsArray = [account];
|
|
@@ -176,13 +177,14 @@ class EvmAccountProvider extends BaseBip44AccountProvider_1.BaseBip44AccountProv
|
|
|
176
177
|
return [];
|
|
177
178
|
}
|
|
178
179
|
// We have some activity on this address, we try to create the account.
|
|
179
|
-
const [
|
|
180
|
+
const [created] = await __classPrivateFieldGet(this, _EvmAccountProvider_instances, "m", _EvmAccountProvider_createAccount).call(this, {
|
|
180
181
|
entropySource,
|
|
181
182
|
groupIndex,
|
|
183
|
+
throwOnGap: false,
|
|
182
184
|
});
|
|
183
|
-
(0, utils_1.assert)(
|
|
184
|
-
|
|
185
|
-
const account = this.messenger.call('AccountsController:getAccount',
|
|
185
|
+
(0, utils_1.assert)(created, 'Account creation failed');
|
|
186
|
+
(0, utils_1.assert)(addressFromGroupIndex === created.address, 'Created account does not match address from group index.');
|
|
187
|
+
const account = this.messenger.call('AccountsController:getAccount', created.id);
|
|
186
188
|
assertInternalAccountExists(account);
|
|
187
189
|
(0, BaseBip44AccountProvider_1.assertIsBip44Account)(account);
|
|
188
190
|
this.accounts.add(account.id);
|
|
@@ -195,9 +197,7 @@ class EvmAccountProvider extends BaseBip44AccountProvider_1.BaseBip44AccountProv
|
|
|
195
197
|
}
|
|
196
198
|
}
|
|
197
199
|
exports.EvmAccountProvider = EvmAccountProvider;
|
|
198
|
-
_EvmAccountProvider_config = new WeakMap(), _EvmAccountProvider_trace = new WeakMap(), _EvmAccountProvider_instances = new WeakSet(),
|
|
199
|
-
return (0, accounts_controller_1.getUUIDFromAddressOfNormalAccount)(address);
|
|
200
|
-
}, _EvmAccountProvider_createAccount =
|
|
200
|
+
_EvmAccountProvider_config = new WeakMap(), _EvmAccountProvider_trace = new WeakMap(), _EvmAccountProvider_instances = new WeakSet(), _EvmAccountProvider_createAccount =
|
|
201
201
|
/**
|
|
202
202
|
* Create an EVM account.
|
|
203
203
|
*
|
|
@@ -205,22 +205,54 @@ _EvmAccountProvider_config = new WeakMap(), _EvmAccountProvider_trace = new Weak
|
|
|
205
205
|
* @param opts.entropySource - The entropy source to use for the creation of the account.
|
|
206
206
|
* @param opts.groupIndex - The index of the group to create the account for.
|
|
207
207
|
* @param opts.throwOnGap - Whether to throw an error if the account index is not contiguous.
|
|
208
|
-
* @returns The
|
|
208
|
+
* @returns The created or existing keyring account(s) at the requested group
|
|
209
|
+
* index. Returns an empty array if the keyring did not create an account.
|
|
209
210
|
*/
|
|
210
|
-
async function _EvmAccountProvider_createAccount({ entropySource, groupIndex, throwOnGap
|
|
211
|
-
|
|
211
|
+
async function _EvmAccountProvider_createAccount({ entropySource, groupIndex, throwOnGap, }) {
|
|
212
|
+
return await this.withKeyringV2({ id: entropySource }, async ({ keyring }) => {
|
|
212
213
|
const existing = await keyring.getAccounts();
|
|
213
214
|
if (groupIndex < existing.length) {
|
|
214
|
-
return [existing[groupIndex]
|
|
215
|
+
return [existing[groupIndex]];
|
|
215
216
|
}
|
|
216
217
|
// If the throwOnGap flag is set, we throw an error to prevent index gaps.
|
|
217
218
|
if (throwOnGap && groupIndex !== existing.length) {
|
|
218
219
|
throw new Error('Trying to create too many accounts');
|
|
219
220
|
}
|
|
220
|
-
|
|
221
|
-
|
|
221
|
+
return await keyring.createAccounts({
|
|
222
|
+
type: keyring_api_1.AccountCreationType.Bip44DeriveIndex,
|
|
223
|
+
entropySource,
|
|
224
|
+
groupIndex,
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
}, _EvmAccountProvider_getAddressFromGroupIndex =
|
|
228
|
+
/**
|
|
229
|
+
* Get the address that would be derived for a given group index without
|
|
230
|
+
* persisting an account in the keyring.
|
|
231
|
+
*
|
|
232
|
+
* Peeks at the next address via the HD `root` so discovery can short-circuit
|
|
233
|
+
* (and skip the vault write + `stateChange` event) when there is no on-chain
|
|
234
|
+
* activity at this index.
|
|
235
|
+
*
|
|
236
|
+
* @param opts - The options for the address derivation.
|
|
237
|
+
* @param opts.entropySource - The entropy source to derive from.
|
|
238
|
+
* @param opts.groupIndex - The group index to derive at.
|
|
239
|
+
* @returns The derived address for the given group index.
|
|
240
|
+
*/
|
|
241
|
+
async function _EvmAccountProvider_getAddressFromGroupIndex({ entropySource, groupIndex, }) {
|
|
242
|
+
// NOTE: To avoid exposing this function at keyring level, we just re-use its internal state
|
|
243
|
+
// and compute the derivation here.
|
|
244
|
+
return await this.withKeyringV2({ id: entropySource }, async ({ keyring }) => {
|
|
245
|
+
// If the account already exist, do not re-derive and just re-use that account.
|
|
246
|
+
const existing = await keyring.getAccounts();
|
|
247
|
+
if (groupIndex < existing.length) {
|
|
248
|
+
return existing[groupIndex].address;
|
|
249
|
+
}
|
|
250
|
+
// If not, then we just "peek" the next address to avoid creating the account.
|
|
251
|
+
(0, utils_1.assert)(keyring.root, 'Expected HD keyring.root to be set');
|
|
252
|
+
const hdKey = keyring.root.deriveChild(groupIndex);
|
|
253
|
+
(0, utils_1.assert)(hdKey.publicKey, 'Expected public key to be set');
|
|
254
|
+
return (0, utils_1.add0x)((0, utils_1.bytesToHex)((0, util_1.publicToAddress)(hdKey.publicKey, true)).toLowerCase());
|
|
222
255
|
});
|
|
223
|
-
return result;
|
|
224
256
|
}, _EvmAccountProvider_getTransactionCount =
|
|
225
257
|
/**
|
|
226
258
|
* Get the transaction count for an EVM account.
|
|
@@ -247,21 +279,6 @@ async function _EvmAccountProvider_getTransactionCount(provider, address) {
|
|
|
247
279
|
return 0;
|
|
248
280
|
}
|
|
249
281
|
return parseInt(response, 16);
|
|
250
|
-
}, _EvmAccountProvider_getAddressFromGroupIndex = async function _EvmAccountProvider_getAddressFromGroupIndex({ entropySource, groupIndex, }) {
|
|
251
|
-
// NOTE: To avoid exposing this function at keyring level, we just re-use its internal state
|
|
252
|
-
// and compute the derivation here.
|
|
253
|
-
return await this.withKeyring({ id: entropySource }, async ({ keyring }) => {
|
|
254
|
-
// If the account already exist, do not re-derive and just re-use that account.
|
|
255
|
-
const existing = await keyring.getAccounts();
|
|
256
|
-
if (groupIndex < existing.length) {
|
|
257
|
-
return existing[groupIndex];
|
|
258
|
-
}
|
|
259
|
-
// If not, then we just "peek" the next address to avoid creating the account.
|
|
260
|
-
(0, utils_1.assert)(keyring.root, 'Expected HD keyring.root to be set');
|
|
261
|
-
const hdKey = keyring.root.deriveChild(groupIndex);
|
|
262
|
-
(0, utils_1.assert)(hdKey.publicKey, 'Expected public key to be set');
|
|
263
|
-
return (0, utils_1.add0x)((0, utils_1.bytesToHex)((0, util_1.publicToAddress)(hdKey.publicKey, true)).toLowerCase());
|
|
264
|
-
});
|
|
265
282
|
};
|
|
266
283
|
EvmAccountProvider.NAME = exports.EVM_ACCOUNT_PROVIDER_NAME;
|
|
267
284
|
//# sourceMappingURL=EvmAccountProvider.cjs.map
|
|
@@ -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 { 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
|
+
{"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 type { TraceCallback } from '@metamask/controller-utils';\nimport type { HdKeyring } from '@metamask/eth-hd-keyring/v2';\nimport type {\n CreateAccountOptions,\n EntropySourceId,\n KeyringAccount,\n} from '@metamask/keyring-api';\nimport {\n AccountCreationType,\n assertCreateAccountOptionIsSupported,\n EthAccountType,\n EthScope,\n} from '@metamask/keyring-api';\nimport type { KeyringCapabilities, Keyring } from '@metamask/keyring-api/v2';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } 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 { traceFallback } from '../analytics';\nimport { TraceName } from '../analytics/traces';\nimport { projectLogger as log, WARNING_PREFIX } from '../logger';\nimport type { MultichainAccountServiceMessenger } from '../types';\nimport {\n assertAreBip44Accounts,\n assertIsBip44Account,\n BaseBip44AccountProvider,\n} from './BaseBip44AccountProvider';\nimport { withRetry, withTimeout } from './utils';\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 * 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 created or existing keyring account(s) at the requested group\n * index. Returns an empty array if the keyring did not create an account.\n */\n async #createAccount({\n entropySource,\n groupIndex,\n throwOnGap,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n throwOnGap: boolean;\n }): Promise<KeyringAccount[]> {\n return await this.withKeyringV2<Keyring, KeyringAccount[]>(\n { id: entropySource },\n async ({ keyring }) => {\n const existing = await keyring.getAccounts();\n if (groupIndex < existing.length) {\n return [existing[groupIndex]];\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 return await keyring.createAccounts({\n type: AccountCreationType.Bip44DeriveIndex,\n entropySource,\n groupIndex,\n });\n },\n );\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.withKeyringV2<Keyring, 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(existing[groupIndex].id);\n }\n }\n\n // Create new accounts one-by-one since HdKeyringV2 only supports\n // bip44:derive-index (not bip44:derive-index-range).\n for (\n let groupIndex = Math.max(range.from, existing.length);\n groupIndex <= range.to;\n groupIndex++\n ) {\n const [created] = await keyring.createAccounts({\n type: AccountCreationType.Bip44DeriveIndex,\n entropySource,\n groupIndex,\n });\n assert(created, 'Account creation failed');\n result.push(created.id);\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 [created] = await this.#createAccount({\n entropySource,\n groupIndex,\n throwOnGap: true,\n });\n\n assert(created, 'Account creation failed');\n\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n created.id,\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 address that would be derived for a given group index without\n * persisting an account in the keyring.\n *\n * Peeks at the next address via the HD `root` so discovery can short-circuit\n * (and skip the vault write + `stateChange` event) when there is no on-chain\n * activity at this index.\n *\n * @param opts - The options for the address derivation.\n * @param opts.entropySource - The entropy source to derive from.\n * @param opts.groupIndex - The group index to derive at.\n * @returns The derived address for the given group index.\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.withKeyringV2<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].address as Hex;\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 * 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: string,\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 /**\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 [created] = await this.#createAccount({\n entropySource,\n groupIndex,\n throwOnGap: false,\n });\n\n assert(created, 'Account creation failed');\n assert(\n addressFromGroupIndex === created.address,\n 'Created account does not match address from group index.',\n );\n\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n created.id,\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,10 +1,11 @@
|
|
|
1
1
|
import type { Bip44Account } from "@metamask/account-api";
|
|
2
2
|
import type { TraceCallback } from "@metamask/controller-utils";
|
|
3
|
-
import type { CreateAccountOptions, EntropySourceId, KeyringAccount
|
|
3
|
+
import type { CreateAccountOptions, EntropySourceId, KeyringAccount } from "@metamask/keyring-api";
|
|
4
|
+
import type { KeyringCapabilities } from "@metamask/keyring-api/v2";
|
|
4
5
|
import type { InternalAccount } from "@metamask/keyring-internal-api";
|
|
5
6
|
import type { Provider } from "@metamask/network-controller";
|
|
6
|
-
import { BaseBip44AccountProvider } from "./BaseBip44AccountProvider.cjs";
|
|
7
7
|
import type { MultichainAccountServiceMessenger } from "../types.cjs";
|
|
8
|
+
import { BaseBip44AccountProvider } from "./BaseBip44AccountProvider.cjs";
|
|
8
9
|
export type EvmAccountProviderConfig = {
|
|
9
10
|
discovery: {
|
|
10
11
|
enabled?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EvmAccountProvider.d.cts","sourceRoot":"","sources":["../../src/providers/EvmAccountProvider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;
|
|
1
|
+
{"version":3,"file":"EvmAccountProvider.d.cts","sourceRoot":"","sources":["../../src/providers/EvmAccountProvider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAEhE,OAAO,KAAK,EACV,oBAAoB,EACpB,eAAe,EACf,cAAc,EACf,8BAA8B;AAO/B,OAAO,KAAK,EAAE,mBAAmB,EAAW,iCAAiC;AAE7E,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,QAAQ,EAAE,qCAAqC;AAO7D,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAiB;AAClE,OAAO,EAGL,wBAAwB,EACzB,uCAAmC;AAmBpC,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;IAqD1B;;;;;OAKG;IACG,cAAc,CAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAwL1C;;;;;;;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;IAsDrC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAItC"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { Bip44Account } from "@metamask/account-api";
|
|
2
2
|
import type { TraceCallback } from "@metamask/controller-utils";
|
|
3
|
-
import type { CreateAccountOptions, EntropySourceId, KeyringAccount
|
|
3
|
+
import type { CreateAccountOptions, EntropySourceId, KeyringAccount } from "@metamask/keyring-api";
|
|
4
|
+
import type { KeyringCapabilities } from "@metamask/keyring-api/v2";
|
|
4
5
|
import type { InternalAccount } from "@metamask/keyring-internal-api";
|
|
5
6
|
import type { Provider } from "@metamask/network-controller";
|
|
6
|
-
import { BaseBip44AccountProvider } from "./BaseBip44AccountProvider.mjs";
|
|
7
7
|
import type { MultichainAccountServiceMessenger } from "../types.mjs";
|
|
8
|
+
import { BaseBip44AccountProvider } from "./BaseBip44AccountProvider.mjs";
|
|
8
9
|
export type EvmAccountProviderConfig = {
|
|
9
10
|
discovery: {
|
|
10
11
|
enabled?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EvmAccountProvider.d.mts","sourceRoot":"","sources":["../../src/providers/EvmAccountProvider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;
|
|
1
|
+
{"version":3,"file":"EvmAccountProvider.d.mts","sourceRoot":"","sources":["../../src/providers/EvmAccountProvider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAEhE,OAAO,KAAK,EACV,oBAAoB,EACpB,eAAe,EACf,cAAc,EACf,8BAA8B;AAO/B,OAAO,KAAK,EAAE,mBAAmB,EAAW,iCAAiC;AAE7E,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,QAAQ,EAAE,qCAAqC;AAO7D,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAiB;AAClE,OAAO,EAGL,wBAAwB,EACzB,uCAAmC;AAmBpC,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;IAqD1B;;;;;OAKG;IACG,cAAc,CAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAwL1C;;;;;;;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;IAsDrC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAItC"}
|
|
@@ -9,17 +9,16 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
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
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _EvmAccountProvider_instances, _EvmAccountProvider_config, _EvmAccountProvider_trace,
|
|
12
|
+
var _EvmAccountProvider_instances, _EvmAccountProvider_config, _EvmAccountProvider_trace, _EvmAccountProvider_createAccount, _EvmAccountProvider_getAddressFromGroupIndex, _EvmAccountProvider_getTransactionCount;
|
|
13
13
|
import { publicToAddress } from "@ethereumjs/util";
|
|
14
|
-
import { getUUIDFromAddressOfNormalAccount } from "@metamask/accounts-controller";
|
|
15
14
|
import { AccountCreationType, assertCreateAccountOptionIsSupported, EthAccountType, EthScope } from "@metamask/keyring-api";
|
|
16
15
|
import { KeyringTypes } from "@metamask/keyring-controller";
|
|
17
16
|
import { add0x, assert, bytesToHex, isStrictHexString } from "@metamask/utils";
|
|
18
|
-
import { assertAreBip44Accounts, assertIsBip44Account, BaseBip44AccountProvider } from "./BaseBip44AccountProvider.mjs";
|
|
19
|
-
import { withRetry, withTimeout } from "./utils.mjs";
|
|
20
17
|
import { traceFallback } from "../analytics/index.mjs";
|
|
21
18
|
import { TraceName } from "../analytics/traces.mjs";
|
|
22
19
|
import { projectLogger as log, WARNING_PREFIX } from "../logger.mjs";
|
|
20
|
+
import { assertAreBip44Accounts, assertIsBip44Account, BaseBip44AccountProvider } from "./BaseBip44AccountProvider.mjs";
|
|
21
|
+
import { withRetry, withTimeout } from "./utils.mjs";
|
|
23
22
|
const ETH_MAINNET_CHAIN_ID = '0x1';
|
|
24
23
|
/**
|
|
25
24
|
* Asserts an internal account exists.
|
|
@@ -94,7 +93,7 @@ export class EvmAccountProvider extends BaseBip44AccountProvider {
|
|
|
94
93
|
if (options.type === AccountCreationType.Bip44DeriveIndexRange) {
|
|
95
94
|
const { range } = options;
|
|
96
95
|
// Use a single withKeyring call for the entire range.
|
|
97
|
-
const accountIds = await this.
|
|
96
|
+
const accountIds = await this.withKeyringV2({ id: entropySource }, async ({ keyring }) => {
|
|
98
97
|
const existing = await keyring.getAccounts();
|
|
99
98
|
// Validate no gaps: we can only create accounts starting from existing.length.
|
|
100
99
|
if (range.from > existing.length) {
|
|
@@ -105,17 +104,19 @@ export class EvmAccountProvider extends BaseBip44AccountProvider {
|
|
|
105
104
|
for (let groupIndex = range.from; groupIndex <= range.to; groupIndex++) {
|
|
106
105
|
if (groupIndex < existing.length) {
|
|
107
106
|
// Account already exists.
|
|
108
|
-
result.push(
|
|
107
|
+
result.push(existing[groupIndex].id);
|
|
109
108
|
}
|
|
110
109
|
}
|
|
111
|
-
//
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
// Create new accounts one-by-one since HdKeyringV2 only supports
|
|
111
|
+
// bip44:derive-index (not bip44:derive-index-range).
|
|
112
|
+
for (let groupIndex = Math.max(range.from, existing.length); groupIndex <= range.to; groupIndex++) {
|
|
113
|
+
const [created] = await keyring.createAccounts({
|
|
114
|
+
type: AccountCreationType.Bip44DeriveIndex,
|
|
115
|
+
entropySource,
|
|
116
|
+
groupIndex,
|
|
117
|
+
});
|
|
118
|
+
assert(created, 'Account creation failed');
|
|
119
|
+
result.push(created.id);
|
|
119
120
|
}
|
|
120
121
|
return result;
|
|
121
122
|
});
|
|
@@ -130,13 +131,13 @@ export class EvmAccountProvider extends BaseBip44AccountProvider {
|
|
|
130
131
|
}
|
|
131
132
|
// Handle Bip44DeriveIndex (single account creation).
|
|
132
133
|
const { groupIndex } = options;
|
|
133
|
-
const [
|
|
134
|
+
const [created] = await __classPrivateFieldGet(this, _EvmAccountProvider_instances, "m", _EvmAccountProvider_createAccount).call(this, {
|
|
134
135
|
entropySource,
|
|
135
136
|
groupIndex,
|
|
136
137
|
throwOnGap: true,
|
|
137
138
|
});
|
|
138
|
-
|
|
139
|
-
const account = this.messenger.call('AccountsController:getAccount',
|
|
139
|
+
assert(created, 'Account creation failed');
|
|
140
|
+
const account = this.messenger.call('AccountsController:getAccount', created.id);
|
|
140
141
|
// We MUST have the associated internal account.
|
|
141
142
|
assertInternalAccountExists(account);
|
|
142
143
|
const accountsArray = [account];
|
|
@@ -173,13 +174,14 @@ export class EvmAccountProvider extends BaseBip44AccountProvider {
|
|
|
173
174
|
return [];
|
|
174
175
|
}
|
|
175
176
|
// We have some activity on this address, we try to create the account.
|
|
176
|
-
const [
|
|
177
|
+
const [created] = await __classPrivateFieldGet(this, _EvmAccountProvider_instances, "m", _EvmAccountProvider_createAccount).call(this, {
|
|
177
178
|
entropySource,
|
|
178
179
|
groupIndex,
|
|
180
|
+
throwOnGap: false,
|
|
179
181
|
});
|
|
180
|
-
assert(
|
|
181
|
-
|
|
182
|
-
const account = this.messenger.call('AccountsController:getAccount',
|
|
182
|
+
assert(created, 'Account creation failed');
|
|
183
|
+
assert(addressFromGroupIndex === created.address, 'Created account does not match address from group index.');
|
|
184
|
+
const account = this.messenger.call('AccountsController:getAccount', created.id);
|
|
183
185
|
assertInternalAccountExists(account);
|
|
184
186
|
assertIsBip44Account(account);
|
|
185
187
|
this.accounts.add(account.id);
|
|
@@ -191,9 +193,7 @@ export class EvmAccountProvider extends BaseBip44AccountProvider {
|
|
|
191
193
|
// the MetaMask side.
|
|
192
194
|
}
|
|
193
195
|
}
|
|
194
|
-
_EvmAccountProvider_config = new WeakMap(), _EvmAccountProvider_trace = new WeakMap(), _EvmAccountProvider_instances = new WeakSet(),
|
|
195
|
-
return getUUIDFromAddressOfNormalAccount(address);
|
|
196
|
-
}, _EvmAccountProvider_createAccount =
|
|
196
|
+
_EvmAccountProvider_config = new WeakMap(), _EvmAccountProvider_trace = new WeakMap(), _EvmAccountProvider_instances = new WeakSet(), _EvmAccountProvider_createAccount =
|
|
197
197
|
/**
|
|
198
198
|
* Create an EVM account.
|
|
199
199
|
*
|
|
@@ -201,22 +201,54 @@ _EvmAccountProvider_config = new WeakMap(), _EvmAccountProvider_trace = new Weak
|
|
|
201
201
|
* @param opts.entropySource - The entropy source to use for the creation of the account.
|
|
202
202
|
* @param opts.groupIndex - The index of the group to create the account for.
|
|
203
203
|
* @param opts.throwOnGap - Whether to throw an error if the account index is not contiguous.
|
|
204
|
-
* @returns The
|
|
204
|
+
* @returns The created or existing keyring account(s) at the requested group
|
|
205
|
+
* index. Returns an empty array if the keyring did not create an account.
|
|
205
206
|
*/
|
|
206
|
-
async function _EvmAccountProvider_createAccount({ entropySource, groupIndex, throwOnGap
|
|
207
|
-
|
|
207
|
+
async function _EvmAccountProvider_createAccount({ entropySource, groupIndex, throwOnGap, }) {
|
|
208
|
+
return await this.withKeyringV2({ id: entropySource }, async ({ keyring }) => {
|
|
208
209
|
const existing = await keyring.getAccounts();
|
|
209
210
|
if (groupIndex < existing.length) {
|
|
210
|
-
return [existing[groupIndex]
|
|
211
|
+
return [existing[groupIndex]];
|
|
211
212
|
}
|
|
212
213
|
// If the throwOnGap flag is set, we throw an error to prevent index gaps.
|
|
213
214
|
if (throwOnGap && groupIndex !== existing.length) {
|
|
214
215
|
throw new Error('Trying to create too many accounts');
|
|
215
216
|
}
|
|
216
|
-
|
|
217
|
-
|
|
217
|
+
return await keyring.createAccounts({
|
|
218
|
+
type: AccountCreationType.Bip44DeriveIndex,
|
|
219
|
+
entropySource,
|
|
220
|
+
groupIndex,
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
}, _EvmAccountProvider_getAddressFromGroupIndex =
|
|
224
|
+
/**
|
|
225
|
+
* Get the address that would be derived for a given group index without
|
|
226
|
+
* persisting an account in the keyring.
|
|
227
|
+
*
|
|
228
|
+
* Peeks at the next address via the HD `root` so discovery can short-circuit
|
|
229
|
+
* (and skip the vault write + `stateChange` event) when there is no on-chain
|
|
230
|
+
* activity at this index.
|
|
231
|
+
*
|
|
232
|
+
* @param opts - The options for the address derivation.
|
|
233
|
+
* @param opts.entropySource - The entropy source to derive from.
|
|
234
|
+
* @param opts.groupIndex - The group index to derive at.
|
|
235
|
+
* @returns The derived address for the given group index.
|
|
236
|
+
*/
|
|
237
|
+
async function _EvmAccountProvider_getAddressFromGroupIndex({ entropySource, groupIndex, }) {
|
|
238
|
+
// NOTE: To avoid exposing this function at keyring level, we just re-use its internal state
|
|
239
|
+
// and compute the derivation here.
|
|
240
|
+
return await this.withKeyringV2({ id: entropySource }, async ({ keyring }) => {
|
|
241
|
+
// If the account already exist, do not re-derive and just re-use that account.
|
|
242
|
+
const existing = await keyring.getAccounts();
|
|
243
|
+
if (groupIndex < existing.length) {
|
|
244
|
+
return existing[groupIndex].address;
|
|
245
|
+
}
|
|
246
|
+
// If not, then we just "peek" the next address to avoid creating the account.
|
|
247
|
+
assert(keyring.root, 'Expected HD keyring.root to be set');
|
|
248
|
+
const hdKey = keyring.root.deriveChild(groupIndex);
|
|
249
|
+
assert(hdKey.publicKey, 'Expected public key to be set');
|
|
250
|
+
return add0x(bytesToHex(publicToAddress(hdKey.publicKey, true)).toLowerCase());
|
|
218
251
|
});
|
|
219
|
-
return result;
|
|
220
252
|
}, _EvmAccountProvider_getTransactionCount =
|
|
221
253
|
/**
|
|
222
254
|
* Get the transaction count for an EVM account.
|
|
@@ -243,21 +275,6 @@ async function _EvmAccountProvider_getTransactionCount(provider, address) {
|
|
|
243
275
|
return 0;
|
|
244
276
|
}
|
|
245
277
|
return parseInt(response, 16);
|
|
246
|
-
}, _EvmAccountProvider_getAddressFromGroupIndex = async function _EvmAccountProvider_getAddressFromGroupIndex({ entropySource, groupIndex, }) {
|
|
247
|
-
// NOTE: To avoid exposing this function at keyring level, we just re-use its internal state
|
|
248
|
-
// and compute the derivation here.
|
|
249
|
-
return await this.withKeyring({ id: entropySource }, async ({ keyring }) => {
|
|
250
|
-
// If the account already exist, do not re-derive and just re-use that account.
|
|
251
|
-
const existing = await keyring.getAccounts();
|
|
252
|
-
if (groupIndex < existing.length) {
|
|
253
|
-
return existing[groupIndex];
|
|
254
|
-
}
|
|
255
|
-
// If not, then we just "peek" the next address to avoid creating the account.
|
|
256
|
-
assert(keyring.root, 'Expected HD keyring.root to be set');
|
|
257
|
-
const hdKey = keyring.root.deriveChild(groupIndex);
|
|
258
|
-
assert(hdKey.publicKey, 'Expected public key to be set');
|
|
259
|
-
return add0x(bytesToHex(publicToAddress(hdKey.publicKey, true)).toLowerCase());
|
|
260
|
-
});
|
|
261
278
|
};
|
|
262
279
|
EvmAccountProvider.NAME = EVM_ACCOUNT_PROVIDER_NAME;
|
|
263
280
|
//# sourceMappingURL=EvmAccountProvider.mjs.map
|