@metamask-previews/multichain-network-controller
Version:
Multichain network controller
1 lines • 9.18 kB
Source Map (JSON)
{"version":3,"file":"MultichainNetworkController.mjs","sourceRoot":"","sources":["../src/MultichainNetworkController.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,8BAA8B;AAGzD,OAAO,EAAE,aAAa,EAAE,wBAAwB;AAEhD,OAAO,EACL,sCAAsC,EACtC,0CAA0C,EAC3C,wBAAoB;AACrB,OAAO,EACL,kCAAkC,EAInC,oBAAgB;AACjB,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,EAC3B,oBAAgB;AAEjB;;;GAGG;AACH,MAAM,OAAO,2BAA4B,SAAQ,cAIhD;IACC,YAAY,EACV,SAAS,EACT,KAAK,GAON;QACC,KAAK,CAAC;YACJ,SAAS;YACT,IAAI,EAAE,kCAAkC;YACxC,QAAQ,EAAE,sCAAsC;YAChD,KAAK,EAAE;gBACL,GAAG,0CAA0C,EAAE;gBAC/C,GAAG,KAAK;aACT;SACF,CAAC,CAAC;;QA6FL;;;;WAIG;QACM,mEAA+B,CAAC,OAAwB,EAAE,EAAE;YACnE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;YAC/D,MAAM,YAAY,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;YAEnD,kCAAkC;YAClC,IAAI,YAAY,EAAE;gBAChB,IAAI,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE;oBAC5B,8CAA8C;oBAC9C,OAAO;iBACR;gBAED,0BAA0B;gBAC1B,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;gBAC7B,CAAC,CAAC,CAAC;gBACH,OAAO;aACR;YAED,sCAAsC;YACtC,MAAM,aAAa,GAAG,0BAA0B,CAAC,cAAc,CAAC,CAAC;YACjE,MAAM,mBAAmB,GACvB,aAAa,KAAK,IAAI,CAAC,KAAK,CAAC,gCAAgC,CAAC;YAEhE,IAAI,mBAAmB,EAAE;gBACvB,2DAA2D;gBAC3D,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;gBAC9B,CAAC,CAAC,CAAC;gBACH,OAAO;aACR;YAED,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,gCAAgC,GAAG,aAAa,CAAC;gBACvD,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;YAC9B,CAAC,CAAC,CAAC;QACL,CAAC,EAAC;QAnIA,uBAAA,IAAI,qGAA0B,MAA9B,IAAI,CAA4B,CAAC;QACjC,uBAAA,IAAI,oGAAyB,MAA7B,IAAI,CAA2B,CAAC;IAClC,CAAC;IAqED;;;;;OAKG;IACH,KAAK,CAAC,gBAAgB,CACpB,EAA0C;QAE1C,IAAI,aAAa,CAAC,EAAE,CAAC,EAAE;YACrB,MAAM,sBAAsB,GAAG,2BAA2B,CAAC,EAAE,CAAC,CAAC;YAC/D,IAAI,CAAC,sBAAsB,EAAE;gBAC3B,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;aAC7D;YACD,OAAO,uBAAA,IAAI,mGAAwB,MAA5B,IAAI,EAAyB,EAAE,CAAC,CAAC;SACzC;QAED,OAAO,MAAM,uBAAA,IAAI,gGAAqB,MAAzB,IAAI,EAAsB,EAAE,CAAC,CAAC;IAC7C,CAAC;CAgEF;;AArJC;;;;GAIG;AACH,KAAK,2DAAsB,EAAmB;IAC5C,oDAAoD;IACpD,IAAI,CAAC,eAAe,CAAC,OAAO,CAC1B,8CAA8C,EAC9C,EAAE,CACH,CAAC;IAEF,oDAAoD;IACpD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QACpB,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,+BAA+B;IAC/B,MAAM,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3D,4BAA4B,CAC7B,CAAC;IAEF,IAAI,EAAE,KAAK,uBAAuB,EAAE;QAClC,uEAAuE;QACvE,OAAO;KACR;IAED,4BAA4B;IAC5B,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,oCAAoC,EAAE,EAAE,CAAC,CAAC;AAC5E,CAAC,qHAOuB,EAAwB;IAC9C,IAAI,EAAE,KAAK,IAAI,CAAC,KAAK,CAAC,gCAAgC,EAAE;QACtD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE;YAC7B,8DAA8D;YAC9D,OAAO;SACR;QAED,gDAAgD;QAChD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,oDAAoD;QACpD,IAAI,CAAC,eAAe,CAAC,OAAO,CAC1B,8CAA8C,EAC9C,EAAE,CACH,CAAC;KACH;IAED,oDAAoD;IACpD,IAAI,CAAC,eAAe,CAAC,OAAO,CAC1B,8CAA8C,EAC9C,EAAE,CACH,CAAC;IAEF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QACpB,KAAK,CAAC,gCAAgC,GAAG,EAAE,CAAC;QAC5C,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;IAC9B,CAAC,CAAC,CAAC;AACL,CAAC;IAoEC,gDAAgD;IAChD,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,0CAA0C,EAC1C,uBAAA,IAAI,gEAA6B,CAClC,CAAC;AACJ,CAAC;IAMC,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,8CAA8C,EAC9C,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CACjC,CAAC;AACJ,CAAC","sourcesContent":["import { BaseController } from '@metamask/base-controller';\nimport { isEvmAccountType } from '@metamask/keyring-api';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { NetworkClientId } from '@metamask/network-controller';\nimport { isCaipChainId } from '@metamask/utils';\n\nimport {\n MULTICHAIN_NETWORK_CONTROLLER_METADATA,\n getDefaultMultichainNetworkControllerState,\n} from './constants';\nimport {\n MULTICHAIN_NETWORK_CONTROLLER_NAME,\n type MultichainNetworkControllerState,\n type MultichainNetworkControllerMessenger,\n type SupportedCaipChainId,\n} from './types';\nimport {\n checkIfSupportedCaipChainId,\n getChainIdForNonEvmAddress,\n} from './utils';\n\n/**\n * The MultichainNetworkController is responsible for fetching and caching account\n * balances.\n */\nexport class MultichainNetworkController extends BaseController<\n typeof MULTICHAIN_NETWORK_CONTROLLER_NAME,\n MultichainNetworkControllerState,\n MultichainNetworkControllerMessenger\n> {\n constructor({\n messenger,\n state,\n }: {\n messenger: MultichainNetworkControllerMessenger;\n state?: Omit<\n Partial<MultichainNetworkControllerState>,\n 'multichainNetworkConfigurationsByChainId'\n >;\n }) {\n super({\n messenger,\n name: MULTICHAIN_NETWORK_CONTROLLER_NAME,\n metadata: MULTICHAIN_NETWORK_CONTROLLER_METADATA,\n state: {\n ...getDefaultMultichainNetworkControllerState(),\n ...state,\n },\n });\n\n this.#subscribeToMessageEvents();\n this.#registerMessageHandlers();\n }\n\n /**\n * Sets the active EVM network.\n *\n * @param id - The client ID of the EVM network to set active.\n */\n async #setActiveEvmNetwork(id: NetworkClientId): Promise<void> {\n // Notify listeners that setActiveNetwork was called\n this.messagingSystem.publish(\n 'MultichainNetworkController:networkDidChange',\n id,\n );\n\n // Indicate that the non-EVM network is not selected\n this.update((state) => {\n state.isEvmSelected = true;\n });\n\n // Prevent setting same network\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n\n if (id === selectedNetworkClientId) {\n // EVM network is already selected, no need to update NetworkController\n return;\n }\n\n // Update evm active network\n await this.messagingSystem.call('NetworkController:setActiveNetwork', id);\n }\n\n /**\n * Sets the active non-EVM network.\n *\n * @param id - The chain ID of the non-EVM network to set active.\n */\n #setActiveNonEvmNetwork(id: SupportedCaipChainId): void {\n if (id === this.state.selectedMultichainNetworkChainId) {\n if (!this.state.isEvmSelected) {\n // Same non-EVM network is already selected, no need to update\n return;\n }\n\n // Indicate that the non-EVM network is selected\n this.update((state) => {\n state.isEvmSelected = false;\n });\n\n // Notify listeners that setActiveNetwork was called\n this.messagingSystem.publish(\n 'MultichainNetworkController:networkDidChange',\n id,\n );\n }\n\n // Notify listeners that setActiveNetwork was called\n this.messagingSystem.publish(\n 'MultichainNetworkController:networkDidChange',\n id,\n );\n\n this.update((state) => {\n state.selectedMultichainNetworkChainId = id;\n state.isEvmSelected = false;\n });\n }\n\n /**\n * Sets the active network.\n *\n * @param id - The non-EVM Caip chain ID or EVM client ID of the network to set active.\n * @returns - A promise that resolves when the network is set active.\n */\n async setActiveNetwork(\n id: SupportedCaipChainId | NetworkClientId,\n ): Promise<void> {\n if (isCaipChainId(id)) {\n const isSupportedCaipChainId = checkIfSupportedCaipChainId(id);\n if (!isSupportedCaipChainId) {\n throw new Error(`Unsupported Caip chain ID: ${String(id)}`);\n }\n return this.#setActiveNonEvmNetwork(id);\n }\n\n return await this.#setActiveEvmNetwork(id);\n }\n\n /**\n * Handles switching between EVM and non-EVM networks when an account is changed\n *\n * @param account - The account that was changed\n */\n readonly #handleSelectedAccountChange = (account: InternalAccount) => {\n const { type: accountType, address: accountAddress } = account;\n const isEvmAccount = isEvmAccountType(accountType);\n\n // Handle switching to EVM network\n if (isEvmAccount) {\n if (this.state.isEvmSelected) {\n // No need to update if already on evm network\n return;\n }\n\n // Make EVM network active\n this.update((state) => {\n state.isEvmSelected = true;\n });\n return;\n }\n\n // Handle switching to non-EVM network\n const nonEvmChainId = getChainIdForNonEvmAddress(accountAddress);\n const isSameNonEvmNetwork =\n nonEvmChainId === this.state.selectedMultichainNetworkChainId;\n\n if (isSameNonEvmNetwork) {\n // No need to update if already on the same non-EVM network\n this.update((state) => {\n state.isEvmSelected = false;\n });\n return;\n }\n\n this.update((state) => {\n state.selectedMultichainNetworkChainId = nonEvmChainId;\n state.isEvmSelected = false;\n });\n };\n\n /**\n * Subscribes to message events.\n */\n #subscribeToMessageEvents() {\n // Handle network switch when account is changed\n this.messagingSystem.subscribe(\n 'AccountsController:selectedAccountChange',\n this.#handleSelectedAccountChange,\n );\n }\n\n /**\n * Registers message handlers.\n */\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n 'MultichainNetworkController:setActiveNetwork',\n this.setActiveNetwork.bind(this),\n );\n }\n}\n"]}