UNPKG

@metamask/multichain-network-controller

Version:
197 lines 11.8 kB
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 _MultichainNetworkController_instances, _MultichainNetworkController_networkService, _MultichainNetworkController_setActiveEvmNetwork, _MultichainNetworkController_setActiveNonEvmNetwork, _MultichainNetworkController_removeEvmNetwork, _MultichainNetworkController_removeNonEvmNetwork, _MultichainNetworkController_handleOnSelectedAccountChange, _MultichainNetworkController_subscribeToMessageEvents, _MultichainNetworkController_registerMessageHandlers; import { BaseController } from "@metamask/base-controller"; import { isEvmAccountType } from "@metamask/keyring-api"; import { isCaipChainId } from "@metamask/utils"; import { toAllowedCaipAccountIds, toActiveNetworksByAddress } from "../api/accounts-api.mjs"; import { AVAILABLE_MULTICHAIN_NETWORK_CONFIGURATIONS, MULTICHAIN_NETWORK_CONTROLLER_METADATA, getDefaultMultichainNetworkControllerState } from "../constants.mjs"; import { MULTICHAIN_NETWORK_CONTROLLER_NAME } from "../types.mjs"; import { checkIfSupportedCaipChainId, getChainIdForNonEvmAddress, convertEvmCaipToHexChainId, isEvmCaipChainId } from "../utils.mjs"; /** * The MultichainNetworkController is responsible for fetching and caching account * balances. */ export class MultichainNetworkController extends BaseController { constructor({ messenger, state, networkService, }) { super({ messenger, name: MULTICHAIN_NETWORK_CONTROLLER_NAME, metadata: MULTICHAIN_NETWORK_CONTROLLER_METADATA, state: { ...getDefaultMultichainNetworkControllerState(), ...state, // We can keep the current network as a hardcoded value // since it is not expected to add/remove networks yet. multichainNetworkConfigurationsByChainId: AVAILABLE_MULTICHAIN_NETWORK_CONFIGURATIONS, }, }); _MultichainNetworkController_instances.add(this); _MultichainNetworkController_networkService.set(this, void 0); __classPrivateFieldSet(this, _MultichainNetworkController_networkService, networkService, "f"); __classPrivateFieldGet(this, _MultichainNetworkController_instances, "m", _MultichainNetworkController_subscribeToMessageEvents).call(this); __classPrivateFieldGet(this, _MultichainNetworkController_instances, "m", _MultichainNetworkController_registerMessageHandlers).call(this); } /** * Sets the active network. * * @param id - The non-EVM Caip chain ID or EVM client ID of the network to set active. * @returns - A promise that resolves when the network is set active. */ async setActiveNetwork(id) { if (isCaipChainId(id)) { const isSupportedCaipChainId = checkIfSupportedCaipChainId(id); if (!isSupportedCaipChainId) { throw new Error(`Unsupported Caip chain ID: ${String(id)}`); } return __classPrivateFieldGet(this, _MultichainNetworkController_instances, "m", _MultichainNetworkController_setActiveNonEvmNetwork).call(this, id); } return await __classPrivateFieldGet(this, _MultichainNetworkController_instances, "m", _MultichainNetworkController_setActiveEvmNetwork).call(this, id); } /** * Returns the active networks for the available EVM addresses (non-EVM networks will be supported in the future). * Fetches the data from the API and caches it in state. * * @returns A promise that resolves to the active networks for the available addresses */ async getNetworksWithTransactionActivityByAccounts() { const accounts = this.messagingSystem.call('AccountsController:listMultichainAccounts'); if (!accounts || accounts.length === 0) { return this.state.networksWithTransactionActivity; } const formattedAccounts = accounts .map((account) => toAllowedCaipAccountIds(account)) .flat(); const activeNetworks = await __classPrivateFieldGet(this, _MultichainNetworkController_networkService, "f").fetchNetworkActivity(formattedAccounts); const formattedNetworks = toActiveNetworksByAddress(activeNetworks); this.update((state) => { state.networksWithTransactionActivity = formattedNetworks; }); return this.state.networksWithTransactionActivity; } /** * Removes a network from the list of networks. * It only supports EVM networks. * * @param chainId - The chain ID of the network to remove. * @returns - A promise that resolves when the network is removed. */ async removeNetwork(chainId) { if (isEvmCaipChainId(chainId)) { return await __classPrivateFieldGet(this, _MultichainNetworkController_instances, "m", _MultichainNetworkController_removeEvmNetwork).call(this, chainId); } return __classPrivateFieldGet(this, _MultichainNetworkController_instances, "m", _MultichainNetworkController_removeNonEvmNetwork).call(this, chainId); } } _MultichainNetworkController_networkService = new WeakMap(), _MultichainNetworkController_instances = new WeakSet(), _MultichainNetworkController_setActiveEvmNetwork = /** * Sets the active EVM network. * * @param id - The client ID of the EVM network to set active. */ async function _MultichainNetworkController_setActiveEvmNetwork(id) { const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState'); const shouldSetEvmActive = !this.state.isEvmSelected; const shouldNotifyNetworkChange = id !== selectedNetworkClientId; // No changes needed if EVM is active and network is already selected if (!shouldSetEvmActive && !shouldNotifyNetworkChange) { return; } // Update EVM selection state if needed if (shouldSetEvmActive) { this.update((state) => { state.isEvmSelected = true; }); } // Only notify the network controller if the selected evm network is different if (shouldNotifyNetworkChange) { await this.messagingSystem.call('NetworkController:setActiveNetwork', id); } // Only publish the networkDidChange event if either the EVM network is different or we're switching between EVM and non-EVM networks if (shouldSetEvmActive || shouldNotifyNetworkChange) { this.messagingSystem.publish('MultichainNetworkController:networkDidChange', id); } }, _MultichainNetworkController_setActiveNonEvmNetwork = function _MultichainNetworkController_setActiveNonEvmNetwork(id) { if (id === this.state.selectedMultichainNetworkChainId && !this.state.isEvmSelected) { // Same non-EVM network is already selected, no need to update return; } this.update((state) => { state.selectedMultichainNetworkChainId = id; state.isEvmSelected = false; }); // Notify listeners that the network changed this.messagingSystem.publish('MultichainNetworkController:networkDidChange', id); }, _MultichainNetworkController_removeEvmNetwork = /** * Removes an EVM network from the list of networks. * This method re-directs the request to the network-controller. * * @param chainId - The chain ID of the network to remove. * @returns - A promise that resolves when the network is removed. */ async function _MultichainNetworkController_removeEvmNetwork(chainId) { const hexChainId = convertEvmCaipToHexChainId(chainId); const selectedChainId = this.messagingSystem.call('NetworkController:getSelectedChainId'); if (selectedChainId === hexChainId) { // We prevent removing the currently selected network. if (this.state.isEvmSelected) { throw new Error('Cannot remove the currently selected network'); } // If a non-EVM network is selected, we can delete the currently EVM selected network, but // we automatically switch to EVM mainnet. const ethereumMainnetHexChainId = '0x1'; // TODO: Should probably be a constant. const clientId = this.messagingSystem.call('NetworkController:findNetworkClientIdByChainId', ethereumMainnetHexChainId); await this.messagingSystem.call('NetworkController:setActiveNetwork', clientId); } this.messagingSystem.call('NetworkController:removeNetwork', hexChainId); }, _MultichainNetworkController_removeNonEvmNetwork = function _MultichainNetworkController_removeNonEvmNetwork(_chainId) { throw new Error('Removal of non-EVM networks is not supported'); }, _MultichainNetworkController_handleOnSelectedAccountChange = function _MultichainNetworkController_handleOnSelectedAccountChange(account) { const { type: accountType, address: accountAddress, scopes } = account; const isEvmAccount = isEvmAccountType(accountType); // Handle switching to EVM network if (isEvmAccount) { if (this.state.isEvmSelected) { // No need to update if already on evm network return; } // Make EVM network active this.update((state) => { state.isEvmSelected = true; }); return; } // Handle switching to non-EVM network if (scopes.includes(this.state.selectedMultichainNetworkChainId)) { // No need to update if the account's scope includes the active network this.update((state) => { state.isEvmSelected = false; }); return; } const nonEvmChainId = getChainIdForNonEvmAddress(accountAddress); this.update((state) => { state.selectedMultichainNetworkChainId = nonEvmChainId; state.isEvmSelected = false; }); // No need to publish NetworkController:setActiveNetwork because EVM accounts falls back to use the last selected EVM network // DO NOT publish MultichainNetworkController:networkDidChange to prevent circular listener loops }, _MultichainNetworkController_subscribeToMessageEvents = function _MultichainNetworkController_subscribeToMessageEvents() { // Handle network switch when account is changed this.messagingSystem.subscribe('AccountsController:selectedAccountChange', (account) => __classPrivateFieldGet(this, _MultichainNetworkController_instances, "m", _MultichainNetworkController_handleOnSelectedAccountChange).call(this, account)); }, _MultichainNetworkController_registerMessageHandlers = function _MultichainNetworkController_registerMessageHandlers() { this.messagingSystem.registerActionHandler('MultichainNetworkController:setActiveNetwork', this.setActiveNetwork.bind(this)); this.messagingSystem.registerActionHandler('MultichainNetworkController:getNetworksWithTransactionActivityByAccounts', this.getNetworksWithTransactionActivityByAccounts.bind(this)); }; //# sourceMappingURL=MultichainNetworkController.mjs.map