@metamask/multichain-network-controller
Version:
Multichain network controller
201 lines • 11.9 kB
JavaScript
"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 _MultichainNetworkController_instances, _MultichainNetworkController_networkService, _MultichainNetworkController_setActiveEvmNetwork, _MultichainNetworkController_setActiveNonEvmNetwork, _MultichainNetworkController_removeEvmNetwork, _MultichainNetworkController_removeNonEvmNetwork, _MultichainNetworkController_handleOnSelectedAccountChange, _MultichainNetworkController_subscribeToMessageEvents, _MultichainNetworkController_registerMessageHandlers;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MultichainNetworkController = void 0;
const base_controller_1 = require("@metamask/base-controller");
const keyring_api_1 = require("@metamask/keyring-api");
const utils_1 = require("@metamask/utils");
const accounts_api_1 = require("../api/accounts-api.cjs");
const constants_1 = require("../constants.cjs");
const types_1 = require("../types.cjs");
const utils_2 = require("../utils.cjs");
/**
* The MultichainNetworkController is responsible for fetching and caching account
* balances.
*/
class MultichainNetworkController extends base_controller_1.BaseController {
constructor({ messenger, state, networkService, }) {
super({
messenger,
name: types_1.MULTICHAIN_NETWORK_CONTROLLER_NAME,
metadata: constants_1.MULTICHAIN_NETWORK_CONTROLLER_METADATA,
state: {
...(0, constants_1.getDefaultMultichainNetworkControllerState)(),
...state,
// We can keep the current network as a hardcoded value
// since it is not expected to add/remove networks yet.
multichainNetworkConfigurationsByChainId: constants_1.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 ((0, utils_1.isCaipChainId)(id)) {
const isSupportedCaipChainId = (0, utils_2.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) => (0, accounts_api_1.toAllowedCaipAccountIds)(account))
.flat();
const activeNetworks = await __classPrivateFieldGet(this, _MultichainNetworkController_networkService, "f").fetchNetworkActivity(formattedAccounts);
const formattedNetworks = (0, accounts_api_1.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 ((0, utils_2.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);
}
}
exports.MultichainNetworkController = MultichainNetworkController;
_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 = (0, utils_2.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 = (0, keyring_api_1.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 = (0, utils_2.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.cjs.map