From 2f815ba6210fb28987f11384bc723316638a0da5 Mon Sep 17 00:00:00 2001
From: Owen Craston <owengc12@gmail.com>
Date: Fri, 17 Jan 2025 13:01:03 -0800
Subject: [PATCH] split up non evm selectors

---
 app/selectors/multichain/index.ts             |   3 +-
 ...ltichain.test.ts => multichainEvm.test.ts} |  18 +-
 app/selectors/multichain/multichainEvm.ts     | 220 +++++++++++++++
 .../multichain/multichainNonEvm.test.ts       |  38 +++
 .../{multichain.ts => multichainNonEvm.ts}    | 258 ++----------------
 5 files changed, 280 insertions(+), 257 deletions(-)
 rename app/selectors/multichain/{multichain.test.ts => multichainEvm.test.ts} (89%)
 create mode 100644 app/selectors/multichain/multichainEvm.ts
 create mode 100644 app/selectors/multichain/multichainNonEvm.test.ts
 rename app/selectors/multichain/{multichain.ts => multichainNonEvm.ts} (57%)

diff --git a/app/selectors/multichain/index.ts b/app/selectors/multichain/index.ts
index f62c2c9df6ea..b12f88bc4238 100644
--- a/app/selectors/multichain/index.ts
+++ b/app/selectors/multichain/index.ts
@@ -1 +1,2 @@
-export * from './multichain';
+export * from './multichainEvm';
+export * from './multichainNonEvm';
diff --git a/app/selectors/multichain/multichain.test.ts b/app/selectors/multichain/multichainEvm.test.ts
similarity index 89%
rename from app/selectors/multichain/multichain.test.ts
rename to app/selectors/multichain/multichainEvm.test.ts
index 3e700a58f636..6b9cab1bd59c 100644
--- a/app/selectors/multichain/multichain.test.ts
+++ b/app/selectors/multichain/multichainEvm.test.ts
@@ -2,9 +2,7 @@ import { RootState } from '../../reducers';
 import {
   selectedAccountNativeTokenCachedBalanceByChainId,
   selectAccountTokensAcrossChains,
-  selectIsBitcoinSupportEnabled,
-  selectIsBitcoinTestnetSupportEnabled,
-} from './multichain';
+} from './multichainEvm';
 
 describe('Multichain Selectors', () => {
   const mockState: RootState = {
@@ -89,10 +87,6 @@ describe('Multichain Selectors', () => {
         },
       },
     },
-    multichainSettings: {
-      bitcoinSupportEnabled: true,
-      bitcoinTestnetSupportEnabled: false,
-    },
   } as unknown as RootState;
 
   describe('selectedAccountNativeTokenCachedBalanceByChainId', () => {
@@ -175,14 +169,4 @@ describe('Multichain Selectors', () => {
       );
     });
   });
-
-  describe('Bitcoin Support Flags', () => {
-    it('should return bitcoin support enabled state', () => {
-      expect(selectIsBitcoinSupportEnabled(mockState)).toBe(true);
-    });
-
-    it('should return bitcoin testnet support enabled state', () => {
-      expect(selectIsBitcoinTestnetSupportEnabled(mockState)).toBe(false);
-    });
-  });
 });
diff --git a/app/selectors/multichain/multichainEvm.ts b/app/selectors/multichain/multichainEvm.ts
new file mode 100644
index 000000000000..9dac3eb83020
--- /dev/null
+++ b/app/selectors/multichain/multichainEvm.ts
@@ -0,0 +1,220 @@
+import { createSelector } from 'reselect';
+import { Hex } from '@metamask/utils';
+import { Token, getNativeTokenAddress } from '@metamask/assets-controllers';
+import {
+  selectSelectedInternalAccountFormattedAddress,
+  selectSelectedInternalAccount,
+} from '../accountsController';
+import { selectAllTokens } from '../tokensController';
+import { selectAccountsByChainId } from '../accountTrackerController';
+import { selectNetworkConfigurations } from '../networkController';
+import { TokenI } from '../../components/UI/Tokens/types';
+import { renderFromWei, weiToFiat } from '../../util/number';
+import { hexToBN, toHex } from '@metamask/controller-utils';
+import {
+  selectCurrencyRates,
+  selectCurrentCurrency,
+} from '../currencyRateController';
+
+interface NativeTokenBalance {
+  balance: string;
+  stakedBalance: string;
+  isStaked: boolean;
+  name: string;
+}
+
+type ChainBalances = Record<string, NativeTokenBalance>;
+
+/**
+ * Get the cached native token balance for the selected account by chainId.
+ *
+ * @param {RootState} state - The root state.
+ * @returns {ChainBalances} The cached native token balance for the selected account by chainId.
+ */
+export const selectedAccountNativeTokenCachedBalanceByChainId = createSelector(
+  [selectSelectedInternalAccountFormattedAddress, selectAccountsByChainId],
+  (selectedAddress, accountsByChainId): ChainBalances => {
+    if (!selectedAddress || !accountsByChainId) {
+      return {};
+    }
+
+    const result: ChainBalances = {};
+    for (const chainId in accountsByChainId) {
+      const accounts = accountsByChainId[chainId];
+      const account = accounts[selectedAddress];
+      if (account) {
+        result[chainId] = {
+          balance: account.balance,
+          stakedBalance: account.stakedBalance ?? '0x0',
+          isStaked: account.stakedBalance !== '0x0',
+          name: '',
+        };
+      }
+    }
+
+    return result;
+  },
+);
+
+/**
+ * Selector to get native tokens for the selected account across all chains.
+ */
+export const selectNativeTokensAcrossChains = createSelector(
+  [
+    selectNetworkConfigurations,
+    selectedAccountNativeTokenCachedBalanceByChainId,
+    selectCurrencyRates,
+    selectCurrentCurrency,
+  ],
+  (
+    networkConfigurations,
+    nativeTokenBalancesByChainId,
+    currencyRates,
+    currentCurrency,
+  ) => {
+    const tokensByChain: { [chainId: string]: TokenI[] } = {};
+    for (const token of Object.values(networkConfigurations)) {
+      const nativeChainId = token.chainId as Hex;
+      const nativeTokenInfoByChainId =
+        nativeTokenBalancesByChainId[nativeChainId];
+      const isETH = ['ETH', 'GOETH', 'SepoliaETH', 'LineaETH'].includes(
+        token.nativeCurrency || '',
+      );
+
+      const name = isETH ? 'Ethereum' : token.nativeCurrency;
+      const logo = isETH ? '../images/eth-logo-new.png' : '';
+      tokensByChain[nativeChainId] = [];
+
+      const nativeBalanceFormatted = renderFromWei(
+        nativeTokenInfoByChainId?.balance,
+      );
+      const stakedBalanceFormatted = renderFromWei(
+        nativeTokenInfoByChainId?.stakedBalance,
+      );
+
+      let balanceFiat = '';
+      let stakedBalanceFiat = '';
+
+      const conversionRate =
+        currencyRates?.[token.nativeCurrency]?.conversionRate ?? 0;
+
+      balanceFiat = weiToFiat(
+        // TODO: Replace "any" with type
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any
+        hexToBN(nativeTokenInfoByChainId?.balance) as any,
+        conversionRate,
+        currentCurrency,
+      );
+      stakedBalanceFiat = weiToFiat(
+        // TODO: Replace "any" with type
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any
+        hexToBN(nativeTokenInfoByChainId?.stakedBalance) as any,
+        conversionRate,
+        currentCurrency,
+      );
+
+      const tokenByChain = {
+        ...nativeTokenInfoByChainId,
+        name,
+        address: getNativeTokenAddress(nativeChainId),
+        balance: nativeBalanceFormatted,
+        chainId: nativeChainId,
+        isNative: true,
+        aggregators: [],
+        balanceFiat,
+        image: '',
+        logo,
+        isETH,
+        decimals: 18,
+        symbol: name,
+        isStaked: false,
+        ticker: token.nativeCurrency,
+      };
+
+      // Non-staked tokens
+      tokensByChain[nativeChainId].push(tokenByChain);
+
+      if (
+        nativeTokenInfoByChainId &&
+        nativeTokenInfoByChainId.isStaked &&
+        nativeTokenInfoByChainId.stakedBalance !== '0x00' &&
+        nativeTokenInfoByChainId.stakedBalance !== toHex(0)
+      ) {
+        // Staked tokens
+        tokensByChain[nativeChainId].push({
+          ...nativeTokenInfoByChainId,
+          nativeAsset: tokenByChain,
+          chainId: nativeChainId,
+          address: getNativeTokenAddress(nativeChainId),
+          balance: stakedBalanceFormatted,
+          balanceFiat: stakedBalanceFiat,
+          isNative: true,
+          aggregators: [],
+          image: '',
+          logo,
+          isETH,
+          decimals: 18,
+          name: 'Staked Ethereum',
+          symbol: name,
+          isStaked: true,
+          ticker: token.nativeCurrency,
+        });
+      }
+    }
+
+    return tokensByChain;
+  },
+);
+
+/**
+ * Get the tokens for the selected account across all chains.
+ *
+ * @param {RootState} state - The root state.
+ * @returns {TokensByChain} The tokens for the selected account across all chains.
+ */
+export const selectAccountTokensAcrossChains = createSelector(
+  [
+    selectSelectedInternalAccount,
+    selectAllTokens,
+    selectNetworkConfigurations,
+    selectNativeTokensAcrossChains,
+  ],
+  (selectedAccount, allTokens, networkConfigurations, nativeTokens) => {
+    const selectedAddress = selectedAccount?.address;
+    const tokensByChain: {
+      [chainId: string]: (
+        | TokenI
+        | (Token & { isStaked?: boolean; isNative?: boolean; isETH?: boolean })
+      )[];
+    } = {};
+
+    if (!selectedAddress) {
+      return tokensByChain;
+    }
+
+    // Create a list of available chainIds
+    const chainIds = Object.keys(networkConfigurations);
+
+    for (const chainId of chainIds) {
+      const currentChainId = chainId as Hex;
+      const nonNativeTokens =
+        allTokens[currentChainId]?.[selectedAddress]?.map((token) => ({
+          ...token,
+          token: token.name,
+          chainId,
+          isETH: false,
+          isNative: false,
+          balanceFiat: '',
+          isStaked: false,
+        })) || [];
+
+      // Add both native and non-native tokens
+      tokensByChain[currentChainId] = [
+        ...(nativeTokens[currentChainId] || []),
+        ...nonNativeTokens,
+      ];
+    }
+
+    return tokensByChain;
+  },
+);
diff --git a/app/selectors/multichain/multichainNonEvm.test.ts b/app/selectors/multichain/multichainNonEvm.test.ts
new file mode 100644
index 000000000000..10ec7c50f509
--- /dev/null
+++ b/app/selectors/multichain/multichainNonEvm.test.ts
@@ -0,0 +1,38 @@
+import { RootState } from '../../reducers';
+import {
+  selectIsBitcoinSupportEnabled,
+  selectIsBitcoinTestnetSupportEnabled,
+} from './multichainNonEvm';
+
+describe('MultichainNonEvm Selectors', () => {
+  const mockState: RootState = {
+    engine: {
+      backgroundState: {
+        AccountsController: {
+          internalAccounts: {
+            selectedAccount: '0xAddress1',
+            accounts: {
+              '0xAddress1': {
+                address: '0xAddress1',
+              },
+            },
+          },
+        },
+      },
+    },
+    multichainSettings: {
+      bitcoinSupportEnabled: true,
+      bitcoinTestnetSupportEnabled: false,
+    },
+  } as unknown as RootState;
+
+  describe('Bitcoin Support Flags', () => {
+    it('should return bitcoin support enabled state', () => {
+      expect(selectIsBitcoinSupportEnabled(mockState)).toBe(true);
+    });
+
+    it('should return bitcoin testnet support enabled state', () => {
+      expect(selectIsBitcoinTestnetSupportEnabled(mockState)).toBe(false);
+    });
+  });
+});
diff --git a/app/selectors/multichain/multichain.ts b/app/selectors/multichain/multichainNonEvm.ts
similarity index 57%
rename from app/selectors/multichain/multichain.ts
rename to app/selectors/multichain/multichainNonEvm.ts
index 049c49b8bbb4..01fdf8fbb53f 100644
--- a/app/selectors/multichain/multichain.ts
+++ b/app/selectors/multichain/multichainNonEvm.ts
@@ -1,61 +1,35 @@
-import { createSelector } from 'reselect';
-import { CaipChainId, Hex } from '@metamask/utils';
-import {
-  MultichainNativeAssets,
-  Token,
-  getNativeTokenAddress,
-} from '@metamask/assets-controllers';
 import {
-  hexToBN,
-  toHex,
-  InfuraNetworkType,
-  NetworkType,
-  NetworkNickname,
-} from '@metamask/controller-utils';
+  MULTICHAIN_PROVIDER_CONFIGS,
+  MultichainProviderConfig,
+} from '../../core/Multichain/constants';
+import { CaipChainId, Hex } from '@metamask/utils';
+import { createSelector } from 'reselect';
 import { RootState } from '../../reducers';
 import {
-  selectSelectedInternalAccountFormattedAddress,
-  selectSelectedInternalAccount,
-} from '../accountsController';
-import { selectAllTokens } from '../tokensController';
-import {
-  selectAccountBalanceByChainId,
-  selectAccountsByChainId,
-} from '../accountTrackerController';
-import {
-  selectChainId,
   selectNetworkConfigurations,
+  selectChainId,
   selectProviderConfig,
 } from '../networkController';
-import { TokenI } from '../../components/UI/Tokens/types';
-import { renderFromWei, weiToFiat } from '../../util/number';
+import { selectSelectedInternalAccount } from '../accountsController';
+import { createDeepEqualSelector } from '../util';
+import { isEvmAccountType } from '@metamask/keyring-api';
 import {
-  selectConversionRate,
   selectCurrencyRates,
-  selectCurrentCurrency,
+  selectConversionRate,
 } from '../currencyRateController';
-
-import { isMainNet } from '../../util/networks';
-import { isBtcMainnetAddress } from '../../core/Multichain/utils';
-import { isEvmAccountType } from '@metamask/keyring-api';
-import { createDeepEqualSelector } from '../util';
-import {
-  MULTICHAIN_PROVIDER_CONFIGS,
-  MultichainProviderConfig,
-} from '../../core/Multichain/constants';
 import {
   NetworkClientConfiguration,
   NetworkClientType,
 } from '@metamask/network-controller';
-
-interface NativeTokenBalance {
-  balance: string;
-  stakedBalance: string;
-  isStaked: boolean;
-  name: string;
-}
-
-type ChainBalances = Record<string, NativeTokenBalance>;
+import {
+  NetworkType,
+  InfuraNetworkType,
+  NetworkNickname,
+} from '@metamask/controller-utils';
+import { isBtcMainnetAddress } from '../../core/Multichain/utils';
+import { isMainNet } from '../../util/networks';
+import { MultichainNativeAssets } from '@metamask/assets-controllers';
+import { selectAccountBalanceByChainId } from '../accountTrackerController';
 
 // Network types from controller-utils
 const NETWORK_TYPES = {
@@ -73,200 +47,6 @@ const NETWORK_TO_NAME_MAP = {
   [NETWORK_TYPES.SEPOLIA]: NetworkNickname.sepolia,
 } as const;
 
-/**
- * Get the cached native token balance for the selected account by chainId.
- *
- * @param {RootState} state - The root state.
- * @returns {ChainBalances} The cached native token balance for the selected account by chainId.
- */
-export const selectedAccountNativeTokenCachedBalanceByChainId = createSelector(
-  [selectSelectedInternalAccountFormattedAddress, selectAccountsByChainId],
-  (selectedAddress, accountsByChainId): ChainBalances => {
-    if (!selectedAddress || !accountsByChainId) {
-      return {};
-    }
-
-    const result: ChainBalances = {};
-    for (const chainId in accountsByChainId) {
-      const accounts = accountsByChainId[chainId];
-      const account = accounts[selectedAddress];
-      if (account) {
-        result[chainId] = {
-          balance: account.balance,
-          stakedBalance: account.stakedBalance ?? '0x0',
-          isStaked: account.stakedBalance !== '0x0',
-          name: '',
-        };
-      }
-    }
-
-    return result;
-  },
-);
-
-/**
- * Selector to get native tokens for the selected account across all chains.
- */
-export const selectNativeTokensAcrossChains = createSelector(
-  [
-    selectNetworkConfigurations,
-    selectedAccountNativeTokenCachedBalanceByChainId,
-    selectCurrencyRates,
-    selectCurrentCurrency,
-  ],
-  (
-    networkConfigurations,
-    nativeTokenBalancesByChainId,
-    currencyRates,
-    currentCurrency,
-  ) => {
-    const tokensByChain: { [chainId: string]: TokenI[] } = {};
-    for (const token of Object.values(networkConfigurations)) {
-      const nativeChainId = token.chainId as Hex;
-      const nativeTokenInfoByChainId =
-        nativeTokenBalancesByChainId[nativeChainId];
-      const isETH = ['ETH', 'GOETH', 'SepoliaETH', 'LineaETH'].includes(
-        token.nativeCurrency || '',
-      );
-
-      const name = isETH ? 'Ethereum' : token.nativeCurrency;
-      const logo = isETH ? '../images/eth-logo-new.png' : '';
-      tokensByChain[nativeChainId] = [];
-
-      const nativeBalanceFormatted = renderFromWei(
-        nativeTokenInfoByChainId?.balance,
-      );
-      const stakedBalanceFormatted = renderFromWei(
-        nativeTokenInfoByChainId?.stakedBalance,
-      );
-
-      let balanceFiat = '';
-      let stakedBalanceFiat = '';
-
-      const conversionRate =
-        currencyRates?.[token.nativeCurrency]?.conversionRate ?? 0;
-
-      balanceFiat = weiToFiat(
-        // TODO: Replace "any" with type
-        // eslint-disable-next-line @typescript-eslint/no-explicit-any
-        hexToBN(nativeTokenInfoByChainId?.balance) as any,
-        conversionRate,
-        currentCurrency,
-      );
-      stakedBalanceFiat = weiToFiat(
-        // TODO: Replace "any" with type
-        // eslint-disable-next-line @typescript-eslint/no-explicit-any
-        hexToBN(nativeTokenInfoByChainId?.stakedBalance) as any,
-        conversionRate,
-        currentCurrency,
-      );
-
-      const tokenByChain = {
-        ...nativeTokenInfoByChainId,
-        name,
-        address: getNativeTokenAddress(nativeChainId),
-        balance: nativeBalanceFormatted,
-        chainId: nativeChainId,
-        isNative: true,
-        aggregators: [],
-        balanceFiat,
-        image: '',
-        logo,
-        isETH,
-        decimals: 18,
-        symbol: name,
-        isStaked: false,
-        ticker: token.nativeCurrency,
-      };
-
-      // Non-staked tokens
-      tokensByChain[nativeChainId].push(tokenByChain);
-
-      if (
-        nativeTokenInfoByChainId &&
-        nativeTokenInfoByChainId.isStaked &&
-        nativeTokenInfoByChainId.stakedBalance !== '0x00' &&
-        nativeTokenInfoByChainId.stakedBalance !== toHex(0)
-      ) {
-        // Staked tokens
-        tokensByChain[nativeChainId].push({
-          ...nativeTokenInfoByChainId,
-          nativeAsset: tokenByChain,
-          chainId: nativeChainId,
-          address: getNativeTokenAddress(nativeChainId),
-          balance: stakedBalanceFormatted,
-          balanceFiat: stakedBalanceFiat,
-          isNative: true,
-          aggregators: [],
-          image: '',
-          logo,
-          isETH,
-          decimals: 18,
-          name: 'Staked Ethereum',
-          symbol: name,
-          isStaked: true,
-          ticker: token.nativeCurrency,
-        });
-      }
-    }
-
-    return tokensByChain;
-  },
-);
-
-/**
- * Get the tokens for the selected account across all chains.
- *
- * @param {RootState} state - The root state.
- * @returns {TokensByChain} The tokens for the selected account across all chains.
- */
-export const selectAccountTokensAcrossChains = createSelector(
-  [
-    selectSelectedInternalAccount,
-    selectAllTokens,
-    selectNetworkConfigurations,
-    selectNativeTokensAcrossChains,
-  ],
-  (selectedAccount, allTokens, networkConfigurations, nativeTokens) => {
-    const selectedAddress = selectedAccount?.address;
-    const tokensByChain: {
-      [chainId: string]: (
-        | TokenI
-        | (Token & { isStaked?: boolean; isNative?: boolean; isETH?: boolean })
-      )[];
-    } = {};
-
-    if (!selectedAddress) {
-      return tokensByChain;
-    }
-
-    // Create a list of available chainIds
-    const chainIds = Object.keys(networkConfigurations);
-
-    for (const chainId of chainIds) {
-      const currentChainId = chainId as Hex;
-      const nonNativeTokens =
-        allTokens[currentChainId]?.[selectedAddress]?.map((token) => ({
-          ...token,
-          token: token.name,
-          chainId,
-          isETH: false,
-          isNative: false,
-          balanceFiat: '',
-          isStaked: false,
-        })) || [];
-
-      // Add both native and non-native tokens
-      tokensByChain[currentChainId] = [
-        ...(nativeTokens[currentChainId] || []),
-        ...nonNativeTokens,
-      ];
-    }
-
-    return tokensByChain;
-  },
-);
-
 /**
  * Get the state of the `bitcoinSupportEnabled` flag.
  *