diff --git a/.yarn/patches/@metamask-assets-controllers-npm-43.1.1-c223d56176.patch b/.yarn/patches/@metamask-assets-controllers-npm-44.0.0-c223d56176.patch similarity index 100% rename from .yarn/patches/@metamask-assets-controllers-npm-43.1.1-c223d56176.patch rename to .yarn/patches/@metamask-assets-controllers-npm-44.0.0-c223d56176.patch diff --git a/app/scripts/constants/sentry-state.ts b/app/scripts/constants/sentry-state.ts index 6f960a496b3d..5146e38e8a41 100644 --- a/app/scripts/constants/sentry-state.ts +++ b/app/scripts/constants/sentry-state.ts @@ -355,6 +355,9 @@ export const SENTRY_BACKGROUND_STATE = { [AllProperties]: false, }, }, + TokenBalancesController: { + tokenBalances: false, + }, TokenRatesController: { marketData: false, }, diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 6e2ba119053c..cc7eaa12d3d1 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -12,6 +12,7 @@ import { CodefiTokenPricesServiceV2, RatesController, fetchMultiExchangeRate, + TokenBalancesController, } from '@metamask/assets-controllers'; import { JsonRpcEngine } from '@metamask/json-rpc-engine'; import { createEngineStream } from '@metamask/json-rpc-middleware-stream'; @@ -685,6 +686,7 @@ export default class MetamaskController extends EventEmitter { 'AccountsController:selectedEvmAccountChange', 'PreferencesController:stateChange', 'TokenListController:stateChange', + 'NetworkController:stateChange', ], }); this.tokensController = new TokensController({ @@ -893,6 +895,28 @@ export default class MetamaskController extends EventEmitter { }; }; + const tokenBalancesMessenger = this.controllerMessenger.getRestricted({ + name: 'TokenBalancesController', + allowedActions: [ + 'NetworkController:getState', + 'NetworkController:getNetworkClientById', + 'TokensController:getState', + 'PreferencesController:getState', + 'AccountsController:getSelectedAccount', + ], + allowedEvents: [ + 'PreferencesController:stateChange', + 'TokensController:stateChange', + 'NetworkController:stateChange', + ], + }); + + this.tokenBalancesController = new TokenBalancesController({ + messenger: tokenBalancesMessenger, + state: initState.TokenBalancesController, + interval: 30000, + }); + const phishingControllerMessenger = this.controllerMessenger.getRestricted({ name: 'PhishingController', }); @@ -2413,6 +2437,7 @@ export default class MetamaskController extends EventEmitter { GasFeeController: this.gasFeeController, TokenListController: this.tokenListController, TokensController: this.tokensController, + TokenBalancesController: this.tokenBalancesController, SmartTransactionsController: this.smartTransactionsController, NftController: this.nftController, PhishingController: this.phishingController, @@ -2468,6 +2493,7 @@ export default class MetamaskController extends EventEmitter { GasFeeController: this.gasFeeController, TokenListController: this.tokenListController, TokensController: this.tokensController, + TokenBalancesController: this.tokenBalancesController, SmartTransactionsController: this.smartTransactionsController, NftController: this.nftController, SelectedNetworkController: this.selectedNetworkController, @@ -3229,6 +3255,7 @@ export default class MetamaskController extends EventEmitter { nftController, nftDetectionController, currencyRateController, + tokenBalancesController, tokenDetectionController, ensController, tokenListController, @@ -4047,6 +4074,14 @@ export default class MetamaskController extends EventEmitter { tokenListStopPollingByPollingToken: tokenListController.stopPollingByPollingToken.bind(tokenListController), + tokenBalancesStartPolling: tokenBalancesController.startPolling.bind( + tokenBalancesController, + ), + tokenBalancesStopPollingByPollingToken: + tokenBalancesController.stopPollingByPollingToken.bind( + tokenBalancesController, + ), + // GasFeeController gasFeeStartPollingByNetworkClientId: gasFeeController.startPollingByNetworkClientId.bind(gasFeeController), @@ -6681,6 +6716,7 @@ export default class MetamaskController extends EventEmitter { this.tokenRatesController.stopAllPolling(); this.tokenDetectionController.stopAllPolling(); this.tokenListController.stopAllPolling(); + this.tokenBalancesController.stopAllPolling(); this.appStateController.clearPollingTokens(); } catch (error) { console.error(error); @@ -6921,6 +6957,9 @@ export default class MetamaskController extends EventEmitter { await this._createTransactionNotifcation(transactionMeta); await this._updateNFTOwnership(transactionMeta); this._trackTransactionFailure(transactionMeta); + await this.tokenBalancesController.updateBalancesByChainId({ + chainId: transactionMeta.chainId, + }); } async _createTransactionNotifcation(transactionMeta) { diff --git a/package.json b/package.json index ae2ebbd338a9..04098328933f 100644 --- a/package.json +++ b/package.json @@ -292,7 +292,7 @@ "@metamask/address-book-controller": "^6.0.0", "@metamask/announcement-controller": "^7.0.0", "@metamask/approval-controller": "^7.0.0", - "@metamask/assets-controllers": "patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A43.1.1%23~/.yarn/patches/@metamask-assets-controllers-npm-43.1.1-c223d56176.patch%3A%3Aversion=43.1.1&hash=5a94c2#~/.yarn/patches/@metamask-assets-controllers-patch-9e00573eb4.patch", + "@metamask/assets-controllers": "patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A44.0.0%23~/.yarn/patches/@metamask-assets-controllers-npm-44.0.0-c223d56176.patch%3A%3Aversion=44.0.0&hash=5a94c2#~/.yarn/patches/@metamask-assets-controllers-patch-9e00573eb4.patch", "@metamask/base-controller": "^7.0.0", "@metamask/bitcoin-wallet-snap": "^0.8.2", "@metamask/browser-passworder": "^4.3.0", diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json index 999dce99ca0c..e47cfcd806b9 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json @@ -314,6 +314,9 @@ "swapsFeatureFlags": {} } }, + "TokenBalancesController": { + "tokenBalances": "object" + }, "TokenListController": { "tokenList": "object", "tokensChainsCache": { diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json index acd9d6f8d074..7fd8501eb2b8 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json @@ -181,6 +181,7 @@ "0xe705": "object", "0xe708": "object" }, + "tokenBalances": "object", "preventPollingOnNetworkRestart": false, "tokens": "object", "ignoredTokens": "object", diff --git a/ui/components/app/assets/asset-list/asset-list.test.tsx b/ui/components/app/assets/asset-list/asset-list.test.tsx index 329c29a6108e..fd65e740238d 100644 --- a/ui/components/app/assets/asset-list/asset-list.test.tsx +++ b/ui/components/app/assets/asset-list/asset-list.test.tsx @@ -64,6 +64,8 @@ jest.mock('../../../../hooks/useIsOriginalNativeTokenSymbol', () => { jest.mock('../../../../store/actions', () => { return { getTokenSymbol: jest.fn(), + tokenBalancesStartPolling: jest.fn().mockResolvedValue('pollingToken'), + tokenBalancesStopPollingByPollingToken: jest.fn(), }; }); diff --git a/ui/components/app/wallet-overview/btc-overview.test.tsx b/ui/components/app/wallet-overview/btc-overview.test.tsx index 62e6f5ff82b3..671e03a87ea8 100644 --- a/ui/components/app/wallet-overview/btc-overview.test.tsx +++ b/ui/components/app/wallet-overview/btc-overview.test.tsx @@ -29,6 +29,8 @@ jest.mock('../../../store/actions', () => ({ handleSnapRequest: jest.fn(), sendMultichainTransaction: jest.fn(), setDefaultHomeActiveTabName: jest.fn(), + tokenBalancesStartPolling: jest.fn().mockResolvedValue('pollingToken'), + tokenBalancesStopPollingByPollingToken: jest.fn(), })); const PORTOFOLIO_URL = 'https://portfolio.test'; diff --git a/ui/components/app/wallet-overview/eth-overview.test.js b/ui/components/app/wallet-overview/eth-overview.test.js index 539cfbb6c59f..a8c490b923c6 100644 --- a/ui/components/app/wallet-overview/eth-overview.test.js +++ b/ui/components/app/wallet-overview/eth-overview.test.js @@ -38,6 +38,8 @@ jest.mock('../../../ducks/locale/locale', () => ({ jest.mock('../../../store/actions', () => ({ startNewDraftTransaction: jest.fn(), + tokenBalancesStartPolling: jest.fn().mockResolvedValue('pollingToken'), + tokenBalancesStopPollingByPollingToken: jest.fn(), })); const mockGetIntlLocale = getIntlLocale; diff --git a/ui/components/multichain/account-overview/account-overview-btc.test.tsx b/ui/components/multichain/account-overview/account-overview-btc.test.tsx index 1def72354c82..fa32883ce773 100644 --- a/ui/components/multichain/account-overview/account-overview-btc.test.tsx +++ b/ui/components/multichain/account-overview/account-overview-btc.test.tsx @@ -8,6 +8,11 @@ import { AccountOverviewBtcProps, } from './account-overview-btc'; +jest.mock('../../../store/actions', () => ({ + tokenBalancesStartPolling: jest.fn().mockResolvedValue('pollingToken'), + tokenBalancesStopPollingByPollingToken: jest.fn(), +})); + const defaultProps: AccountOverviewBtcProps = { defaultHomeActiveTabName: null, onTabClick: jest.fn(), diff --git a/ui/components/multichain/account-overview/account-overview-eth.test.tsx b/ui/components/multichain/account-overview/account-overview-eth.test.tsx index ba2049ffd205..f9b53665e753 100644 --- a/ui/components/multichain/account-overview/account-overview-eth.test.tsx +++ b/ui/components/multichain/account-overview/account-overview-eth.test.tsx @@ -8,6 +8,11 @@ import { AccountOverviewEthProps, } from './account-overview-eth'; +jest.mock('../../../store/actions', () => ({ + tokenBalancesStartPolling: jest.fn().mockResolvedValue('pollingToken'), + tokenBalancesStopPollingByPollingToken: jest.fn(), +})); + const render = (props: AccountOverviewEthProps) => { const store = configureStore({ metamask: mockState.metamask, diff --git a/ui/ducks/metamask/metamask.js b/ui/ducks/metamask/metamask.js index 63ff92a11ccc..7ddc156c92ae 100644 --- a/ui/ducks/metamask/metamask.js +++ b/ui/ducks/metamask/metamask.js @@ -457,6 +457,16 @@ export const getGasEstimateTypeByChainId = createSelector( }, ); +/** + * Returns the balances of imported and detected tokens across all accounts and chains. + * + * @param {*} state + * @returns { import('@metamask/assets-controllers').TokenBalancesControllerState['tokenBalances']} + */ +export function getTokenBalances(state) { + return state.metamask.tokenBalances; +} + export const getGasFeeEstimatesByChainId = createSelector( getGasFeeControllerEstimatesByChainId, getTransactionGasFeeEstimatesByChainId, diff --git a/ui/hooks/useAccountTotalFiatBalance.js b/ui/hooks/useAccountTotalFiatBalance.js index 7b4a4675225a..aa1f906473ef 100644 --- a/ui/hooks/useAccountTotalFiatBalance.js +++ b/ui/hooks/useAccountTotalFiatBalance.js @@ -22,7 +22,7 @@ import { import { formatCurrency } from '../helpers/utils/confirm-tx.util'; import { getTokenFiatAmount } from '../helpers/utils/token-util'; import { roundToDecimalPlacesRemovingExtraZeroes } from '../helpers/utils/util'; -import { useTokenTracker } from './useTokenTracker'; +import { useTokenTracker } from './useTokenBalances'; export const useAccountTotalFiatBalance = ( account, @@ -54,10 +54,11 @@ export const useAccountTotalFiatBalance = ( const primaryTokenImage = useSelector(getNativeCurrencyImage); const nativeCurrency = useSelector(getNativeCurrency); - const { loading, tokensWithBalances } = useTokenTracker({ + const loading = false; + const { tokensWithBalances } = useTokenTracker({ + chainId: currentChainId, tokens, address: account?.address, - includeFailedTokens: true, hideZeroBalanceTokens: shouldHideZeroBalanceTokens, }); diff --git a/ui/hooks/useAccountTotalFiatBalance.test.js b/ui/hooks/useAccountTotalFiatBalance.test.js index 9fb1227367e1..6ac93cd08e33 100644 --- a/ui/hooks/useAccountTotalFiatBalance.test.js +++ b/ui/hooks/useAccountTotalFiatBalance.test.js @@ -14,35 +14,6 @@ const mockAccount = createMockInternalAccount({ address: '0x0836f5ed6b62baf60706fe3adc0ff0fd1df833da', }); -jest.mock('./useTokenTracker', () => { - return { - useTokenTracker: () => ({ - loading: false, - tokensWithBalances: [ - { - address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - balance: '48573', - balanceError: null, - decimals: 6, - image: undefined, - isERC721: undefined, - string: '0.04857', - symbol: 'USDC', - }, - { - address: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', - symbol: 'YFI', - balance: '1409247882142934', - decimals: 18, - string: '0.001409247882142934', - balanceError: null, - }, - ], - error: null, - }), - }; -}); - const renderUseAccountTotalFiatBalance = (address) => { const state = { ...mockState, @@ -78,7 +49,7 @@ const renderUseAccountTotalFiatBalance = (address) => { }, ...mockNetworkState({ chainId: CHAIN_IDS.MAINNET }), - detectedTokens: { + allTokens: { '0x1': { '0x0836f5ed6b62baf60706fe3adc0ff0fd1df833da': [ { @@ -96,6 +67,14 @@ const renderUseAccountTotalFiatBalance = (address) => { ], }, }, + tokenBalances: { + [mockAccount.address]: { + [CHAIN_IDS.MAINNET]: { + '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': '0xBDBD', + '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e': '0x501B4176A64D6', + }, + }, + }, }, }; @@ -122,8 +101,6 @@ describe('useAccountTotalFiatBalance', () => { address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', symbol: 'USDC', balance: '48573', - image: undefined, - isERC721: undefined, decimals: 6, string: 0.04857, balanceError: null, diff --git a/ui/hooks/useMultichainAccountTotalFiatBalance.test.tsx b/ui/hooks/useMultichainAccountTotalFiatBalance.test.tsx index ffd664612a02..e46eff925e50 100644 --- a/ui/hooks/useMultichainAccountTotalFiatBalance.test.tsx +++ b/ui/hooks/useMultichainAccountTotalFiatBalance.test.tsx @@ -15,31 +15,21 @@ const mockTokenBalances = [ balance: '48573', balanceError: null, decimals: 6, - image: undefined, - isERC721: undefined, - string: '0.04857', + string: 0.04857, symbol: 'USDC', + tokenFiatAmount: '0.05', }, { address: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', symbol: 'YFI', balance: '1409247882142934', decimals: 18, - string: '0.001409247882142934', + string: 0.00141, balanceError: null, + tokenFiatAmount: '7.52', }, ]; -jest.mock('./useTokenTracker', () => { - return { - useTokenTracker: () => ({ - loading: false, - tokensWithBalances: mockTokenBalances, - error: null, - }), - }; -}); - const mockAccount = createMockInternalAccount({ name: 'Account 1', address: '0x0836f5ed6b62baf60706fe3adc0ff0fd1df833da', @@ -104,7 +94,7 @@ const renderUseMultichainAccountTotalFiatBalance = ( }, ...mockNetworkState({ chainId: CHAIN_IDS.MAINNET }), - detectedTokens: { + allTokens: { '0x1': { '0x0836f5ed6b62baf60706fe3adc0ff0fd1df833da': [ { @@ -122,6 +112,14 @@ const renderUseMultichainAccountTotalFiatBalance = ( ], }, }, + tokenBalances: { + [mockAccount.address]: { + [CHAIN_IDS.MAINNET]: { + '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': '0xBDBD', + '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e': '0x501B4176A64D6', + }, + }, + }, }, }; diff --git a/ui/hooks/useMultichainAccountTotalFiatBalance.ts b/ui/hooks/useMultichainAccountTotalFiatBalance.ts index 9e807be41ea5..335b8399c6d5 100644 --- a/ui/hooks/useMultichainAccountTotalFiatBalance.ts +++ b/ui/hooks/useMultichainAccountTotalFiatBalance.ts @@ -31,9 +31,9 @@ export const useMultichainAccountTotalFiatBalance = ( tokensWithBalances: { address: string; symbol: string; - decimals: string; - isERC721: boolean; - image: string; + decimals: number; + isERC721?: boolean; + image?: string; }[]; totalWeiBalance?: string; totalBalance?: string; diff --git a/ui/hooks/useTokenBalances.ts b/ui/hooks/useTokenBalances.ts new file mode 100644 index 000000000000..9ff92d488814 --- /dev/null +++ b/ui/hooks/useTokenBalances.ts @@ -0,0 +1,110 @@ +import { useSelector } from 'react-redux'; +import BN from 'bn.js'; +import { Token } from '@metamask/assets-controllers'; +import { Hex } from '@metamask/utils'; +import { getNetworkConfigurationsByChainId } from '../selectors'; +import { + tokenBalancesStartPolling, + tokenBalancesStopPollingByPollingToken, +} from '../store/actions'; +import { getTokenBalances } from '../ducks/metamask/metamask'; +import { hexToDecimal } from '../../shared/modules/conversion.utils'; +import useMultiPolling from './useMultiPolling'; + +export const useTokenBalances = ({ chainIds }: { chainIds?: Hex[] } = {}) => { + const tokenBalances = useSelector(getTokenBalances); + const networkConfigurations = useSelector(getNetworkConfigurationsByChainId); + + useMultiPolling({ + startPolling: tokenBalancesStartPolling, + stopPollingByPollingToken: tokenBalancesStopPollingByPollingToken, + input: chainIds ?? Object.keys(networkConfigurations), + }); + + return { tokenBalances }; +}; + +// This hook is designed for backwards compatibility with `ui/hooks/useTokenTracker.js` +// and the github.com/MetaMask/eth-token-tracker library. It replaces RPC calls with +// reading state from `TokenBalancesController`. It should not be used in new code. +// Instead, prefer to use `useTokenBalances` directly, or compose higher level hooks from it. +export const useTokenTracker = ({ + chainId, + tokens, + address, + hideZeroBalanceTokens, +}: { + chainId: Hex; + tokens: Token[]; + address: Hex; + hideZeroBalanceTokens?: boolean; +}) => { + const { tokenBalances } = useTokenBalances({ chainIds: [chainId] }); + + const tokensWithBalances = tokens.reduce((acc, token) => { + const hexBalance = + tokenBalances[address]?.[chainId]?.[token.address as Hex] ?? '0x0'; + if (hexBalance !== '0x0' || !hideZeroBalanceTokens) { + const decimalBalance = hexToDecimal(hexBalance); + acc.push({ + address: token.address, + symbol: token.symbol, + decimals: token.decimals, + balance: decimalBalance, + balanceError: null, + string: stringifyBalance( + new BN(decimalBalance), + new BN(token.decimals), + ), + }); + } + return acc; + }, [] as (Token & { balance: string; string: string; balanceError: unknown })[]); + + return { + tokensWithBalances, + }; +}; + +// From https://github.com/MetaMask/eth-token-tracker/blob/main/lib/util.js +// Ensures backwards compatibility with display formatting. +function stringifyBalance(balance: BN, bnDecimals: BN, balanceDecimals = 5) { + if (balance.eq(new BN(0))) { + return '0'; + } + + const decimals = parseInt(bnDecimals.toString(), 10); + if (decimals === 0) { + return balance.toString(); + } + + let bal = balance.toString(); + let len = bal.length; + let decimalIndex = len - decimals; + let prefix = ''; + + if (decimalIndex <= 0) { + while (prefix.length <= decimalIndex * -1) { + prefix += '0'; + len += 1; + } + bal = prefix + bal; + decimalIndex = 1; + } + + const whole = bal.substr(0, len - decimals); + + if (balanceDecimals === 0) { + return whole; + } + + const fractional = bal.substr(decimalIndex, balanceDecimals); + if (/0+$/u.test(fractional)) { + let withOnlySigZeroes = bal.substr(decimalIndex).replace(/0+$/u, ''); + if (withOnlySigZeroes.length > 0) { + withOnlySigZeroes = `.${withOnlySigZeroes}`; + } + return `${whole}${withOnlySigZeroes}`; + } + return `${whole}.${fractional}`; +} diff --git a/ui/pages/asset/components/asset-page.test.tsx b/ui/pages/asset/components/asset-page.test.tsx index 6bf1d12feb9e..5df516184004 100644 --- a/ui/pages/asset/components/asset-page.test.tsx +++ b/ui/pages/asset/components/asset-page.test.tsx @@ -13,6 +13,12 @@ import { setBackgroundConnection } from '../../../store/background-connection'; import { mockNetworkState } from '../../../../test/stub/networks'; import AssetPage from './asset-page'; +jest.mock('../../../store/actions', () => ({ + ...jest.requireActual('../../../store/actions'), + tokenBalancesStartPolling: jest.fn().mockResolvedValue('pollingToken'), + tokenBalancesStopPollingByPollingToken: jest.fn(), +})); + // Mock the price chart jest.mock('react-chartjs-2', () => ({ Line: () => null })); diff --git a/ui/pages/routes/routes.component.test.js b/ui/pages/routes/routes.component.test.js index 6151fedc687b..8a516fd76d6a 100644 --- a/ui/pages/routes/routes.component.test.js +++ b/ui/pages/routes/routes.component.test.js @@ -43,6 +43,8 @@ jest.mock('../../store/actions', () => ({ .mockResolvedValue({ chainId: '0x5' }), showNetworkDropdown: () => mockShowNetworkDropdown, hideNetworkDropdown: () => mockHideNetworkDropdown, + tokenBalancesStartPolling: jest.fn().mockResolvedValue('pollingToken'), + tokenBalancesStopPollingByPollingToken: jest.fn(), })); jest.mock('../../ducks/bridge/actions', () => ({ diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 32434d3a1d59..390db05f04df 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -4625,6 +4625,26 @@ export async function tokenListStopPollingByPollingToken(pollingToken: string) { await removePollingTokenFromAppState(pollingToken); } +export async function tokenBalancesStartPolling( + chainId: string, +): Promise { + const pollingToken = await submitRequestToBackground( + 'tokenBalancesStartPolling', + [{ chainId }], + ); + await addPollingTokenToAppState(pollingToken); + return pollingToken; +} + +export async function tokenBalancesStopPollingByPollingToken( + pollingToken: string, +) { + await submitRequestToBackground('tokenBalancesStopPollingByPollingToken', [ + pollingToken, + ]); + await removePollingTokenFromAppState(pollingToken); +} + /** * Informs the TokenRatesController that the UI requires * token rate polling for the given chain id. diff --git a/yarn.lock b/yarn.lock index 8d622a3d2d25..4602bb34f62f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4934,11 +4934,12 @@ __metadata: languageName: node linkType: hard -"@metamask/assets-controllers@npm:43.1.1": - version: 43.1.1 - resolution: "@metamask/assets-controllers@npm:43.1.1" +"@metamask/assets-controllers@npm:44.0.0": + version: 44.0.0 + resolution: "@metamask/assets-controllers@npm:44.0.0" dependencies: "@ethereumjs/util": "npm:^8.1.0" + "@ethersproject/abi": "npm:^5.7.0" "@ethersproject/address": "npm:^5.7.0" "@ethersproject/bignumber": "npm:^5.7.0" "@ethersproject/contracts": "npm:^5.7.0" @@ -4968,15 +4969,16 @@ __metadata: "@metamask/keyring-controller": ^18.0.0 "@metamask/network-controller": ^22.0.0 "@metamask/preferences-controller": ^14.0.0 - checksum: 10/e8f37928085a243f2f3a9d3b09b486f31737814d6257ee49bc2d841d2f467733b8c533c056e9ca24acdcc80414503b34b00e10abb1cdfeb8483e6fe30bc4a62f + checksum: 10/6f3d8712a90aa322aabd38d43663d299ad7ee98a6d838d72bfc3b426ea0e4e925bb78c1aaaa3c75d43e95d46993c47583a4a03f4c58aee155525424fa86207ae languageName: node linkType: hard -"@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A43.1.1#~/.yarn/patches/@metamask-assets-controllers-npm-43.1.1-c223d56176.patch::version=43.1.1&hash=5a94c2": - version: 43.1.1 - resolution: "@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A43.1.1#~/.yarn/patches/@metamask-assets-controllers-npm-43.1.1-c223d56176.patch::version=43.1.1&hash=5a94c2" +"@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A44.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-44.0.0-c223d56176.patch::version=44.0.0&hash=5a94c2": + version: 44.0.0 + resolution: "@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A44.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-44.0.0-c223d56176.patch::version=44.0.0&hash=5a94c2" dependencies: "@ethereumjs/util": "npm:^8.1.0" + "@ethersproject/abi": "npm:^5.7.0" "@ethersproject/address": "npm:^5.7.0" "@ethersproject/bignumber": "npm:^5.7.0" "@ethersproject/contracts": "npm:^5.7.0" @@ -5006,15 +5008,16 @@ __metadata: "@metamask/keyring-controller": ^18.0.0 "@metamask/network-controller": ^22.0.0 "@metamask/preferences-controller": ^14.0.0 - checksum: 10/1a3672cb721c6716d33c1c6c5e7ffc2859689407e70af7503204220afe41f6c0d20f883ad7d51089af7376e4005de7479525b3faa49113c942cf3ab1bceba154 + checksum: 10/0d6c386a1f1e68ab339340fd8fa600827f55f234bc54b2224069a1819ab037641daa9696a0d62f187c0649317393efaeeb119a7852af51da3bb340e0e98cf9f6 languageName: node linkType: hard -"@metamask/assets-controllers@patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A43.1.1%23~/.yarn/patches/@metamask-assets-controllers-npm-43.1.1-c223d56176.patch%3A%3Aversion=43.1.1&hash=5a94c2#~/.yarn/patches/@metamask-assets-controllers-patch-9e00573eb4.patch": - version: 43.1.1 - resolution: "@metamask/assets-controllers@patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A43.1.1%23~/.yarn/patches/@metamask-assets-controllers-npm-43.1.1-c223d56176.patch%3A%3Aversion=43.1.1&hash=5a94c2#~/.yarn/patches/@metamask-assets-controllers-patch-9e00573eb4.patch::version=43.1.1&hash=c4e407" +"@metamask/assets-controllers@patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A44.0.0%23~/.yarn/patches/@metamask-assets-controllers-npm-44.0.0-c223d56176.patch%3A%3Aversion=44.0.0&hash=5a94c2#~/.yarn/patches/@metamask-assets-controllers-patch-9e00573eb4.patch": + version: 44.0.0 + resolution: "@metamask/assets-controllers@patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A44.0.0%23~/.yarn/patches/@metamask-assets-controllers-npm-44.0.0-c223d56176.patch%3A%3Aversion=44.0.0&hash=5a94c2#~/.yarn/patches/@metamask-assets-controllers-patch-9e00573eb4.patch::version=44.0.0&hash=c4e407" dependencies: "@ethereumjs/util": "npm:^8.1.0" + "@ethersproject/abi": "npm:^5.7.0" "@ethersproject/address": "npm:^5.7.0" "@ethersproject/bignumber": "npm:^5.7.0" "@ethersproject/contracts": "npm:^5.7.0" @@ -5044,7 +5047,7 @@ __metadata: "@metamask/keyring-controller": ^18.0.0 "@metamask/network-controller": ^22.0.0 "@metamask/preferences-controller": ^14.0.0 - checksum: 10/189f45b9afefef9dc54f29920eb64fcebbc1dd13d792627ab2649c973a94ca310c848411fe4b294419c881d1956ff50bd6107f7411faa2a953da005662269e40 + checksum: 10/11e8920bdf8ffce4a534c6aadfe768176c4e461a00bc06e6ece52f085755ff252194881d9edd308097186a05057075fd9812b6e4b1fd97dd731814ad205013da languageName: node linkType: hard @@ -26737,7 +26740,7 @@ __metadata: "@metamask/announcement-controller": "npm:^7.0.0" "@metamask/api-specs": "npm:^0.9.3" "@metamask/approval-controller": "npm:^7.0.0" - "@metamask/assets-controllers": "patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A43.1.1%23~/.yarn/patches/@metamask-assets-controllers-npm-43.1.1-c223d56176.patch%3A%3Aversion=43.1.1&hash=5a94c2#~/.yarn/patches/@metamask-assets-controllers-patch-9e00573eb4.patch" + "@metamask/assets-controllers": "patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A44.0.0%23~/.yarn/patches/@metamask-assets-controllers-npm-44.0.0-c223d56176.patch%3A%3Aversion=44.0.0&hash=5a94c2#~/.yarn/patches/@metamask-assets-controllers-patch-9e00573eb4.patch" "@metamask/auto-changelog": "npm:^2.1.0" "@metamask/base-controller": "npm:^7.0.0" "@metamask/bitcoin-wallet-snap": "npm:^0.8.2"