UNPKG

@metamask/multichain-account-service

Version:
249 lines 14.9 kB
"use strict"; 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 _MultichainAccountService_instances, _MultichainAccountService_messenger, _MultichainAccountService_providers, _MultichainAccountService_wallets, _MultichainAccountService_accountIdToContext, _MultichainAccountService_handleOnAccountAdded, _MultichainAccountService_handleOnAccountRemoved, _MultichainAccountService_getWallet; Object.defineProperty(exports, "__esModule", { value: true }); exports.MultichainAccountService = exports.serviceName = void 0; const account_api_1 = require("@metamask/account-api"); const keyring_controller_1 = require("@metamask/keyring-controller"); const MultichainAccountWallet_1 = require("./MultichainAccountWallet.cjs"); const EvmAccountProvider_1 = require("./providers/EvmAccountProvider.cjs"); const SolAccountProvider_1 = require("./providers/SolAccountProvider.cjs"); exports.serviceName = 'MultichainAccountService'; /** * Service to expose multichain accounts capabilities. */ class MultichainAccountService { /** * Constructs a new MultichainAccountService. * * @param options - The options. * @param options.messenger - The messenger suited to this * MultichainAccountService. * @param options.providers - Optional list of account * providers. */ constructor({ messenger, providers = [], }) { _MultichainAccountService_instances.add(this); _MultichainAccountService_messenger.set(this, void 0); _MultichainAccountService_providers.set(this, void 0); _MultichainAccountService_wallets.set(this, void 0); _MultichainAccountService_accountIdToContext.set(this, void 0); /** * The name of the service. */ this.name = exports.serviceName; __classPrivateFieldSet(this, _MultichainAccountService_messenger, messenger, "f"); __classPrivateFieldSet(this, _MultichainAccountService_wallets, new Map(), "f"); __classPrivateFieldSet(this, _MultichainAccountService_accountIdToContext, new Map(), "f"); // TODO: Rely on keyring capabilities once the keyring API is used by all keyrings. __classPrivateFieldSet(this, _MultichainAccountService_providers, [ new EvmAccountProvider_1.EvmAccountProvider(__classPrivateFieldGet(this, _MultichainAccountService_messenger, "f")), new SolAccountProvider_1.SolAccountProvider(__classPrivateFieldGet(this, _MultichainAccountService_messenger, "f")), // Custom account providers that can be provided by the MetaMask client. ...providers, ], "f"); __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").registerActionHandler('MultichainAccountService:getMultichainAccountGroup', (...args) => this.getMultichainAccountGroup(...args)); __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").registerActionHandler('MultichainAccountService:getMultichainAccountGroups', (...args) => this.getMultichainAccountGroups(...args)); __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").registerActionHandler('MultichainAccountService:getMultichainAccountWallet', (...args) => this.getMultichainAccountWallet(...args)); __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").registerActionHandler('MultichainAccountService:getMultichainAccountWallets', (...args) => this.getMultichainAccountWallets(...args)); __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").registerActionHandler('MultichainAccountService:createNextMultichainAccountGroup', (...args) => this.createNextMultichainAccountGroup(...args)); __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").registerActionHandler('MultichainAccountService:createMultichainAccountGroup', (...args) => this.createMultichainAccountGroup(...args)); __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").registerActionHandler('MultichainAccountService:alignWallets', (...args) => this.alignWallets(...args)); __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").registerActionHandler('MultichainAccountService:alignWallet', (...args) => this.alignWallet(...args)); } /** * Initialize the service and constructs the internal reprensentation of * multichain accounts and wallets. */ init() { // Create initial wallets. const { keyrings } = __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").call('KeyringController:getState'); for (const keyring of keyrings) { if (keyring.type === keyring_controller_1.KeyringTypes.hd) { // Only HD keyrings have an entropy source/SRP. const entropySource = keyring.metadata.id; // This will automatically "associate" all multichain accounts for that wallet // (based on the accounts owned by each account providers). const wallet = new MultichainAccountWallet_1.MultichainAccountWallet({ entropySource, providers: __classPrivateFieldGet(this, _MultichainAccountService_providers, "f"), }); __classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").set(wallet.id, wallet); // Reverse mapping between account ID and their multichain wallet/account: for (const group of wallet.getMultichainAccountGroups()) { for (const account of group.getAccounts()) { __classPrivateFieldGet(this, _MultichainAccountService_accountIdToContext, "f").set(account.id, { wallet, group, }); } } } } __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").subscribe('AccountsController:accountAdded', (account) => __classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_handleOnAccountAdded).call(this, account)); __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").subscribe('AccountsController:accountRemoved', (id) => __classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_handleOnAccountRemoved).call(this, id)); } /** * Gets the account's context which contains its multichain wallet and * multichain account group references. * * @param id - Account ID. * @returns The account context if any, undefined otherwise. */ getAccountContext(id) { return __classPrivateFieldGet(this, _MultichainAccountService_accountIdToContext, "f").get(id); } /** * Gets a reference to the multichain account wallet matching this entropy source. * * @param options - Options. * @param options.entropySource - The entropy source of the multichain account. * @throws If none multichain account match this entropy. * @returns A reference to the multichain account wallet. */ getMultichainAccountWallet({ entropySource, }) { return __classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_getWallet).call(this, entropySource); } /** * Gets an array of all multichain account wallets. * * @returns An array of all multichain account wallets. */ getMultichainAccountWallets() { return Array.from(__classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").values()); } /** * Gets a reference to the multichain account group matching this entropy source * and a group index. * * @param options - Options. * @param options.entropySource - The entropy source of the multichain account. * @param options.groupIndex - The group index of the multichain account. * @throws If none multichain account match this entropy source and group index. * @returns A reference to the multichain account. */ getMultichainAccountGroup({ entropySource, groupIndex, }) { const multichainAccount = __classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_getWallet).call(this, entropySource).getMultichainAccountGroup(groupIndex); if (!multichainAccount) { throw new Error(`No multichain account for index: ${groupIndex}`); } return multichainAccount; } /** * Gets all multichain account groups for a given entropy source. * * @param options - Options. * @param options.entropySource - The entropy source to query. * @throws If no multichain accounts match this entropy source. * @returns A list of all multichain accounts. */ getMultichainAccountGroups({ entropySource, }) { return __classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_getWallet).call(this, entropySource).getMultichainAccountGroups(); } /** * Creates the next multichain account group. * * @param options - Options. * @param options.entropySource - The wallet's entropy source. * @returns The next multichain account group. */ async createNextMultichainAccountGroup({ entropySource, }) { return await __classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_getWallet).call(this, entropySource).createNextMultichainAccountGroup(); } /** * Creates a multichain account group. * * @param options - Options. * @param options.groupIndex - The group index to use. * @param options.entropySource - The wallet's entropy source. * @returns The multichain account group for this group index. */ async createMultichainAccountGroup({ groupIndex, entropySource, }) { return await __classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_getWallet).call(this, entropySource).createMultichainAccountGroup(groupIndex); } /** * Align all multichain account wallets. */ async alignWallets() { const wallets = this.getMultichainAccountWallets(); await Promise.all(wallets.map((w) => w.alignGroups())); } /** * Align a specific multichain account wallet. * * @param entropySource - The entropy source of the multichain account wallet. */ async alignWallet(entropySource) { const wallet = this.getMultichainAccountWallet({ entropySource }); await wallet.alignGroups(); } } exports.MultichainAccountService = MultichainAccountService; _MultichainAccountService_messenger = new WeakMap(), _MultichainAccountService_providers = new WeakMap(), _MultichainAccountService_wallets = new WeakMap(), _MultichainAccountService_accountIdToContext = new WeakMap(), _MultichainAccountService_instances = new WeakSet(), _MultichainAccountService_handleOnAccountAdded = function _MultichainAccountService_handleOnAccountAdded(account) { // We completely omit non-BIP-44 accounts! if (!(0, account_api_1.isBip44Account)(account)) { return; } let sync = true; let wallet = __classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").get((0, account_api_1.toMultichainAccountWalletId)(account.options.entropy.id)); if (!wallet) { // That's a new wallet. wallet = new MultichainAccountWallet_1.MultichainAccountWallet({ entropySource: account.options.entropy.id, providers: __classPrivateFieldGet(this, _MultichainAccountService_providers, "f"), }); __classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").set(wallet.id, wallet); // If that's a new wallet wallet. There's nothing to "force-sync". sync = false; } let group = wallet.getMultichainAccountGroup(account.options.entropy.groupIndex); if (!group) { // This new account is a new multichain account, let the wallet know // it has to re-sync with its providers. if (sync) { wallet.sync(); } group = wallet.getMultichainAccountGroup(account.options.entropy.groupIndex); // If that's a new multichain account. There's nothing to "force-sync". sync = false; } // We have to check against `undefined` in case `getMultichainAccount` is // not able to find this multichain account (which should not be possible...) if (group) { if (sync) { group.sync(); } // Same here, this account should have been already grouped in that // multichain account. __classPrivateFieldGet(this, _MultichainAccountService_accountIdToContext, "f").set(account.id, { wallet, group, }); } }, _MultichainAccountService_handleOnAccountRemoved = function _MultichainAccountService_handleOnAccountRemoved(id) { // Force sync of the appropriate wallet if an account got removed. const found = __classPrivateFieldGet(this, _MultichainAccountService_accountIdToContext, "f").get(id); if (found) { const { wallet } = found; wallet.sync(); } // Safe to call delete even if the `id` was not referencing a BIP-44 account. __classPrivateFieldGet(this, _MultichainAccountService_accountIdToContext, "f").delete(id); }, _MultichainAccountService_getWallet = function _MultichainAccountService_getWallet(entropySource) { const wallet = __classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").get((0, account_api_1.toMultichainAccountWalletId)(entropySource)); if (!wallet) { throw new Error('Unknown wallet, no wallet matching this entropy source'); } return wallet; }; //# sourceMappingURL=MultichainAccountService.cjs.map