UNPKG

@metamask-previews/account-api

Version:
235 lines 13.7 kB
/* eslint-disable @typescript-eslint/no-redundant-type-constituents */ // This rule seems to be triggering a false positive. Possibly eslint is not // inferring the `InternalAccount` type correctly which causes issue with the // union `| undefined`. var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); 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"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _MultichainAccountAdapter_id, _MultichainAccountAdapter_wallet, _MultichainAccountAdapter_index, _MultichainAccountAdapter_providers, _MultichainAccountAdapter_providersByAccountId, _MultichainAccountAdapter_accounts, _MultichainAccountWalletAdapter_instances, _MultichainAccountWalletAdapter_id, _MultichainAccountWalletAdapter_providers, _MultichainAccountWalletAdapter_entropySource, _MultichainAccountWalletAdapter_accounts, _MultichainAccountWalletAdapter_createMultichainAccount; import { isScopeEqualToAny } from "@metamask/keyring-utils"; import { getGroupIndexFromAccountGroupId, toDefaultAccountGroupId, toMultichainAccountId, toMultichainAccountWalletId } from "../index.mjs"; export class MultichainAccountAdapter { constructor({ groupIndex, wallet, providers, }) { _MultichainAccountAdapter_id.set(this, void 0); _MultichainAccountAdapter_wallet.set(this, void 0); _MultichainAccountAdapter_index.set(this, void 0); _MultichainAccountAdapter_providers.set(this, void 0); _MultichainAccountAdapter_providersByAccountId.set(this, void 0); _MultichainAccountAdapter_accounts.set(this, void 0); __classPrivateFieldSet(this, _MultichainAccountAdapter_id, toMultichainAccountId(wallet.id, groupIndex), "f"); __classPrivateFieldSet(this, _MultichainAccountAdapter_index, groupIndex, "f"); __classPrivateFieldSet(this, _MultichainAccountAdapter_wallet, wallet, "f"); __classPrivateFieldSet(this, _MultichainAccountAdapter_providers, providers, "f"); __classPrivateFieldSet(this, _MultichainAccountAdapter_accounts, new Map(), "f"); __classPrivateFieldSet(this, _MultichainAccountAdapter_providersByAccountId, new Map(), "f"); for (const provider of __classPrivateFieldGet(this, _MultichainAccountAdapter_providers, "f")) { const accounts = provider.getAccounts({ entropySource: __classPrivateFieldGet(this, _MultichainAccountAdapter_wallet, "f").entropySource, groupIndex: __classPrivateFieldGet(this, _MultichainAccountAdapter_index, "f"), }); __classPrivateFieldGet(this, _MultichainAccountAdapter_accounts, "f").set(provider, accounts); for (const id of accounts) { __classPrivateFieldGet(this, _MultichainAccountAdapter_providersByAccountId, "f").set(id, provider); } } } get id() { return __classPrivateFieldGet(this, _MultichainAccountAdapter_id, "f"); } get wallet() { return __classPrivateFieldGet(this, _MultichainAccountAdapter_wallet, "f"); } get index() { return __classPrivateFieldGet(this, _MultichainAccountAdapter_index, "f"); } hasAccounts() { // Use this map, cause if there's no accounts, then this map will also // be empty. return __classPrivateFieldGet(this, _MultichainAccountAdapter_providersByAccountId, "f").size > 0; } getAccounts() { let allAccounts = []; for (const [provider, accounts] of __classPrivateFieldGet(this, _MultichainAccountAdapter_accounts, "f").entries()) { allAccounts = allAccounts.concat(accounts.map((id) => provider.getAccount(id))); } return allAccounts; } getAccount(id) { const provider = __classPrivateFieldGet(this, _MultichainAccountAdapter_providersByAccountId, "f").get(id); return provider?.getAccount(id); } get(selector) { const accounts = this.select(selector); if (accounts.length > 1) { throw new Error(`Too many account candidates, expected 1, got: ${accounts.length}`); } if (accounts.length === 0) { return undefined; } return accounts[0]; // This is safe, see checks above. } select(selector) { return this.getAccounts().filter((account) => { let selected = true; if (selector.id) { selected && (selected = account.id === selector.id); } if (selector.address) { selected && (selected = account.address === selector.address); } if (selector.type) { selected && (selected = account.type === selector.type); } if (selector.methods !== undefined) { selected && (selected = selector.methods.some((method) => account.methods.includes(method))); } if (selector.scopes !== undefined) { selected && (selected = selector.scopes.some((scope) => { return ( // This will cover specific EVM EOA scopes as well. isScopeEqualToAny(scope, account.scopes)); })); } return selected; }); } } _MultichainAccountAdapter_id = new WeakMap(), _MultichainAccountAdapter_wallet = new WeakMap(), _MultichainAccountAdapter_index = new WeakMap(), _MultichainAccountAdapter_providers = new WeakMap(), _MultichainAccountAdapter_providersByAccountId = new WeakMap(), _MultichainAccountAdapter_accounts = new WeakMap(); export class MultichainAccountWalletAdapter { constructor({ providers, entropySource, }) { _MultichainAccountWalletAdapter_instances.add(this); _MultichainAccountWalletAdapter_id.set(this, void 0); _MultichainAccountWalletAdapter_providers.set(this, void 0); _MultichainAccountWalletAdapter_entropySource.set(this, void 0); _MultichainAccountWalletAdapter_accounts.set(this, void 0); __classPrivateFieldSet(this, _MultichainAccountWalletAdapter_id, toMultichainAccountWalletId(entropySource), "f"); __classPrivateFieldSet(this, _MultichainAccountWalletAdapter_providers, providers, "f"); __classPrivateFieldSet(this, _MultichainAccountWalletAdapter_entropySource, entropySource, "f"); __classPrivateFieldSet(this, _MultichainAccountWalletAdapter_accounts, new Map(), "f"); let groupIndex = 0; let hasAccounts = false; do { const multichainAccount = new MultichainAccountAdapter({ groupIndex, wallet: this, providers: __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_providers, "f"), }); // We only add multichain account that has underlying accounts. hasAccounts = multichainAccount.hasAccounts(); if (hasAccounts) { __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_accounts, "f").set(groupIndex, multichainAccount); } groupIndex += 1; } while (hasAccounts); } get id() { return __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_id, "f"); } get entropySource() { return __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_entropySource, "f"); } getAccountGroup(groupId) { // We consider the "default case" to be mapped to index 0. if (groupId === toDefaultAccountGroupId(this.id)) { return __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_accounts, "f").get(0); } const groupIndex = getGroupIndexFromAccountGroupId(groupId); if (groupIndex === undefined) { return undefined; } return __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_accounts, "f").get(groupIndex); } getAccountGroups() { return this.getMultichainAccounts(); } getMultichainAccount(groupIndex) { return __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_accounts, "f").get(groupIndex); } getMultichainAccounts() { return Array.from(__classPrivateFieldGet(this, _MultichainAccountWalletAdapter_accounts, "f").values()); // TODO: Prevent copy here. } getNextGroupIndex() { // Assuming we cannot have indexes gaps. return __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_accounts, "f").size; // No +1 here, group indexes starts at 0. } async createMultichainAccount(groupIndex) { const nextGroupIndex = this.getNextGroupIndex(); if (groupIndex > nextGroupIndex) { throw new Error(`You cannot use an group index that is higher than the next available one: expect <${nextGroupIndex}, got ${groupIndex}`); } for (const provider of __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_providers, "f")) { await provider.createAccounts({ entropySource: __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_entropySource, "f"), groupIndex, }); } // Re-create and "refresh" the multichain account (we assume all account creations are // idempotent, so we should get the same accounts and potentially some new accounts (if // some account providers decide to return more of them this time). return __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_instances, "m", _MultichainAccountWalletAdapter_createMultichainAccount).call(this, groupIndex); } async createNextMultichainAccount() { return this.createMultichainAccount(this.getNextGroupIndex()); } async discoverAndCreateMultichainAccounts() { const multichainAccounts = []; let discovered; let groupIndex = 0; do { // Keep track if any accounts got discovered for that new index. discovered = false; const missingProviders = []; for (const provider of __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_providers, "f")) { const discoveredAccounts = await provider.discoverAndCreateAccounts({ entropySource: __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_entropySource, "f"), groupIndex, }); if (discoveredAccounts.length) { // This provider has discovered and created accounts, meaning there might // be something to discover on the next index. discovered = true; } else { // This provider did not discover or create any accounts. We mark it as // "missing", so we can create accounts on this index if other providers // did discover something. missingProviders.push(provider); } } if (discovered) { // We only create missing accounts if one of the provider has discovered // and created accounts. for (const provider of missingProviders) { await provider.createAccounts({ entropySource: __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_entropySource, "f"), groupIndex, }); } // We've got all the accounts now, we can create our multichain account. multichainAccounts.push(__classPrivateFieldGet(this, _MultichainAccountWalletAdapter_instances, "m", _MultichainAccountWalletAdapter_createMultichainAccount).call(this, groupIndex)); // We have accounts, we need to check the next index. groupIndex += 1; } } while (discovered); return multichainAccounts; } } _MultichainAccountWalletAdapter_id = new WeakMap(), _MultichainAccountWalletAdapter_providers = new WeakMap(), _MultichainAccountWalletAdapter_entropySource = new WeakMap(), _MultichainAccountWalletAdapter_accounts = new WeakMap(), _MultichainAccountWalletAdapter_instances = new WeakSet(), _MultichainAccountWalletAdapter_createMultichainAccount = function _MultichainAccountWalletAdapter_createMultichainAccount(groupIndex) { const multichainAccount = new MultichainAccountAdapter({ wallet: this, providers: __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_providers, "f"), groupIndex, }); // Register the account to our internal map. __classPrivateFieldGet(this, _MultichainAccountWalletAdapter_accounts, "f").set(groupIndex, multichainAccount); return multichainAccount; }; //# sourceMappingURL=adapters.mjs.map