diff --git a/app/components/UI/CollectibleContractElement/index.js b/app/components/UI/CollectibleContractElement/index.js index 3474d78e48d..574cfcc8911 100644 --- a/app/components/UI/CollectibleContractElement/index.js +++ b/app/components/UI/CollectibleContractElement/index.js @@ -92,7 +92,6 @@ function CollectibleContractElement({ chainId, selectedAddress, removeFavoriteCollectible, - toggleRemovingProgress, }) { const [collectiblesGrid, setCollectiblesGrid] = useState([]); const [collectiblesVisible, setCollectiblesVisible] = useState( @@ -150,11 +149,7 @@ function CollectibleContractElement({ const handleMenuAction = (index) => { if (index === 1) { - // set toggle to true - toggleRemovingProgress(); removeNft(); - // set toggle to false to indicate that removing the NFT has finished - toggleRemovingProgress(); } else if (index === 0) { refreshMetadata(); } @@ -306,7 +301,6 @@ CollectibleContractElement.propTypes = { * Dispatch remove collectible from favorites action */ removeFavoriteCollectible: PropTypes.func, - toggleRemovingProgress: PropTypes.func, }; const mapStateToProps = (state) => ({ diff --git a/app/components/UI/CollectibleContracts/index.js b/app/components/UI/CollectibleContracts/index.js index 4dbd431d91c..fe0269cd51d 100644 --- a/app/components/UI/CollectibleContracts/index.js +++ b/app/components/UI/CollectibleContracts/index.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback, useMemo } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import PropTypes from 'prop-types'; import { TouchableOpacity, @@ -9,7 +9,7 @@ import { FlatList, RefreshControl, } from 'react-native'; -import { connect, useSelector } from 'react-redux'; +import { connect } from 'react-redux'; import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import Engine from '../../../core/Engine'; @@ -23,7 +23,7 @@ import { import { removeFavoriteCollectible } from '../../../actions/collectibles'; import Text from '../../Base/Text'; import AppConstants from '../../../core/AppConstants'; -import { isIPFSUri, toLowerCaseEquals } from '../../../util/general'; +import { toLowerCaseEquals } from '../../../util/general'; import { compareTokenIds } from '../../../util/tokens'; import CollectibleDetectionModal from '../CollectibleDetectionModal'; import { useTheme } from '../../../util/theme'; @@ -37,13 +37,11 @@ import { selectIsIpfsGatewayEnabled, selectSelectedAddress, selectUseNftDetection, - selectDisplayNftMedia, } from '../../../selectors/preferencesController'; import { IMPORT_NFT_BUTTON_ID, NFT_TAB_CONTAINER_ID, } from '../../../../wdio/screen-objects/testIDs/Screens/WalletView.testIds'; -import Logger from '../../../util/Logger'; import { useMetrics } from '../../../components/hooks/useMetrics'; const createStyles = (colors) => @@ -114,13 +112,6 @@ const CollectibleContracts = ({ const [isAddNFTEnabled, setIsAddNFTEnabled] = useState(true); const [refreshing, setRefreshing] = useState(false); - const [isRemovingNftInProgress, setIsRemovingNftInProgress] = useState(false); - - const toggleRemovingProgress = () => - setIsRemovingNftInProgress((value) => !value); - - const displayNftMedia = useSelector(selectDisplayNftMedia); - const isCollectionDetectionBannerVisible = networkType === MAINNET && !useNftDetection; @@ -160,19 +151,60 @@ const CollectibleContracts = ({ typeof collectible.tokenId === 'number' || (typeof collectible.tokenId === 'string' && !isNaN(collectible.tokenId)); - /** - * Method to updated collectible and avoid backwards compatibility issues. - * @param address - Collectible address. - * @param tokenId - Collectible token ID. - */ - const updateCollectibleMetadata = useCallback( + const updateAllCollectibleMetadata = useCallback( + async (collectibles) => { + const { NftController } = Engine.context; + // Filter out ignored collectibles + const filteredcollectibles = collectibles.filter( + (collectible) => !isCollectibleIgnored(collectible), + ); + + // filter removable collectible + const removable = filteredcollectibles.filter((single) => + String(single.tokenId).includes('e+'), + ); + const updatable = filteredcollectibles.filter( + (single) => !String(single.tokenId).includes('e+'), + ); + + removable.forEach((elm) => { + removeFavoriteCollectible(selectedAddress, chainId, elm); + }); + + filteredcollectibles.forEach((collectible) => { + if (String(collectible.tokenId).includes('e+')) { + removeFavoriteCollectible(selectedAddress, chainId, collectible); + } + }); + + if (updatable.length !== 0) { + await NftController.updateNftMetadata({ + nfts: updatable, + userAddress: selectedAddress, + }); + } + }, + [isCollectibleIgnored, removeFavoriteCollectible, chainId, selectedAddress], + ); + + useEffect(() => { + // TO DO: Move this fix to the controllers layer + const updatableCollectibles = collectibles.filter((single) => + shouldUpdateCollectibleMetadata(single), + ); + if (updatableCollectibles.length !== 0) { + updateAllCollectibleMetadata(updatableCollectibles); + } + }, [collectibles, updateAllCollectibleMetadata]); + + /* const updateCollectibleMetadata = useCallback( async (collectible) => { const { NftController } = Engine.context; const { address, tokenId } = collectible; const isIgnored = isCollectibleIgnored(collectible); - if (!isRemovingNftInProgress && !isIgnored) { + if (!isIgnored) { if (String(tokenId).includes('e+')) { removeFavoriteCollectible(selectedAddress, chainId, collectible); } else { @@ -180,13 +212,7 @@ const CollectibleContracts = ({ } } }, - [ - chainId, - removeFavoriteCollectible, - selectedAddress, - isCollectibleIgnored, - isRemovingNftInProgress, - ], + [chainId, removeFavoriteCollectible, selectedAddress, isCollectibleIgnored], ); useEffect(() => { @@ -196,80 +222,7 @@ const CollectibleContracts = ({ updateCollectibleMetadata(collectible); } }); - }, [collectibles, updateCollectibleMetadata]); - - const memoizedCollectibles = useMemo(() => collectibles, [collectibles]); - - const isNftUpdatableWithOpenSea = (collectible) => - Boolean( - !collectible.image && - !collectible.name && - !collectible.description && - // Preventing on a loop if the proxy or open sea api can't be fetched - !( - collectible.error?.startsWith('Opensea') || - collectible.error?.startsWith('Both') - ), - ); - - const updateOpenSeaUnfetchedMetadata = useCallback(async () => { - try { - if (displayNftMedia) { - const promises = memoizedCollectibles.map(async (collectible) => { - if (isNftUpdatableWithOpenSea(collectible)) { - await updateCollectibleMetadata(collectible); - } - }); - - await Promise.all(promises); - } - } catch (error) { - Logger.error( - error, - 'error while trying to update metadata of stored nfts', - ); - } - }, [updateCollectibleMetadata, memoizedCollectibles, displayNftMedia]); - - useEffect(() => { - updateOpenSeaUnfetchedMetadata(); - }, [updateOpenSeaUnfetchedMetadata]); - - const isNftUpdatableWithThirdParties = (collectible) => - Boolean( - !collectible.image && - !collectible.name && - !collectible.description && - isIPFSUri(collectible.tokenURI) && - // Preventing on a loop if the third party service can't be fetched - !( - collectible.error?.startsWith('URI') || - collectible.error?.startsWith('Both') - ), - ); - - const updateThirdPartyUnfetchedMetadata = useCallback(async () => { - try { - if (isIpfsGatewayEnabled) { - const promises = memoizedCollectibles.map(async (collectible) => { - if (isNftUpdatableWithThirdParties(collectible)) { - await updateCollectibleMetadata(collectible); - } - }); - - await Promise.all(promises); - } - } catch (error) { - Logger.error( - error, - 'error while trying to update metadata of stored nfts', - ); - } - }, [updateCollectibleMetadata, isIpfsGatewayEnabled, memoizedCollectibles]); - - useEffect(() => { - updateThirdPartyUnfetchedMetadata(); - }, [updateThirdPartyUnfetchedMetadata]); + }, [collectibles, updateCollectibleMetadata]); */ const goToAddCollectible = useCallback(() => { setIsAddNFTEnabled(false); @@ -310,7 +263,6 @@ const CollectibleContracts = ({ key={item.address} contractCollectibles={contractCollectibles} collectiblesVisible={index === 0} - toggleRemovingProgress={toggleRemovingProgress} /> ); }, @@ -333,12 +285,10 @@ const CollectibleContracts = ({ key={'Favorites'} contractCollectibles={filteredCollectibles} collectiblesVisible - toggleRemovingProgress={toggleRemovingProgress} /> ) ); }, [favoriteCollectibles, collectibles, onItemPress]); - const onRefresh = useCallback(async () => { requestAnimationFrame(async () => { setRefreshing(true); diff --git a/app/components/UI/CollectibleContracts/index.test.tsx b/app/components/UI/CollectibleContracts/index.test.tsx index aedf262024e..1db8f3d45cd 100644 --- a/app/components/UI/CollectibleContracts/index.test.tsx +++ b/app/components/UI/CollectibleContracts/index.test.tsx @@ -31,6 +31,7 @@ jest.mock('../../../core/Engine', () => ({ context: { NftController: { addNft: jest.fn(), + updateNftMetadata: jest.fn(), checkAndUpdateAllNftsOwnershipStatus: jest.fn(), }, NftDetectionController: { @@ -219,6 +220,7 @@ describe('CollectibleContracts', () => { }, NftController: { addNft: jest.fn(), + updateNftMetadata: jest.fn(), allNfts: { [CURRENT_ACCOUNT]: { '1': [], @@ -241,8 +243,8 @@ describe('CollectibleContracts', () => { const spyOnContracts = jest .spyOn(allSelectors, 'collectibleContractsSelector') .mockReturnValue(collectibleData); - const spyOnAddNft = jest - .spyOn(Engine.context.NftController, 'addNft') + const spyOnUpdateNftMetadata = jest + .spyOn(Engine.context.NftController, 'updateNftMetadata') .mockImplementation(async () => undefined); const { getByTestId } = renderWithProvider(, { @@ -256,7 +258,7 @@ describe('CollectibleContracts', () => { }); await waitFor(() => { - expect(spyOnAddNft).toHaveBeenCalled(); + expect(spyOnUpdateNftMetadata).toHaveBeenCalled(); const nftImageAfter = queryByTestId('nft-image'); expect(nftImageAfter.props.source.uri).toEqual( nftItemDataUpdated[0].image, @@ -265,6 +267,6 @@ describe('CollectibleContracts', () => { spyOnCollectibles.mockRestore(); spyOnContracts.mockRestore(); - spyOnAddNft.mockRestore(); + spyOnUpdateNftMetadata.mockRestore(); }); }); diff --git a/patches/@metamask+assets-controllers+12.0.0.patch b/patches/@metamask+assets-controllers+12.0.0.patch index 2aa755699da..58363257d47 100644 --- a/patches/@metamask+assets-controllers+12.0.0.patch +++ b/patches/@metamask+assets-controllers+12.0.0.patch @@ -1,23 +1,23 @@ diff --git a/node_modules/@metamask/assets-controllers/dist/.patch.txt b/node_modules/@metamask/assets-controllers/dist/.patch.txt new file mode 100644 -index 0000000..8197c83 +index 0000000..550de56 --- /dev/null +++ b/node_modules/@metamask/assets-controllers/dist/.patch.txt @@ -0,0 +1,14 @@ -+PATCH GENERATED FROM MetaMask/core branch: patch/mobile-assets-controllers-v-11-1-0 ++PATCH GENERATED FROM MetaMask/core branch: patch/mobile-assets-controllers-v-12-0-0 +This patch backports various assets controllers features from the main branch of MetaMask/core +Steps to update patch: -+* Create a new core branch from: patch/mobile-assets-controllers-v-11-1-0 ++* Create a new core branch from: patch/mobile-assets-controllers-v-12-0-0 +* Run "yarn build" in the core monorepo +* Run "yarn patch:assets " in the mobile repo -+* If you have changes also add them to the branch: patch/mobile-assets-controllers-v-11-1-0 ++* If you have changes also add them to the branch: patch/mobile-assets-controllers-v-12-0-0 +* Steps to update the assets-controllers version +* Create a new core branch from the next assets-controllers version -+* Merge the branch patch/mobile-assets-controllers-v-11-1-0 ++* Merge the branch patch/mobile-assets-controllers-v-12-0-0 +* Solve the conflicts and review changes accordingly the changelog +* Run "yarn build" in the core monorepo +* Run "yarn patch:assets " in the mobile repo -+* If you have changes also add them to the branch: patch/mobile-assets-controllers-v-11-1-0 ++* If you have changes also add them to the branch: patch/mobile-assets-controllers-v-12-0-0 diff --git a/node_modules/@metamask/assets-controllers/dist/AccountTrackerController.d.ts b/node_modules/@metamask/assets-controllers/dist/AccountTrackerController.d.ts index 41bf5fe..7b4be39 100644 --- a/node_modules/@metamask/assets-controllers/dist/AccountTrackerController.d.ts @@ -370,7 +370,7 @@ index 19038c2..7de82d8 100644 +{"version":3,"file":"CurrencyRateController.js","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Mutex } from 'async-mutex';\nimport type { Patch } from 'immer';\nimport {\n BaseControllerV2,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport {\n TESTNET_TICKER_SYMBOLS,\n FALL_BACK_VS_CURRENCY,\n safelyExecute,\n} from '@metamask/controller-utils';\nimport { fetchExchangeRate as defaultFetchExchangeRate } from './crypto-compare';\n\n/**\n * @type CurrencyRateState\n * @property conversionDate - Timestamp of conversion rate expressed in ms since UNIX epoch\n * @property conversionRate - Conversion rate from current base asset to the current currency\n * @property currentCurrency - Currently-active ISO 4217 currency code\n * @property nativeCurrency - Symbol for the base asset used for conversion\n * @property pendingCurrentCurrency - The currency being switched to\n * @property pendingNativeCurrency - The base asset currency being switched to\n * @property usdConversionRate - Conversion rate from usd to the current currency\n */\nexport type CurrencyRateState = {\n conversionDate: number | null;\n conversionRate: number | null;\n currentCurrency: string;\n nativeCurrency: string;\n pendingCurrentCurrency: string | null;\n pendingNativeCurrency: string | null;\n usdConversionRate: number | null;\n};\n\nconst name = 'CurrencyRateController';\n\nexport type CurrencyRateStateChange = {\n type: `${typeof name}:stateChange`;\n payload: [CurrencyRateState, Patch[]];\n};\n\nexport type GetCurrencyRateState = {\n type: `${typeof name}:getState`;\n handler: () => CurrencyRateState;\n};\n\ntype CurrencyRateMessenger = RestrictedControllerMessenger<\n typeof name,\n GetCurrencyRateState,\n CurrencyRateStateChange,\n never,\n never\n>;\n\nconst metadata = {\n conversionDate: { persist: true, anonymous: true },\n conversionRate: { persist: true, anonymous: true },\n currentCurrency: { persist: true, anonymous: true },\n nativeCurrency: { persist: true, anonymous: true },\n pendingCurrentCurrency: { persist: false, anonymous: true },\n pendingNativeCurrency: { persist: false, anonymous: true },\n usdConversionRate: { persist: true, anonymous: true },\n};\n\nconst defaultState = {\n conversionDate: 0,\n conversionRate: 0,\n currentCurrency: 'usd',\n nativeCurrency: 'ETH',\n pendingCurrentCurrency: null,\n pendingNativeCurrency: null,\n usdConversionRate: null,\n};\n\n/**\n * Controller that passively polls on a set interval for an exchange rate from the current network\n * asset to the user's preferred currency.\n */\nexport class CurrencyRateController extends BaseControllerV2<\n typeof name,\n CurrencyRateState,\n CurrencyRateMessenger\n> {\n private mutex = new Mutex();\n\n private intervalId?: ReturnType;\n\n private intervalDelay;\n\n private fetchExchangeRate;\n\n private includeUsdRate;\n\n /**\n * A boolean that controls whether or not network requests can be made by the controller\n */\n #enabled;\n\n /**\n * Creates a CurrencyRateController instance.\n *\n * @param options - Constructor options.\n * @param options.includeUsdRate - Keep track of the USD rate in addition to the current currency rate.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.messenger - A reference to the messaging system.\n * @param options.state - Initial state to set on this controller.\n * @param options.fetchExchangeRate - Fetches the exchange rate from an external API. This option is primarily meant for use in unit tests.\n */\n constructor({\n includeUsdRate = false,\n interval = 180000,\n messenger,\n state,\n fetchExchangeRate = defaultFetchExchangeRate,\n }: {\n includeUsdRate?: boolean;\n interval?: number;\n messenger: CurrencyRateMessenger;\n state?: Partial;\n fetchExchangeRate?: typeof defaultFetchExchangeRate;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.includeUsdRate = includeUsdRate;\n this.intervalDelay = interval;\n this.fetchExchangeRate = fetchExchangeRate;\n this.#enabled = false;\n }\n\n /**\n * Start polling for the currency rate.\n */\n async start() {\n this.#enabled = true;\n\n await this.startPolling();\n }\n\n /**\n * Stop polling for the currency rate.\n */\n stop() {\n this.#enabled = false;\n\n this.stopPolling();\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n /**\n * Sets a currency to track.\n *\n * @param currentCurrency - ISO 4217 currency code.\n */\n async setCurrentCurrency(currentCurrency: string) {\n this.update((state) => {\n state.pendingCurrentCurrency = currentCurrency;\n });\n await this.updateExchangeRate();\n }\n\n /**\n * Sets a new native currency.\n *\n * @param symbol - Symbol for the base asset.\n */\n async setNativeCurrency(symbol: string) {\n this.update((state) => {\n state.pendingNativeCurrency = symbol;\n });\n await this.updateExchangeRate();\n }\n\n private stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n }\n\n /**\n * Starts a new polling interval.\n */\n private async startPolling(): Promise {\n this.stopPolling();\n // TODO: Expose polling currency rate update errors\n\n await safelyExecute(async () => await this.updateExchangeRate());\n\n this.intervalId = setInterval(async () => {\n await safelyExecute(async () => await this.updateExchangeRate());\n }, this.intervalDelay);\n }\n\n /**\n * Updates exchange rate for the current currency.\n *\n * @returns The controller state.\n */\n async updateExchangeRate(): Promise {\n if (!this.#enabled) {\n console.info(\n '[CurrencyRateController] Not updating exchange rate since network requests have been disabled',\n );\n return this.state;\n }\n const releaseLock = await this.mutex.acquire();\n const {\n currentCurrency: stateCurrentCurrency,\n nativeCurrency: stateNativeCurrency,\n pendingCurrentCurrency,\n pendingNativeCurrency,\n } = this.state;\n\n let conversionDate: number | null = null;\n let conversionRate: number | null = null;\n let usdConversionRate: number | null = null;\n const currentCurrency = pendingCurrentCurrency ?? stateCurrentCurrency;\n const nativeCurrency = pendingNativeCurrency ?? stateNativeCurrency;\n\n // For preloaded testnets (Goerli, Sepolia) we want to fetch exchange rate for real ETH.\n const nativeCurrencyForExchangeRate = Object.values(\n TESTNET_TICKER_SYMBOLS,\n ).includes(nativeCurrency)\n ? FALL_BACK_VS_CURRENCY // ETH\n : nativeCurrency;\n\n try {\n if (\n currentCurrency &&\n nativeCurrency &&\n // if either currency is an empty string we can skip the comparison\n // because it will result in an error from the api and ultimately\n // a null conversionRate either way.\n currentCurrency !== '' &&\n nativeCurrency !== ''\n ) {\n const fetchExchangeRateResponse = await this.fetchExchangeRate(\n currentCurrency,\n nativeCurrencyForExchangeRate,\n this.includeUsdRate,\n );\n\n conversionRate = fetchExchangeRateResponse.conversionRate;\n usdConversionRate = fetchExchangeRateResponse.usdConversionRate;\n conversionDate = Date.now() / 1000;\n }\n } catch (error) {\n if (\n !(\n error instanceof Error &&\n error.message.includes('market does not exist for this coin pair')\n )\n ) {\n throw error;\n }\n } finally {\n try {\n this.update(() => {\n return {\n conversionDate,\n conversionRate,\n // we currently allow and handle an empty string as a valid nativeCurrency\n // in cases where a user has not entered a native ticker symbol for a custom network\n // currentCurrency is not from user input but this protects us from unexpected changes.\n nativeCurrency,\n currentCurrency,\n pendingCurrentCurrency: null,\n pendingNativeCurrency: null,\n usdConversionRate,\n };\n });\n } finally {\n releaseLock();\n }\n }\n return this.state;\n }\n}\n\nexport default CurrencyRateController;\n"]} \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/NftController.d.ts b/node_modules/@metamask/assets-controllers/dist/NftController.d.ts -index b322b8b..e19956d 100644 +index b322b8b..78ecbbf 100644 --- a/node_modules/@metamask/assets-controllers/dist/NftController.d.ts +++ b/node_modules/@metamask/assets-controllers/dist/NftController.d.ts @@ -1,14 +1,13 @@ @@ -530,17 +530,35 @@ index b322b8b..e19956d 100644 /** * Creates an NftController instance. * +@@ -383,6 +455,17 @@ export declare class NftController extends BaseController { + * @returns Promise resolving to the current NFT list. + */ + addNft(address: string, tokenId: string, nftMetadata?: NftMetadata, accountParams?: AccountParams, source?: Source): Promise; ++ /** ++ * Refetches NFT metadata and updates the state ++ * ++ * @param options - Options for refetching NFT metadata ++ * @param options.nfts - nfts to update metadata for. ++ * @param options.userAddress - The current user address ++ */ ++ updateNftMetadata({ nfts, userAddress, }: { ++ nfts: Nft[]; ++ userAddress?: string; ++ }): Promise; + /** + * Removes an NFT from the stored token list. + * diff --git a/node_modules/@metamask/assets-controllers/dist/NftController.d.ts.map b/node_modules/@metamask/assets-controllers/dist/NftController.d.ts.map -index a51fdf7..37e2d3e 100644 +index a51fdf7..825e5f7 100644 --- a/node_modules/@metamask/assets-controllers/dist/NftController.d.ts.map +++ b/node_modules/@metamask/assets-controllers/dist/NftController.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"NftController.d.ts","sourceRoot":"","sources":["../src/NftController.ts"],"names":[],"mappings":"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"} \ No newline at end of file -+{"version":3,"file":"NftController.d.ts","sourceRoot":"","sources":["../src/NftController.ts"],"names":[],"mappings":"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"} ++{"version":3,"file":"NftController.d.ts","sourceRoot":"","sources":["../src/NftController.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/NftController.js b/node_modules/@metamask/assets-controllers/dist/NftController.js -index 3d65ff2..10259a1 100644 +index 3d65ff2..f41375c 100644 --- a/node_modules/@metamask/assets-controllers/dist/NftController.js +++ b/node_modules/@metamask/assets-controllers/dist/NftController.js @@ -9,17 +9,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge @@ -580,12 +598,13 @@ index 3d65ff2..10259a1 100644 useIPFSSubdomains: true, isIpfsGatewayEnabled: true, }; -@@ -82,11 +86,11 @@ class NftController extends base_controller_1.BaseController { +@@ -82,24 +86,41 @@ class NftController extends base_controller_1.BaseController { this.getERC1155TokenURI = getERC1155TokenURI; this.onNftAdded = onNftAdded; this.messagingSystem = messenger; - onPreferencesStateChange(({ selectedAddress, ipfsGateway, openSeaEnabled, isIpfsGatewayEnabled, }) => { -+ onPreferencesStateChange(({ selectedAddress, ipfsGateway, displayNftMedia, isIpfsGatewayEnabled, }) => { ++ onPreferencesStateChange(({ selectedAddress, ipfsGateway, displayNftMedia, isIpfsGatewayEnabled, }) => __awaiter(this, void 0, void 0, function* () { ++ var _a, _b; this.configure({ selectedAddress, ipfsGateway, @@ -593,8 +612,24 @@ index 3d65ff2..10259a1 100644 + displayNftMedia, isIpfsGatewayEnabled, }); - }); -@@ -96,10 +100,13 @@ class NftController extends base_controller_1.BaseController { +- }); ++ const needsUpdateNftMetadata = (isIpfsGatewayEnabled && ipfsGateway !== '') || displayNftMedia; ++ if (needsUpdateNftMetadata) { ++ const { chainId } = this.config; ++ const nfts = (_b = (_a = this.state.allNfts[selectedAddress]) === null || _a === void 0 ? void 0 : _a[chainId]) !== null && _b !== void 0 ? _b : []; ++ // filter only nfts ++ const nftsToUpdate = nfts.filter((singleNft) => !singleNft.name && !singleNft.description && !singleNft.image); ++ if (nftsToUpdate.length !== 0) { ++ yield this.updateNftMetadata({ ++ nfts: nftsToUpdate, ++ userAddress: selectedAddress, ++ }); ++ } ++ } ++ })); + onNetworkStateChange(({ providerConfig }) => { + const { chainId } = providerConfig; + this.configure({ chainId }); }); } getNftApi({ contractAddress, tokenId, }) { @@ -610,7 +645,7 @@ index 3d65ff2..10259a1 100644 } /** * Helper method to update nested state for allNfts and allNftContracts. -@@ -131,30 +138,41 @@ class NftController extends base_controller_1.BaseController { +@@ -131,30 +152,41 @@ class NftController extends base_controller_1.BaseController { */ getNftInformationFromApi(contractAddress, tokenId) { return __awaiter(this, void 0, void 0, function* () { @@ -669,7 +704,7 @@ index 3d65ff2..10259a1 100644 }); } /** -@@ -166,10 +184,20 @@ class NftController extends base_controller_1.BaseController { +@@ -166,10 +198,20 @@ class NftController extends base_controller_1.BaseController { */ getNftInformationFromTokenURI(contractAddress, tokenId) { return __awaiter(this, void 0, void 0, function* () { @@ -691,7 +726,7 @@ index 3d65ff2..10259a1 100644 const hasIpfsTokenURI = tokenURI.startsWith('ipfs://'); if (hasIpfsTokenURI && !isIpfsGatewayEnabled) { return { -@@ -184,6 +212,16 @@ class NftController extends base_controller_1.BaseController { +@@ -184,6 +226,16 @@ class NftController extends base_controller_1.BaseController { if (hasIpfsTokenURI) { tokenURI = (0, assetsUtil_1.getFormattedIpfsUrl)(ipfsGateway, tokenURI, useIPFSSubdomains); } @@ -708,7 +743,7 @@ index 3d65ff2..10259a1 100644 try { const object = yield (0, controller_utils_1.handleFetch)(tokenURI); // TODO: Check image_url existence. This is not part of EIP721 nor EIP1155 -@@ -207,6 +245,7 @@ class NftController extends base_controller_1.BaseController { +@@ -207,6 +259,7 @@ class NftController extends base_controller_1.BaseController { standard: standard || null, favorite: false, tokenURI: tokenURI !== null && tokenURI !== void 0 ? tokenURI : null, @@ -716,7 +751,7 @@ index 3d65ff2..10259a1 100644 }; } }); -@@ -258,18 +297,29 @@ class NftController extends base_controller_1.BaseController { +@@ -258,18 +311,29 @@ class NftController extends base_controller_1.BaseController { * @returns Promise resolving to the current NFT name and image. */ getNftInformation(contractAddress, tokenId) { @@ -749,7 +784,7 @@ index 3d65ff2..10259a1 100644 }); } /** -@@ -288,7 +338,16 @@ class NftController extends base_controller_1.BaseController { +@@ -288,7 +352,16 @@ class NftController extends base_controller_1.BaseController { }); // if we successfully fetched return the fetched data immediately if (apiNftContractObject) { @@ -767,7 +802,7 @@ index 3d65ff2..10259a1 100644 } // If we've reached this point we were unable to fetch data from either the proxy or opensea so we return // the default/null of ApiNftContract -@@ -337,7 +396,7 @@ class NftController extends base_controller_1.BaseController { +@@ -337,7 +410,7 @@ class NftController extends base_controller_1.BaseController { return yield this.getNftContractInformationFromContract(contractAddress); })); let openSeaContractData; @@ -776,7 +811,7 @@ index 3d65ff2..10259a1 100644 openSeaContractData = yield (0, controller_utils_1.safelyExecute)(() => __awaiter(this, void 0, void 0, function* () { return yield this.getNftContractInformationFromApi(contractAddress); })); -@@ -419,6 +478,7 @@ class NftController extends base_controller_1.BaseController { +@@ -419,6 +492,7 @@ class NftController extends base_controller_1.BaseController { tokenId: tokenId.toString(), standard: nftMetadata.standard, source, @@ -784,7 +819,7 @@ index 3d65ff2..10259a1 100644 }); } return newNfts; -@@ -469,7 +529,7 @@ class NftController extends base_controller_1.BaseController { +@@ -469,7 +543,7 @@ class NftController extends base_controller_1.BaseController { if (k === 'collection') { return (v === null || v === void 0 ? void 0 : v.name) === null && (v === null || v === void 0 ? void 0 : v.image_url) === null; } @@ -793,7 +828,56 @@ index 3d65ff2..10259a1 100644 })) { return nftContracts; } -@@ -770,7 +830,7 @@ class NftController extends base_controller_1.BaseController { +@@ -699,6 +773,48 @@ class NftController extends base_controller_1.BaseController { + } + }); + } ++ /** ++ * Refetches NFT metadata and updates the state ++ * ++ * @param options - Options for refetching NFT metadata ++ * @param options.nfts - nfts to update metadata for. ++ * @param options.userAddress - The current user address ++ */ ++ updateNftMetadata({ nfts, userAddress = this.config.selectedAddress, }) { ++ var _a; ++ return __awaiter(this, void 0, void 0, function* () { ++ const { chainId } = this.config; ++ const nftsWithChecksumAdr = nfts.map((nft) => { ++ return Object.assign(Object.assign({}, nft), { address: (0, controller_utils_1.toChecksumHexAddress)(nft.address) }); ++ }); ++ const nftMetadataResults = yield Promise.allSettled(nftsWithChecksumAdr.map((nft) => __awaiter(this, void 0, void 0, function* () { ++ const resMetadata = yield this.getNftInformation(nft.address, nft.tokenId); ++ return { ++ nft, ++ newMetadata: resMetadata, ++ }; ++ }))); ++ const successfulNewFetchedNfts = nftMetadataResults.filter((result) => result.status === 'fulfilled'); ++ // We want to avoid updating the state if the state and fetched nft info are the same ++ const nftsWithDifferentMetadata = []; ++ const { allNfts } = this.state; ++ const stateNfts = ((_a = allNfts[userAddress]) === null || _a === void 0 ? void 0 : _a[chainId]) || []; ++ successfulNewFetchedNfts.forEach((singleNft) => { ++ const existingEntry = stateNfts.find((nft) => nft.address.toLowerCase() === ++ singleNft.value.nft.address.toLowerCase() && ++ nft.tokenId === singleNft.value.nft.tokenId); ++ if (existingEntry) { ++ const differentMetadata = (0, assetsUtil_1.compareNftMetadata)(singleNft.value.newMetadata, existingEntry); ++ if (differentMetadata) { ++ nftsWithDifferentMetadata.push(singleNft); ++ } ++ } ++ }); ++ if (nftsWithDifferentMetadata.length !== 0) { ++ nftsWithDifferentMetadata.forEach((elm) => this.updateNft(elm.value.nft, elm.value.newMetadata, userAddress, chainId)); ++ } ++ }); ++ } + /** + * Removes an NFT from the stored token list. + * +@@ -770,7 +886,7 @@ class NftController extends base_controller_1.BaseController { } } nft.isCurrentlyOwned = isOwned; @@ -803,13 +887,13 @@ index 3d65ff2..10259a1 100644 } // if this is not part of a batched update we update this one NFT in state diff --git a/node_modules/@metamask/assets-controllers/dist/NftController.js.map b/node_modules/@metamask/assets-controllers/dist/NftController.js.map -index 90c895d..afeca87 100644 +index 90c895d..dc54674 100644 --- a/node_modules/@metamask/assets-controllers/dist/NftController.js.map +++ b/node_modules/@metamask/assets-controllers/dist/NftController.js.map @@ -1 +1 @@ -{"version":3,"file":"NftController.js","sourceRoot":"","sources":["../src/NftController.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAddress } from '@ethersproject/address';\nimport type { AddApprovalRequest } from '@metamask/approval-controller';\nimport type {\n BaseConfig,\n BaseState,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport {\n safelyExecute,\n handleFetch,\n toChecksumHexAddress,\n BNToHex,\n fetchWithErrorHandling,\n IPFS_DEFAULT_GATEWAY_URL,\n ERC721,\n ERC1155,\n OPENSEA_PROXY_URL,\n ApprovalType,\n} from '@metamask/controller-utils';\nimport type { NetworkState } from '@metamask/network-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { BN, stripHexPrefix } from 'ethereumjs-util';\nimport { EventEmitter } from 'events';\nimport { v4 as random } from 'uuid';\n\nimport type { AssetsContractController } from './AssetsContractController';\nimport { compareNftMetadata, getFormattedIpfsUrl } from './assetsUtil';\nimport { Source } from './constants';\nimport type {\n ApiNft,\n ApiNftCreator,\n ApiNftContract,\n ApiNftLastSale,\n} from './NftDetectionController';\n\ntype NFTStandardType = 'ERC721' | 'ERC1155';\n\ntype SuggestedNftMeta = {\n asset: { address: string; tokenId: string } & NftMetadata;\n id: string;\n time: number;\n type: NFTStandardType;\n interactingAddress: string;\n origin: string;\n};\n\n/**\n * @type Nft\n *\n * NFT representation\n * @property address - Hex address of a ERC721 contract\n * @property description - The NFT description\n * @property image - URI of custom NFT image associated with this tokenId\n * @property name - Name associated with this tokenId and contract address\n * @property tokenId - The NFT identifier\n * @property numberOfSales - Number of sales\n * @property backgroundColor - The background color to be displayed with the item\n * @property imagePreview - URI of a smaller image associated with this NFT\n * @property imageThumbnail - URI of a thumbnail image associated with this NFT\n * @property imageOriginal - URI of the original image associated with this NFT\n * @property animation - URI of a animation associated with this NFT\n * @property animationOriginal - URI of the original animation associated with this NFT\n * @property externalLink - External link containing additional information\n * @property creator - The NFT owner information object\n * @property isCurrentlyOwned - Boolean indicating whether the address/chainId combination where it's currently stored currently owns this NFT\n * @property transactionId - Transaction Id associated with the NFT\n */\nexport interface Nft extends NftMetadata {\n tokenId: string;\n address: string;\n isCurrentlyOwned?: boolean;\n}\n\n/**\n * @type NftContract\n *\n * NFT contract information representation\n * @property name - Contract name\n * @property logo - Contract logo\n * @property address - Contract address\n * @property symbol - Contract symbol\n * @property description - Contract description\n * @property totalSupply - Total supply of NFTs\n * @property assetContractType - The NFT type, it could be `semi-fungible` or `non-fungible`\n * @property createdDate - Creation date\n * @property schemaName - The schema followed by the contract, it could be `ERC721` or `ERC1155`\n * @property externalLink - External link containing additional information\n */\nexport interface NftContract {\n name?: string;\n logo?: string;\n address: string;\n symbol?: string;\n description?: string;\n totalSupply?: string;\n assetContractType?: string;\n createdDate?: string;\n schemaName?: string;\n externalLink?: string;\n}\n\n/**\n * @type NftMetadata\n *\n * NFT custom information\n * @property name - NFT custom name\n * @property description - The NFT description\n * @property numberOfSales - Number of sales\n * @property backgroundColor - The background color to be displayed with the item\n * @property image - Image custom image URI\n * @property imagePreview - URI of a smaller image associated with this NFT\n * @property imageThumbnail - URI of a thumbnail image associated with this NFT\n * @property imageOriginal - URI of the original image associated with this NFT\n * @property animation - URI of a animation associated with this NFT\n * @property animationOriginal - URI of the original animation associated with this NFT\n * @property externalLink - External link containing additional information\n * @property creator - The NFT owner information object\n * @property standard - NFT standard name for the NFT, e.g., ERC-721 or ERC-1155\n */\nexport interface NftMetadata {\n name: string | null;\n description: string | null;\n image: string | null;\n standard: string | null;\n favorite?: boolean;\n numberOfSales?: number;\n backgroundColor?: string;\n imagePreview?: string;\n imageThumbnail?: string;\n imageOriginal?: string;\n animation?: string;\n animationOriginal?: string;\n externalLink?: string;\n creator?: ApiNftCreator;\n lastSale?: ApiNftLastSale;\n transactionId?: string;\n tokenURI?: string | null;\n}\n\ninterface AccountParams {\n userAddress: string;\n chainId: Hex;\n}\n\n/**\n * @type NftConfig\n *\n * NFT controller configuration\n * @property selectedAddress - Vault selected address\n */\nexport interface NftConfig extends BaseConfig {\n selectedAddress: string;\n chainId: Hex;\n ipfsGateway: string;\n openSeaEnabled: boolean;\n useIPFSSubdomains: boolean;\n isIpfsGatewayEnabled: boolean;\n}\n\n/**\n * @type NftState\n *\n * NFT controller state\n * @property allNftContracts - Object containing NFT contract information\n * @property allNfts - Object containing NFTs per account and network\n * @property ignoredNfts - List of NFTs that should be ignored\n */\nexport interface NftState extends BaseState {\n allNftContracts: {\n [key: string]: { [chainId: Hex]: NftContract[] };\n };\n allNfts: { [key: string]: { [chainId: Hex]: Nft[] } };\n ignoredNfts: Nft[];\n}\n\nconst ALL_NFTS_STATE_KEY = 'allNfts';\nconst ALL_NFTS_CONTRACTS_STATE_KEY = 'allNftContracts';\n\ninterface NftAsset {\n address: string;\n tokenId: string;\n}\n\n/**\n * The name of the {@link NftController}.\n */\nconst controllerName = 'NftController';\n\n/**\n * The external actions available to the {@link NftController}.\n */\ntype AllowedActions = AddApprovalRequest;\n\n/**\n * The messenger of the {@link NftController}.\n */\nexport type NftControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n AllowedActions,\n never,\n AllowedActions['type'],\n never\n>;\n\n/**\n * Controller that stores assets and exposes convenience methods\n */\nexport class NftController extends BaseController {\n private readonly mutex = new Mutex();\n\n private readonly messagingSystem: NftControllerMessenger;\n\n private getNftApi({\n contractAddress,\n tokenId,\n }: {\n contractAddress: string;\n tokenId: string;\n }) {\n return `${OPENSEA_PROXY_URL}/asset/${contractAddress}/${tokenId}`;\n }\n\n private getNftContractInformationApi({\n contractAddress,\n }: {\n contractAddress: string;\n }) {\n return `${OPENSEA_PROXY_URL}/asset_contract/${contractAddress}`;\n }\n\n /**\n * Helper method to update nested state for allNfts and allNftContracts.\n *\n * @param newCollection - the modified piece of state to update in the controller's store\n * @param baseStateKey - The root key in the store to update.\n * @param passedConfig - An object containing the selectedAddress and chainId that are passed through the auto-detection flow.\n * @param passedConfig.userAddress - the address passed through the NFT detection flow to ensure assets are stored to the correct account\n * @param passedConfig.chainId - the chainId passed through the NFT detection flow to ensure assets are stored to the correct account\n */\n private updateNestedNftState(\n newCollection: Nft[] | NftContract[],\n baseStateKey: 'allNfts' | 'allNftContracts',\n { userAddress, chainId } = {\n userAddress: this.config.selectedAddress,\n chainId: this.config.chainId,\n },\n ) {\n const { [baseStateKey]: oldState } = this.state;\n\n const addressState = oldState[userAddress];\n const newAddressState = {\n ...addressState,\n ...{ [chainId]: newCollection },\n };\n const newState = {\n ...oldState,\n ...{ [userAddress]: newAddressState },\n };\n\n this.update({\n [baseStateKey]: newState,\n });\n }\n\n /**\n * Request individual NFT information from OpenSea API.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformationFromApi(\n contractAddress: string,\n tokenId: string,\n ): Promise {\n // Attempt to fetch the data with the proxy\n const nftInformation: ApiNft | undefined = await fetchWithErrorHandling({\n url: this.getNftApi({\n contractAddress,\n tokenId,\n }),\n });\n\n // if we were still unable to fetch the data we return out the default/null of `NftMetadata`\n if (!nftInformation) {\n return {\n name: null,\n description: null,\n image: null,\n standard: null,\n };\n }\n\n // if we've reached this point, we have successfully fetched some data for nftInformation\n // now we reconfigure the data to conform to the `NftMetadata` type for storage.\n const {\n num_sales,\n background_color,\n image_url,\n image_preview_url,\n image_thumbnail_url,\n image_original_url,\n animation_url,\n animation_original_url,\n name,\n description,\n external_link,\n creator,\n last_sale,\n asset_contract: { schema_name },\n } = nftInformation;\n\n /* istanbul ignore next */\n const nftMetadata: NftMetadata = Object.assign(\n {},\n { name: name || null },\n { description: description || null },\n { image: image_url || null },\n creator && { creator },\n num_sales && { numberOfSales: num_sales },\n background_color && { backgroundColor: background_color },\n image_preview_url && { imagePreview: image_preview_url },\n image_thumbnail_url && { imageThumbnail: image_thumbnail_url },\n image_original_url && { imageOriginal: image_original_url },\n animation_url && { animation: animation_url },\n animation_original_url && {\n animationOriginal: animation_original_url,\n },\n external_link && { externalLink: external_link },\n last_sale && { lastSale: last_sale },\n schema_name && { standard: schema_name },\n );\n\n return nftMetadata;\n }\n\n /**\n * Request individual NFT information from contracts that follows Metadata Interface.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformationFromTokenURI(\n contractAddress: string,\n tokenId: string,\n ): Promise {\n const { ipfsGateway, useIPFSSubdomains, isIpfsGatewayEnabled } =\n this.config;\n const result = await this.getNftURIAndStandard(contractAddress, tokenId);\n let tokenURI = result[0];\n const standard = result[1];\n\n const hasIpfsTokenURI = tokenURI.startsWith('ipfs://');\n\n if (hasIpfsTokenURI && !isIpfsGatewayEnabled) {\n return {\n image: null,\n name: null,\n description: null,\n standard: standard || null,\n favorite: false,\n tokenURI: tokenURI ?? null,\n };\n }\n if (hasIpfsTokenURI) {\n tokenURI = getFormattedIpfsUrl(ipfsGateway, tokenURI, useIPFSSubdomains);\n }\n\n try {\n const object = await handleFetch(tokenURI);\n // TODO: Check image_url existence. This is not part of EIP721 nor EIP1155\n const image = Object.prototype.hasOwnProperty.call(object, 'image')\n ? 'image'\n : /* istanbul ignore next */ 'image_url';\n\n return {\n image: object[image],\n name: object.name,\n description: object.description,\n standard,\n favorite: false,\n tokenURI: tokenURI ?? null,\n };\n } catch {\n return {\n image: null,\n name: null,\n description: null,\n standard: standard || null,\n favorite: false,\n tokenURI: tokenURI ?? null,\n };\n }\n }\n\n /**\n * Retrieve NFT uri with metadata. TODO Update method to use IPFS.\n *\n * @param contractAddress - NFT contract address.\n * @param tokenId - NFT token id.\n * @returns Promise resolving NFT uri and token standard.\n */\n private async getNftURIAndStandard(\n contractAddress: string,\n tokenId: string,\n ): Promise<[string, string]> {\n // try ERC721 uri\n try {\n const uri = await this.getERC721TokenURI(contractAddress, tokenId);\n return [uri, ERC721];\n } catch {\n // Ignore error\n }\n\n // try ERC1155 uri\n try {\n const tokenURI = await this.getERC1155TokenURI(contractAddress, tokenId);\n\n /**\n * According to EIP1155 the URI value allows for ID substitution\n * in case the string `{id}` exists.\n * https://eips.ethereum.org/EIPS/eip-1155#metadata\n */\n\n if (!tokenURI.includes('{id}')) {\n return [tokenURI, ERC1155];\n }\n\n const hexTokenId = stripHexPrefix(BNToHex(new BN(tokenId)))\n .padStart(64, '0')\n .toLowerCase();\n return [tokenURI.replace('{id}', hexTokenId), ERC1155];\n } catch {\n // Ignore error\n }\n\n return ['', ''];\n }\n\n /**\n * Request individual NFT information (name, image url and description).\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformation(\n contractAddress: string,\n tokenId: string,\n ): Promise {\n const blockchainMetadata = await safelyExecute(async () => {\n return await this.getNftInformationFromTokenURI(contractAddress, tokenId);\n });\n\n let openSeaMetadata;\n if (this.config.openSeaEnabled) {\n openSeaMetadata = await safelyExecute(async () => {\n return await this.getNftInformationFromApi(contractAddress, tokenId);\n });\n }\n return {\n ...openSeaMetadata,\n name: blockchainMetadata.name ?? openSeaMetadata?.name ?? null,\n description:\n blockchainMetadata.description ?? openSeaMetadata?.description ?? null,\n image: blockchainMetadata.image ?? openSeaMetadata?.image ?? null,\n standard:\n blockchainMetadata.standard ?? openSeaMetadata?.standard ?? null,\n tokenURI: blockchainMetadata.tokenURI ?? null,\n };\n }\n\n /**\n * Request NFT contract information from OpenSea API.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftContractInformationFromApi(\n contractAddress: string,\n ): Promise {\n /* istanbul ignore if */\n const apiNftContractObject: ApiNftContract | undefined =\n await fetchWithErrorHandling({\n url: this.getNftContractInformationApi({\n contractAddress,\n }),\n });\n\n // if we successfully fetched return the fetched data immediately\n if (apiNftContractObject) {\n return apiNftContractObject;\n }\n\n // If we've reached this point we were unable to fetch data from either the proxy or opensea so we return\n // the default/null of ApiNftContract\n return {\n address: contractAddress,\n asset_contract_type: null,\n created_date: null,\n schema_name: null,\n symbol: null,\n total_supply: null,\n description: null,\n external_link: null,\n collection: {\n name: null,\n image_url: null,\n },\n };\n }\n\n /**\n * Request NFT contract information from the contract itself.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftContractInformationFromContract(\n contractAddress: string,\n ): Promise<\n Partial &\n Pick &\n Pick\n > {\n const name = await this.getERC721AssetName(contractAddress);\n const symbol = await this.getERC721AssetSymbol(contractAddress);\n return {\n collection: { name },\n symbol,\n address: contractAddress,\n };\n }\n\n /**\n * Request NFT contract information from OpenSea API.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @returns Promise resolving to the NFT contract name, image and description.\n */\n private async getNftContractInformation(\n contractAddress: string,\n ): Promise<\n Partial &\n Pick &\n Pick\n > {\n const blockchainContractData: Partial &\n Pick &\n Pick = await safelyExecute(async () => {\n return await this.getNftContractInformationFromContract(contractAddress);\n });\n\n let openSeaContractData: Partial | undefined;\n if (this.config.openSeaEnabled) {\n openSeaContractData = await safelyExecute(async () => {\n return await this.getNftContractInformationFromApi(contractAddress);\n });\n }\n\n if (blockchainContractData || openSeaContractData) {\n return {\n ...openSeaContractData,\n ...blockchainContractData,\n collection: {\n image_url: null,\n ...openSeaContractData?.collection,\n ...blockchainContractData?.collection,\n },\n };\n }\n\n /* istanbul ignore next */\n return {\n address: contractAddress,\n asset_contract_type: null,\n created_date: null,\n schema_name: null,\n symbol: null,\n total_supply: null,\n description: null,\n external_link: null,\n collection: { name: null, image_url: null },\n };\n }\n\n /**\n * Adds an individual NFT to the stored NFT list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @param nftMetadata - NFT optional information (name, image and description).\n * @param nftContract - An object containing contract data of the NFT being added.\n * @param accountParams - The chain ID and address of network and account to which the nftContract should be added.\n * @param source - Whether the NFT was detected, added manually or suggested by a dapp.\n * @returns Promise resolving to the current NFT list.\n */\n private async addIndividualNft(\n address: string,\n tokenId: string,\n nftMetadata: NftMetadata,\n nftContract: NftContract,\n accountParams?: AccountParams,\n source = Source.Custom,\n ): Promise {\n // TODO: Remove unused return\n const releaseLock = await this.mutex.acquire();\n try {\n address = toChecksumHexAddress(address);\n const { allNfts } = this.state;\n let chainId, selectedAddress;\n if (accountParams) {\n chainId = accountParams.chainId;\n selectedAddress = accountParams.userAddress;\n } else {\n chainId = this.config.chainId;\n selectedAddress = this.config.selectedAddress;\n }\n\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n\n const existingEntry: Nft | undefined = nfts.find(\n (nft) =>\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId,\n );\n\n if (existingEntry) {\n const differentMetadata = compareNftMetadata(\n nftMetadata,\n existingEntry,\n );\n if (differentMetadata || !existingEntry.isCurrentlyOwned) {\n // TODO: Switch to indexToUpdate\n const indexToRemove = nfts.findIndex(\n (nft) =>\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId,\n );\n /* istanbul ignore next */\n if (indexToRemove !== -1) {\n nfts.splice(indexToRemove, 1);\n }\n } else {\n return nfts;\n }\n }\n\n const newEntry: Nft = {\n address,\n tokenId,\n favorite: existingEntry?.favorite || false,\n isCurrentlyOwned: true,\n ...nftMetadata,\n };\n\n const newNfts = [...nfts, newEntry];\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY, {\n chainId,\n userAddress: selectedAddress,\n });\n\n if (this.onNftAdded) {\n this.onNftAdded({\n address,\n symbol: nftContract.symbol,\n tokenId: tokenId.toString(),\n standard: nftMetadata.standard,\n source,\n });\n }\n\n return newNfts;\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Adds an NFT contract to the stored NFT contracts list.\n *\n * @param address - Hex address of the NFT contract.\n * @param accountParams - The chain ID and address of network and account to which the nftContract should be added.\n * @param source - Whether the NFT was detected, added manually or suggested by a dapp.\n * @returns Promise resolving to the current NFT contracts list.\n */\n private async addNftContract(\n address: string,\n accountParams?: AccountParams,\n source?: Source,\n ): Promise {\n const releaseLock = await this.mutex.acquire();\n try {\n address = toChecksumHexAddress(address);\n const { allNftContracts } = this.state;\n let chainId, selectedAddress;\n if (accountParams) {\n chainId = accountParams.chainId;\n selectedAddress = accountParams.userAddress;\n } else {\n chainId = this.config.chainId;\n selectedAddress = this.config.selectedAddress;\n }\n\n const nftContracts = allNftContracts[selectedAddress]?.[chainId] || [];\n\n const existingEntry = nftContracts.find(\n (nftContract) =>\n nftContract.address.toLowerCase() === address.toLowerCase(),\n );\n if (existingEntry) {\n return nftContracts;\n }\n const contractInformation = await this.getNftContractInformation(address);\n const {\n asset_contract_type,\n created_date,\n schema_name,\n symbol,\n total_supply,\n description,\n external_link,\n collection: { name, image_url },\n } = contractInformation;\n\n // If the nft is auto-detected we want some valid metadata to be present\n if (\n source === Source.Detected &&\n Object.entries(contractInformation).every(([k, v]: [string, any]) => {\n if (k === 'address') {\n return true; // address will always be present\n }\n // collection will always be an object, we need to check the internal values\n if (k === 'collection') {\n return v?.name === null && v?.image_url === null;\n }\n return !v;\n })\n ) {\n return nftContracts;\n }\n\n /* istanbul ignore next */\n const newEntry: NftContract = Object.assign(\n {},\n { address },\n description && { description },\n name && { name },\n image_url && { logo: image_url },\n symbol && { symbol },\n total_supply !== null &&\n typeof total_supply !== 'undefined' && { totalSupply: total_supply },\n asset_contract_type && { assetContractType: asset_contract_type },\n created_date && { createdDate: created_date },\n schema_name && { schemaName: schema_name },\n external_link && { externalLink: external_link },\n );\n const newNftContracts = [...nftContracts, newEntry];\n this.updateNestedNftState(newNftContracts, ALL_NFTS_CONTRACTS_STATE_KEY, {\n chainId,\n userAddress: selectedAddress,\n });\n\n return newNftContracts;\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Removes an individual NFT from the stored token list and saves it in ignored NFTs list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Token identifier of the NFT.\n */\n private removeAndIgnoreIndividualNft(address: string, tokenId: string) {\n address = toChecksumHexAddress(address);\n const { allNfts, ignoredNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const newIgnoredNfts = [...ignoredNfts];\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const newNfts = nfts.filter((nft) => {\n if (\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId\n ) {\n const alreadyIgnored = newIgnoredNfts.find(\n (c) => c.address === address && c.tokenId === tokenId,\n );\n !alreadyIgnored && newIgnoredNfts.push(nft);\n return false;\n }\n return true;\n });\n\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY);\n\n this.update({\n ignoredNfts: newIgnoredNfts,\n });\n }\n\n /**\n * Removes an individual NFT from the stored token list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Token identifier of the NFT.\n */\n private removeIndividualNft(address: string, tokenId: string) {\n address = toChecksumHexAddress(address);\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const newNfts = nfts.filter(\n (nft) =>\n !(\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId\n ),\n );\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY);\n }\n\n /**\n * Removes an NFT contract to the stored NFT contracts list.\n *\n * @param address - Hex address of the NFT contract.\n * @returns Promise resolving to the current NFT contracts list.\n */\n private removeNftContract(address: string): NftContract[] {\n address = toChecksumHexAddress(address);\n const { allNftContracts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nftContracts = allNftContracts[selectedAddress]?.[chainId] || [];\n\n const newNftContracts = nftContracts.filter(\n (nftContract) =>\n !(nftContract.address.toLowerCase() === address.toLowerCase()),\n );\n this.updateNestedNftState(newNftContracts, ALL_NFTS_CONTRACTS_STATE_KEY);\n\n return newNftContracts;\n }\n\n /**\n * EventEmitter instance used to listen to specific EIP747 events\n */\n hub = new EventEmitter();\n\n /**\n * Optional API key to use with opensea\n */\n openSeaApiKey?: string;\n\n /**\n * Name of this controller used during composition\n */\n override name = 'NftController';\n\n private readonly getERC721AssetName: AssetsContractController['getERC721AssetName'];\n\n private readonly getERC721AssetSymbol: AssetsContractController['getERC721AssetSymbol'];\n\n private readonly getERC721TokenURI: AssetsContractController['getERC721TokenURI'];\n\n private readonly getERC721OwnerOf: AssetsContractController['getERC721OwnerOf'];\n\n private readonly getERC1155BalanceOf: AssetsContractController['getERC1155BalanceOf'];\n\n private readonly getERC1155TokenURI: AssetsContractController['getERC1155TokenURI'];\n\n private readonly onNftAdded?: (data: {\n address: string;\n symbol: string | undefined;\n tokenId: string;\n standard: string | null;\n source: Source;\n }) => void;\n\n /**\n * Creates an NftController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onPreferencesStateChange - Allows subscribing to preference controller state changes.\n * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.\n * @param options.getERC721AssetName - Gets the name of the asset at the given address.\n * @param options.getERC721AssetSymbol - Gets the symbol of the asset at the given address.\n * @param options.getERC721TokenURI - Gets the URI of the ERC721 token at the given address, with the given ID.\n * @param options.getERC721OwnerOf - Get the owner of a ERC-721 NFT.\n * @param options.getERC1155BalanceOf - Gets balance of a ERC-1155 NFT.\n * @param options.getERC1155TokenURI - Gets the URI of the ERC1155 token at the given address, with the given ID.\n * @param options.onNftAdded - Callback that is called when an NFT is added. Currently used pass data\n * for tracking the NFT added event.\n * @param options.messenger - The controller messenger.\n * @param config - Initial options used to configure this controller.\n * @param state - Initial state to set on this controller.\n */\n constructor(\n {\n chainId: initialChainId,\n onPreferencesStateChange,\n onNetworkStateChange,\n getERC721AssetName,\n getERC721AssetSymbol,\n getERC721TokenURI,\n getERC721OwnerOf,\n getERC1155BalanceOf,\n getERC1155TokenURI,\n onNftAdded,\n messenger,\n }: {\n chainId: Hex;\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n getERC721AssetName: AssetsContractController['getERC721AssetName'];\n getERC721AssetSymbol: AssetsContractController['getERC721AssetSymbol'];\n getERC721TokenURI: AssetsContractController['getERC721TokenURI'];\n getERC721OwnerOf: AssetsContractController['getERC721OwnerOf'];\n getERC1155BalanceOf: AssetsContractController['getERC1155BalanceOf'];\n getERC1155TokenURI: AssetsContractController['getERC1155TokenURI'];\n onNftAdded?: (data: {\n address: string;\n symbol: string | undefined;\n tokenId: string;\n standard: string | null;\n source: string;\n }) => void;\n messenger: NftControllerMessenger;\n },\n config?: Partial,\n state?: Partial,\n ) {\n super(config, state);\n this.defaultConfig = {\n selectedAddress: '',\n chainId: initialChainId,\n ipfsGateway: IPFS_DEFAULT_GATEWAY_URL,\n openSeaEnabled: false,\n useIPFSSubdomains: true,\n isIpfsGatewayEnabled: true,\n };\n\n this.defaultState = {\n allNftContracts: {},\n allNfts: {},\n ignoredNfts: [],\n };\n this.initialize();\n this.getERC721AssetName = getERC721AssetName;\n this.getERC721AssetSymbol = getERC721AssetSymbol;\n this.getERC721TokenURI = getERC721TokenURI;\n this.getERC721OwnerOf = getERC721OwnerOf;\n this.getERC1155BalanceOf = getERC1155BalanceOf;\n this.getERC1155TokenURI = getERC1155TokenURI;\n this.onNftAdded = onNftAdded;\n this.messagingSystem = messenger;\n\n onPreferencesStateChange(\n ({\n selectedAddress,\n ipfsGateway,\n openSeaEnabled,\n isIpfsGatewayEnabled,\n }) => {\n this.configure({\n selectedAddress,\n ipfsGateway,\n openSeaEnabled,\n isIpfsGatewayEnabled,\n });\n },\n );\n\n onNetworkStateChange(({ providerConfig }) => {\n const { chainId } = providerConfig;\n this.configure({ chainId });\n });\n }\n\n async validateWatchNft(\n asset: NftAsset,\n type: NFTStandardType,\n accountAddress: string,\n ) {\n const { address: contractAddress, tokenId } = asset;\n\n // Validate parameters\n if (!type) {\n throw rpcErrors.invalidParams('Asset type is required');\n }\n\n if (type !== ERC721 && type !== ERC1155) {\n throw rpcErrors.invalidParams(\n `Non NFT asset type ${type} not supported by watchNft`,\n );\n }\n\n if (!contractAddress || !tokenId) {\n throw rpcErrors.invalidParams('Both address and tokenId are required');\n }\n\n if (!isAddress(contractAddress)) {\n throw rpcErrors.invalidParams('Invalid address');\n }\n\n if (!/^\\d+$/u.test(tokenId)) {\n throw rpcErrors.invalidParams('Invalid tokenId');\n }\n\n // Check if the user owns the suggested NFT\n try {\n const isOwner = await this.isNftOwner(\n accountAddress,\n contractAddress,\n tokenId,\n );\n if (!isOwner) {\n throw rpcErrors.invalidInput(\n 'Suggested NFT is not owned by the selected account',\n );\n }\n } catch (error: any) {\n // error thrown here: \"Unable to verify ownership. Possibly because the standard is not supported or the user's currently selected network does not match the chain of the asset in question.\"\n throw rpcErrors.resourceUnavailable(error.message);\n }\n }\n\n /**\n * Adds a new suggestedAsset to state. Parameters will be validated according to\n * asset type being watched. A `:pending` hub event will be emitted once added.\n *\n * @param asset - The asset to be watched. For now ERC721 and ERC1155 tokens are accepted.\n * @param asset.address - The address of the asset contract.\n * @param asset.tokenId - The ID of the asset.\n * @param type - The asset type.\n * @param origin - Domain origin to register the asset from.\n * @returns Object containing a Promise resolving to the suggestedAsset address if accepted.\n */\n async watchNft(asset: NftAsset, type: NFTStandardType, origin: string) {\n const { selectedAddress, chainId } = this.config;\n\n await this.validateWatchNft(asset, type, selectedAddress);\n\n const nftMetadata = await this.getNftInformation(\n asset.address,\n asset.tokenId,\n );\n\n if (nftMetadata.standard && nftMetadata.standard !== type) {\n throw rpcErrors.invalidInput(\n `Suggested NFT of type ${nftMetadata.standard} does not match received type ${type}`,\n );\n }\n\n const suggestedNftMeta: SuggestedNftMeta = {\n asset: { ...asset, ...nftMetadata },\n type,\n id: random(),\n time: Date.now(),\n interactingAddress: selectedAddress,\n origin,\n };\n await this._requestApproval(suggestedNftMeta);\n const { address, tokenId } = asset;\n const { name, standard, description, image } = nftMetadata;\n\n await this.addNft(\n address,\n tokenId,\n {\n name: name ?? null,\n description: description ?? null,\n image: image ?? null,\n standard: standard ?? null,\n },\n {\n chainId,\n userAddress: selectedAddress,\n },\n Source.Dapp,\n );\n }\n\n /**\n * Sets an OpenSea API key to retrieve NFT information.\n *\n * @param openSeaApiKey - OpenSea API key.\n */\n setApiKey(openSeaApiKey: string) {\n this.openSeaApiKey = openSeaApiKey;\n }\n\n /**\n * Checks the ownership of a ERC-721 or ERC-1155 NFT for a given address.\n *\n * @param ownerAddress - User public address.\n * @param nftAddress - NFT contract address.\n * @param nftId - NFT token ID.\n * @returns Promise resolving the NFT ownership.\n */\n async isNftOwner(\n ownerAddress: string,\n nftAddress: string,\n nftId: string,\n ): Promise {\n // Checks the ownership for ERC-721.\n try {\n const owner = await this.getERC721OwnerOf(nftAddress, nftId);\n return ownerAddress.toLowerCase() === owner.toLowerCase();\n // eslint-disable-next-line no-empty\n } catch {\n // Ignore ERC-721 contract error\n }\n\n // Checks the ownership for ERC-1155.\n try {\n const balance = await this.getERC1155BalanceOf(\n ownerAddress,\n nftAddress,\n nftId,\n );\n return !balance.isZero();\n // eslint-disable-next-line no-empty\n } catch {\n // Ignore ERC-1155 contract error\n }\n\n throw new Error(\n `Unable to verify ownership. Possibly because the standard is not supported or the user's currently selected network does not match the chain of the asset in question.`,\n );\n }\n\n /**\n * Verifies currently selected address owns entered NFT address/tokenId combo and\n * adds the NFT and respective NFT contract to the stored NFT and NFT contracts lists.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n */\n async addNftVerifyOwnership(address: string, tokenId: string) {\n const { selectedAddress } = this.config;\n if (!(await this.isNftOwner(selectedAddress, address, tokenId))) {\n throw new Error('This NFT is not owned by the user');\n }\n await this.addNft(address, tokenId);\n }\n\n /**\n * Adds an NFT and respective NFT contract to the stored NFT and NFT contracts lists.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @param nftMetadata - NFT optional metadata.\n * @param accountParams - The chain ID and address of network and account to which the nftContract should be added.\n * @param source - Whether the NFT was detected, added manually or suggested by a dapp.\n * @returns Promise resolving to the current NFT list.\n */\n async addNft(\n address: string,\n tokenId: string,\n nftMetadata?: NftMetadata,\n accountParams?: AccountParams,\n source = Source.Custom,\n ) {\n address = toChecksumHexAddress(address);\n const newNftContracts = await this.addNftContract(\n address,\n accountParams,\n source,\n );\n nftMetadata =\n nftMetadata || (await this.getNftInformation(address, tokenId));\n\n // If NFT contract was not added, do not add individual NFT\n const nftContract = newNftContracts.find(\n (contract) => contract.address.toLowerCase() === address.toLowerCase(),\n );\n\n // If NFT contract information, add individual NFT\n if (nftContract) {\n await this.addIndividualNft(\n address,\n tokenId,\n nftMetadata,\n nftContract,\n accountParams,\n source,\n );\n }\n }\n\n /**\n * Removes an NFT from the stored token list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Token identifier of the NFT.\n */\n removeNft(address: string, tokenId: string) {\n address = toChecksumHexAddress(address);\n this.removeIndividualNft(address, tokenId);\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const remainingNft = nfts.find(\n (nft) => nft.address.toLowerCase() === address.toLowerCase(),\n );\n if (!remainingNft) {\n this.removeNftContract(address);\n }\n }\n\n /**\n * Removes an NFT from the stored token list and saves it in ignored NFTs list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Token identifier of the NFT.\n */\n removeAndIgnoreNft(address: string, tokenId: string) {\n address = toChecksumHexAddress(address);\n this.removeAndIgnoreIndividualNft(address, tokenId);\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const remainingNft = nfts.find(\n (nft) => nft.address.toLowerCase() === address.toLowerCase(),\n );\n if (!remainingNft) {\n this.removeNftContract(address);\n }\n }\n\n /**\n * Removes all NFTs from the ignored list.\n */\n clearIgnoredNfts() {\n this.update({ ignoredNfts: [] });\n }\n\n /**\n * Checks whether input NFT is still owned by the user\n * And updates the isCurrentlyOwned value on the NFT object accordingly.\n *\n * @param nft - The NFT object to check and update.\n * @param batch - A boolean indicating whether this method is being called as part of a batch or single update.\n * @param accountParams - The userAddress and chainId to check ownership against\n * @param accountParams.userAddress - the address passed through the confirmed transaction flow to ensure assets are stored to the correct account\n * @param accountParams.chainId - the chainId passed through the confirmed transaction flow to ensure assets are stored to the correct account\n * @returns the NFT with the updated isCurrentlyOwned value\n */\n async checkAndUpdateSingleNftOwnershipStatus(\n nft: Nft,\n batch: boolean,\n { userAddress, chainId } = {\n userAddress: this.config.selectedAddress,\n chainId: this.config.chainId,\n },\n ) {\n const { address, tokenId } = nft;\n let isOwned = nft.isCurrentlyOwned;\n try {\n isOwned = await this.isNftOwner(userAddress, address, tokenId);\n } catch (error) {\n if (\n !(\n error instanceof Error &&\n error.message.includes('Unable to verify ownership')\n )\n ) {\n throw error;\n }\n }\n\n nft.isCurrentlyOwned = isOwned;\n\n if (batch) {\n return nft;\n }\n\n // if this is not part of a batched update we update this one NFT in state\n const { allNfts } = this.state;\n const nfts = allNfts[userAddress]?.[chainId] || [];\n const nftToUpdate = nfts.find(\n (item) =>\n item.tokenId === tokenId &&\n item.address.toLowerCase() === address.toLowerCase(),\n );\n if (nftToUpdate) {\n nftToUpdate.isCurrentlyOwned = isOwned;\n this.updateNestedNftState(nfts, ALL_NFTS_STATE_KEY, {\n userAddress,\n chainId,\n });\n }\n return nft;\n }\n\n /**\n * Checks whether NFTs associated with current selectedAddress/chainId combination are still owned by the user\n * And updates the isCurrentlyOwned value on each accordingly.\n */\n async checkAndUpdateAllNftsOwnershipStatus() {\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const updatedNfts = await Promise.all(\n nfts.map(async (nft) => {\n return (\n (await this.checkAndUpdateSingleNftOwnershipStatus(nft, true)) ?? nft\n );\n }),\n );\n\n this.updateNestedNftState(updatedNfts, ALL_NFTS_STATE_KEY);\n }\n\n /**\n * Update NFT favorite status.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Hex address of the NFT contract.\n * @param favorite - NFT new favorite status.\n */\n updateNftFavoriteStatus(address: string, tokenId: string, favorite: boolean) {\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const index: number = nfts.findIndex(\n (nft) => nft.address === address && nft.tokenId === tokenId,\n );\n\n if (index === -1) {\n return;\n }\n\n const updatedNft: Nft = {\n ...nfts[index],\n favorite,\n };\n\n // Update Nfts array\n nfts[index] = updatedNft;\n\n this.updateNestedNftState(nfts, ALL_NFTS_STATE_KEY);\n }\n\n /**\n * Returns an NFT by the address and token id.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Number that represents the id of the token.\n * @param selectedAddress - Hex address of the user account.\n * @param chainId - Id of the current network.\n * @returns Object containing the NFT and its position in the array\n */\n findNftByAddressAndTokenId(\n address: string,\n tokenId: string,\n selectedAddress: string,\n chainId: Hex,\n ): { nft: Nft; index: number } | null {\n const { allNfts } = this.state;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const index: number = nfts.findIndex(\n (nft) =>\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId,\n );\n\n if (index === -1) {\n return null;\n }\n\n return { nft: nfts[index], index };\n }\n\n /**\n * Update NFT data.\n *\n * @param nft - NFT object to find the right NFT to updates.\n * @param updates - NFT partial object to update properties of the NFT.\n * @param selectedAddress - Hex address of the user account.\n * @param chainId - Id of the current network.\n */\n updateNft(\n nft: Nft,\n updates: Partial,\n selectedAddress: string,\n chainId: Hex,\n ) {\n const { allNfts } = this.state;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const nftInfo = this.findNftByAddressAndTokenId(\n nft.address,\n nft.tokenId,\n selectedAddress,\n chainId,\n );\n\n if (!nftInfo) {\n return;\n }\n\n const updatedNft: Nft = {\n ...nft,\n ...updates,\n };\n\n const newNfts = [\n ...nfts.slice(0, nftInfo.index),\n updatedNft,\n ...nfts.slice(nftInfo.index + 1),\n ];\n\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY);\n }\n\n /**\n * Resets the transaction status of an NFT.\n *\n * @param transactionId - NFT transaction id.\n * @param selectedAddress - Hex address of the user account.\n * @param chainId - Id of the current network.\n * @returns a boolean indicating if the reset was well succeded or not\n */\n resetNftTransactionStatusByTransactionId(\n transactionId: string,\n selectedAddress: string,\n chainId: Hex,\n ): boolean {\n const { allNfts } = this.state;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const index: number = nfts.findIndex(\n (nft) => nft.transactionId === transactionId,\n );\n\n if (index === -1) {\n return false;\n }\n const updatedNft: Nft = {\n ...nfts[index],\n transactionId: undefined,\n };\n\n const newNfts = [\n ...nfts.slice(0, index),\n updatedNft,\n ...nfts.slice(index + 1),\n ];\n\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY);\n return true;\n }\n\n async _requestApproval(suggestedNftMeta: SuggestedNftMeta) {\n return this.messagingSystem.call(\n 'ApprovalController:addRequest',\n {\n id: suggestedNftMeta.id,\n origin: suggestedNftMeta.origin,\n type: ApprovalType.WatchAsset,\n requestData: {\n id: suggestedNftMeta.id,\n interactingAddress: suggestedNftMeta.interactingAddress,\n asset: {\n address: suggestedNftMeta.asset.address,\n tokenId: suggestedNftMeta.asset.tokenId,\n name: suggestedNftMeta.asset.name,\n description: suggestedNftMeta.asset.description,\n image: suggestedNftMeta.asset.image,\n standard: suggestedNftMeta.asset.standard,\n },\n },\n },\n true,\n );\n }\n}\n\nexport default NftController;\n"]} \ No newline at end of file -+{"version":3,"file":"NftController.js","sourceRoot":"","sources":["../src/NftController.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from 'events';\nimport { BN, stripHexPrefix } from 'ethereumjs-util';\nimport { isAddress } from '@ethersproject/address';\nimport { Mutex } from 'async-mutex';\nimport type { Hex } from '@metamask/utils';\nimport { v4 as random } from 'uuid';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport {\n BaseController,\n BaseConfig,\n BaseState,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport type { NetworkState } from '@metamask/network-controller';\nimport { AddApprovalRequest } from '@metamask/approval-controller';\nimport {\n safelyExecute,\n handleFetch,\n toChecksumHexAddress,\n BNToHex,\n fetchWithErrorHandling,\n IPFS_DEFAULT_GATEWAY_URL,\n ERC721,\n ERC1155,\n OPENSEA_PROXY_URL,\n ApprovalType,\n} from '@metamask/controller-utils';\nimport type {\n ApiNftCreator,\n ApiNftContract,\n ApiNftLastSale,\n} from './NftDetectionController';\nimport type { AssetsContractController } from './AssetsContractController';\nimport {\n compareNftMetadata,\n getFormattedIpfsUrl,\n mapOpenSeaContractV2ToV1,\n mapOpenSeaDetailedNftV2ToV1,\n} from './assetsUtil';\nimport { Source } from './constants';\n\ntype NFTStandardType = 'ERC721' | 'ERC1155';\n\ntype SuggestedNftMeta = {\n asset: { address: string; tokenId: string } & NftMetadata;\n id: string;\n time: number;\n type: NFTStandardType;\n interactingAddress: string;\n origin: string;\n};\n\n/**\n * @type Nft\n *\n * NFT representation\n * @property address - Hex address of a ERC721 contract\n * @property description - The NFT description\n * @property image - URI of custom NFT image associated with this tokenId\n * @property name - Name associated with this tokenId and contract address\n * @property tokenId - The NFT identifier\n * @property numberOfSales - Number of sales\n * @property backgroundColor - The background color to be displayed with the item\n * @property imagePreview - URI of a smaller image associated with this NFT\n * @property imageThumbnail - URI of a thumbnail image associated with this NFT\n * @property imageOriginal - URI of the original image associated with this NFT\n * @property animation - URI of a animation associated with this NFT\n * @property animationOriginal - URI of the original animation associated with this NFT\n * @property externalLink - External link containing additional information\n * @property creator - The NFT owner information object\n * @property isCurrentlyOwned - Boolean indicating whether the address/chainId combination where it's currently stored currently owns this NFT\n * @property transactionId - Transaction Id associated with the NFT\n */\nexport interface Nft extends NftMetadata {\n tokenId: string;\n address: string;\n isCurrentlyOwned?: boolean;\n}\n\n/**\n * @type NftContract\n *\n * NFT contract information representation\n * @property name - Contract name\n * @property logo - Contract logo\n * @property address - Contract address\n * @property symbol - Contract symbol\n * @property description - Contract description\n * @property totalSupply - Total supply of NFTs\n * @property assetContractType - The NFT type, it could be `semi-fungible` or `non-fungible`\n * @property createdDate - Creation date\n * @property schemaName - The schema followed by the contract, it could be `ERC721` or `ERC1155`\n * @property externalLink - External link containing additional information\n */\nexport interface NftContract {\n name?: string;\n logo?: string;\n address: string;\n symbol?: string;\n description?: string;\n totalSupply?: string;\n assetContractType?: string;\n createdDate?: string;\n schemaName?: string;\n externalLink?: string;\n}\n\nexport enum OpenSeaV2ChainIds {\n ethereum = 'ethereum',\n}\n\nexport type OpenSeaV2GetNftResponse = { nft: OpenSeaV2DetailedNft };\n\nexport type OpenSeaV2Nft = {\n identifier: string;\n collection: string;\n contract: string;\n token_standard: string;\n name: string;\n description: string;\n image_url?: string;\n metadata_url?: string;\n updated_at: string;\n is_disabled: boolean;\n is_nsfw: boolean;\n};\n\nexport type OpenSeaV2DetailedNft = OpenSeaV2Nft & {\n animation_url?: string;\n is_suspicious: boolean;\n creator: string;\n traits: {\n trait_type: string;\n display_type?: string;\n max_value: string;\n trait_count?: number;\n value: number | string;\n }[];\n owners: {\n address: string;\n quantity: number;\n }[];\n rarity: { rank: number };\n};\n\nexport type OpenSeaV2ListNftsResponse = {\n nfts: OpenSeaV2Nft[];\n next?: string;\n};\n\nexport type OpenSeaV2Contract = {\n address: string;\n chain: string;\n collection: string;\n contract_standard: string;\n name: string;\n supply: number;\n};\n\nexport type OpenSeaV2Collection = {\n collection: string;\n name: string;\n description?: string;\n image_url?: string;\n owner: string;\n category: string;\n is_disabled: boolean;\n is_nsfw: boolean;\n trait_offers_enabled: boolean;\n opensea_url: string;\n project_url?: string;\n wiki_url?: string;\n discord_url?: string;\n telegram_url?: string;\n twitter_username?: string;\n instagram_username?: string;\n};\n\n/**\n * @type NftMetadata\n *\n * NFT custom information\n * @property name - NFT custom name\n * @property description - The NFT description\n * @property numberOfSales - Number of sales\n * @property backgroundColor - The background color to be displayed with the item\n * @property image - Image custom image URI\n * @property imagePreview - URI of a smaller image associated with this NFT\n * @property imageThumbnail - URI of a thumbnail image associated with this NFT\n * @property imageOriginal - URI of the original image associated with this NFT\n * @property animation - URI of a animation associated with this NFT\n * @property animationOriginal - URI of the original animation associated with this NFT\n * @property externalLink - External link containing additional information\n * @property creator - The NFT owner information object\n * @property standard - NFT standard name for the NFT, e.g., ERC-721 or ERC-1155\n */\nexport interface NftMetadata {\n name: string | null;\n description: string | null;\n image: string | null;\n standard: string | null;\n favorite?: boolean;\n numberOfSales?: number;\n backgroundColor?: string;\n imagePreview?: string;\n imageThumbnail?: string;\n imageOriginal?: string;\n animation?: string;\n animationOriginal?: string;\n externalLink?: string;\n creator?: ApiNftCreator;\n lastSale?: ApiNftLastSale;\n transactionId?: string;\n tokenURI?: string;\n error?: string;\n}\n\ninterface AccountParams {\n userAddress: string;\n chainId: Hex;\n}\n\n/**\n * @type NftConfig\n *\n * NFT controller configuration\n * @property selectedAddress - Vault selected address\n */\nexport interface NftConfig extends BaseConfig {\n selectedAddress: string;\n chainId: Hex;\n ipfsGateway: string;\n isIpfsGatewayEnabled: boolean;\n displayNftMedia: boolean;\n useIPFSSubdomains: boolean;\n}\n\n/**\n * @type NftState\n *\n * NFT controller state\n * @property allNftContracts - Object containing NFT contract information\n * @property allNfts - Object containing NFTs per account and network\n * @property ignoredNfts - List of NFTs that should be ignored\n */\nexport interface NftState extends BaseState {\n allNftContracts: {\n [key: string]: { [chainId: Hex]: NftContract[] };\n };\n allNfts: { [key: string]: { [chainId: Hex]: Nft[] } };\n ignoredNfts: Nft[];\n}\n\nconst ALL_NFTS_STATE_KEY = 'allNfts';\nconst ALL_NFTS_CONTRACTS_STATE_KEY = 'allNftContracts';\n\ninterface NftAsset {\n address: string;\n tokenId: string;\n}\n\n/**\n * The name of the {@link NftController}.\n */\nconst controllerName = 'NftController';\n\n/**\n * The external actions available to the {@link NftController}.\n */\ntype AllowedActions = AddApprovalRequest;\n\n/**\n * The messenger of the {@link NftController}.\n */\nexport type NftControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n AllowedActions,\n never,\n AllowedActions['type'],\n never\n>;\n\n/**\n * Controller that stores assets and exposes convenience methods\n */\nexport class NftController extends BaseController {\n private mutex = new Mutex();\n\n private messagingSystem: NftControllerMessenger;\n\n getNftApi({\n contractAddress,\n tokenId,\n }: {\n contractAddress: string;\n tokenId: string;\n }) {\n return `${OPENSEA_PROXY_URL}/chain/${OpenSeaV2ChainIds.ethereum}/contract/${contractAddress}/nfts/${tokenId}`;\n }\n\n private getNftContractInformationApi({\n contractAddress,\n }: {\n contractAddress: string;\n }) {\n return `${OPENSEA_PROXY_URL}/chain/${OpenSeaV2ChainIds.ethereum}/contract/${contractAddress}`;\n }\n\n private getNftCollectionInformationApi({\n collectionSlug,\n }: {\n collectionSlug: string;\n }) {\n return `${OPENSEA_PROXY_URL}/collections/${collectionSlug}`;\n }\n\n /**\n * Helper method to update nested state for allNfts and allNftContracts.\n *\n * @param newCollection - the modified piece of state to update in the controller's store\n * @param baseStateKey - The root key in the store to update.\n * @param passedConfig - An object containing the selectedAddress and chainId that are passed through the auto-detection flow.\n * @param passedConfig.userAddress - the address passed through the NFT detection flow to ensure assets are stored to the correct account\n * @param passedConfig.chainId - the chainId passed through the NFT detection flow to ensure assets are stored to the correct account\n */\n private updateNestedNftState(\n newCollection: Nft[] | NftContract[],\n baseStateKey: 'allNfts' | 'allNftContracts',\n { userAddress, chainId } = {\n userAddress: this.config.selectedAddress,\n chainId: this.config.chainId,\n },\n ) {\n const { [baseStateKey]: oldState } = this.state;\n\n const addressState = oldState[userAddress];\n const newAddressState = {\n ...addressState,\n ...{ [chainId]: newCollection },\n };\n const newState = {\n ...oldState,\n ...{ [userAddress]: newAddressState },\n };\n\n this.update({\n [baseStateKey]: newState,\n });\n }\n\n /**\n * Request individual NFT information from OpenSea API.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformationFromApi(\n contractAddress: string,\n tokenId: string,\n ): Promise {\n try {\n // Attempt to fetch the data with the proxy\n const nftInformation: { nft: OpenSeaV2DetailedNft } | undefined =\n await fetchWithErrorHandling({\n url: this.getNftApi({\n contractAddress,\n tokenId,\n }),\n });\n\n // if we were still unable to fetch the data we return out the default/null of `NftMetadata`\n if (!nftInformation?.nft) {\n return {\n name: null,\n description: null,\n image: null,\n standard: null,\n };\n }\n\n // if we've reached this point, we have successfully fetched some data for nftInformation\n // now we reconfigure the data to conform to the `NftMetadata` type for storage.\n const {\n num_sales,\n background_color,\n image_url,\n image_preview_url,\n image_thumbnail_url,\n image_original_url,\n animation_url,\n animation_original_url,\n name,\n description,\n external_link,\n creator,\n last_sale,\n asset_contract: { schema_name },\n } = mapOpenSeaDetailedNftV2ToV1(nftInformation.nft);\n\n /* istanbul ignore next */\n const nftMetadata: NftMetadata = Object.assign(\n {},\n { name: name || null },\n { description: description || null },\n { image: image_url || null },\n creator && { creator },\n num_sales && { numberOfSales: num_sales },\n background_color && { backgroundColor: background_color },\n image_preview_url && { imagePreview: image_preview_url },\n image_thumbnail_url && { imageThumbnail: image_thumbnail_url },\n image_original_url && { imageOriginal: image_original_url },\n animation_url && { animation: animation_url },\n animation_original_url && {\n animationOriginal: animation_original_url,\n },\n external_link && { externalLink: external_link },\n last_sale && { lastSale: last_sale },\n schema_name && { standard: schema_name },\n );\n\n return nftMetadata;\n } catch (error) {\n return {\n name: null,\n description: null,\n image: null,\n standard: null,\n error: 'Opensea import error',\n };\n }\n }\n\n /**\n * Request individual NFT information from contracts that follows Metadata Interface.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformationFromTokenURI(\n contractAddress: string,\n tokenId: string,\n ): Promise {\n const {\n ipfsGateway,\n useIPFSSubdomains,\n isIpfsGatewayEnabled,\n displayNftMedia,\n } = this.config;\n const result = await this.getNftURIAndStandard(contractAddress, tokenId);\n let tokenURI = result[0];\n const standard = result[1];\n\n if (!displayNftMedia && !isIpfsGatewayEnabled) {\n return {\n image: null,\n name: null,\n description: null,\n standard: standard || null,\n favorite: false,\n tokenURI,\n };\n }\n\n const hasIpfsTokenURI = tokenURI.startsWith('ipfs://');\n\n if (hasIpfsTokenURI && !isIpfsGatewayEnabled) {\n return {\n image: null,\n name: null,\n description: null,\n standard: standard || null,\n favorite: false,\n tokenURI: tokenURI ?? null,\n };\n }\n if (hasIpfsTokenURI) {\n tokenURI = getFormattedIpfsUrl(ipfsGateway, tokenURI, useIPFSSubdomains);\n }\n\n if (!hasIpfsTokenURI && !displayNftMedia) {\n return {\n image: null,\n name: null,\n description: null,\n standard: standard || null,\n favorite: false,\n tokenURI: tokenURI ?? null,\n };\n }\n\n try {\n const object = await handleFetch(tokenURI);\n // TODO: Check image_url existence. This is not part of EIP721 nor EIP1155\n const image = Object.prototype.hasOwnProperty.call(object, 'image')\n ? 'image'\n : /* istanbul ignore next */ 'image_url';\n\n return {\n image: object[image],\n name: object.name,\n description: object.description,\n standard,\n favorite: false,\n tokenURI: tokenURI ?? null,\n };\n } catch {\n return {\n image: null,\n name: null,\n description: null,\n standard: standard || null,\n favorite: false,\n tokenURI: tokenURI ?? null,\n error: 'URI import error',\n };\n }\n }\n\n /**\n * Retrieve NFT uri with metadata. TODO Update method to use IPFS.\n *\n * @param contractAddress - NFT contract address.\n * @param tokenId - NFT token id.\n * @returns Promise resolving NFT uri and token standard.\n */\n private async getNftURIAndStandard(\n contractAddress: string,\n tokenId: string,\n ): Promise<[string, string]> {\n // try ERC721 uri\n try {\n const uri = await this.getERC721TokenURI(contractAddress, tokenId);\n return [uri, ERC721];\n } catch {\n // Ignore error\n }\n\n // try ERC1155 uri\n try {\n const tokenURI = await this.getERC1155TokenURI(contractAddress, tokenId);\n\n /**\n * According to EIP1155 the URI value allows for ID substitution\n * in case the string `{id}` exists.\n * https://eips.ethereum.org/EIPS/eip-1155#metadata\n */\n\n if (!tokenURI.includes('{id}')) {\n return [tokenURI, ERC1155];\n }\n\n const hexTokenId = stripHexPrefix(BNToHex(new BN(tokenId)))\n .padStart(64, '0')\n .toLowerCase();\n return [tokenURI.replace('{id}', hexTokenId), ERC1155];\n } catch {\n // Ignore error\n }\n\n return ['', ''];\n }\n\n /**\n * Request individual NFT information (name, image url and description).\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformation(\n contractAddress: string,\n tokenId: string,\n ): Promise {\n const blockchainMetadata = await safelyExecute(async () => {\n return await this.getNftInformationFromTokenURI(contractAddress, tokenId);\n });\n\n let openSeaMetadata;\n if (this.config.displayNftMedia) {\n openSeaMetadata = await safelyExecute(async () => {\n return await this.getNftInformationFromApi(contractAddress, tokenId);\n });\n }\n\n if (blockchainMetadata.error && openSeaMetadata?.error) {\n return {\n image: null,\n name: null,\n description: null,\n standard: blockchainMetadata.standard ?? null,\n favorite: false,\n tokenURI: blockchainMetadata.tokenURI ?? null,\n error: 'Both import failed',\n };\n }\n\n return {\n ...openSeaMetadata,\n tokenURI:\n blockchainMetadata.tokenURI ?? openSeaMetadata?.tokenURI ?? null,\n name: blockchainMetadata.name ?? openSeaMetadata?.name ?? null,\n description:\n blockchainMetadata.description ?? openSeaMetadata?.description ?? null,\n image: blockchainMetadata.image ?? openSeaMetadata?.image ?? null,\n standard:\n blockchainMetadata.standard ?? openSeaMetadata?.standard ?? null,\n };\n }\n\n /**\n * Request NFT contract information from OpenSea API.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftContractInformationFromApi(\n contractAddress: string,\n ): Promise {\n /* istanbul ignore if */\n const apiNftContractObject: OpenSeaV2Contract | undefined =\n await fetchWithErrorHandling({\n url: this.getNftContractInformationApi({\n contractAddress,\n }),\n });\n\n // if we successfully fetched return the fetched data immediately\n if (apiNftContractObject) {\n // If we successfully fetched the contract\n if (apiNftContractObject) {\n // Then fetch some additional details from the collection\n const collection: OpenSeaV2Collection | undefined =\n await fetchWithErrorHandling({\n url: this.getNftCollectionInformationApi({\n collectionSlug: apiNftContractObject.collection,\n }),\n });\n\n return mapOpenSeaContractV2ToV1(apiNftContractObject, collection);\n }\n }\n\n // If we've reached this point we were unable to fetch data from either the proxy or opensea so we return\n // the default/null of ApiNftContract\n return {\n address: contractAddress,\n asset_contract_type: null,\n created_date: null,\n schema_name: null,\n symbol: null,\n total_supply: null,\n description: null,\n external_link: null,\n collection: {\n name: null,\n image_url: null,\n },\n };\n }\n\n /**\n * Request NFT contract information from the contract itself.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftContractInformationFromContract(\n contractAddress: string,\n ): Promise<\n Partial &\n Pick &\n Pick\n > {\n const name = await this.getERC721AssetName(contractAddress);\n const symbol = await this.getERC721AssetSymbol(contractAddress);\n return {\n collection: { name },\n symbol,\n address: contractAddress,\n };\n }\n\n /**\n * Request NFT contract information from OpenSea API.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @returns Promise resolving to the NFT contract name, image and description.\n */\n private async getNftContractInformation(\n contractAddress: string,\n ): Promise<\n Partial &\n Pick &\n Pick\n > {\n const blockchainContractData: Partial &\n Pick &\n Pick = await safelyExecute(async () => {\n return await this.getNftContractInformationFromContract(contractAddress);\n });\n\n let openSeaContractData: Partial | undefined;\n if (this.config.displayNftMedia) {\n openSeaContractData = await safelyExecute(async () => {\n return await this.getNftContractInformationFromApi(contractAddress);\n });\n }\n\n if (blockchainContractData || openSeaContractData) {\n return {\n ...openSeaContractData,\n ...blockchainContractData,\n collection: {\n image_url: null,\n ...openSeaContractData?.collection,\n ...blockchainContractData?.collection,\n },\n };\n }\n\n /* istanbul ignore next */\n return {\n address: contractAddress,\n asset_contract_type: null,\n created_date: null,\n schema_name: null,\n symbol: null,\n total_supply: null,\n description: null,\n external_link: null,\n collection: { name: null, image_url: null },\n };\n }\n\n /**\n * Adds an individual NFT to the stored NFT list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @param nftMetadata - NFT optional information (name, image and description).\n * @param nftContract - An object containing contract data of the NFT being added.\n * @param accountParams - The chain ID and address of network and account to which the nftContract should be added.\n * @param source - Whether the NFT was detected, added manually or suggested by a dapp.\n * @returns Promise resolving to the current NFT list.\n */\n private async addIndividualNft(\n address: string,\n tokenId: string,\n nftMetadata: NftMetadata,\n nftContract: NftContract,\n accountParams?: AccountParams,\n source = Source.Custom,\n ): Promise {\n // TODO: Remove unused return\n const releaseLock = await this.mutex.acquire();\n try {\n address = toChecksumHexAddress(address);\n const { allNfts } = this.state;\n let chainId, selectedAddress;\n if (accountParams) {\n chainId = accountParams.chainId;\n selectedAddress = accountParams.userAddress;\n } else {\n chainId = this.config.chainId;\n selectedAddress = this.config.selectedAddress;\n }\n\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n\n const existingEntry: Nft | undefined = nfts.find(\n (nft) =>\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId,\n );\n\n if (existingEntry) {\n const differentMetadata = compareNftMetadata(\n nftMetadata,\n existingEntry,\n );\n if (differentMetadata || !existingEntry.isCurrentlyOwned) {\n // TODO: Switch to indexToUpdate\n const indexToRemove = nfts.findIndex(\n (nft) =>\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId,\n );\n /* istanbul ignore next */\n if (indexToRemove !== -1) {\n nfts.splice(indexToRemove, 1);\n }\n } else {\n return nfts;\n }\n }\n\n const newEntry: Nft = {\n address,\n tokenId,\n favorite: existingEntry?.favorite || false,\n isCurrentlyOwned: true,\n ...nftMetadata,\n };\n\n const newNfts = [...nfts, newEntry];\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY, {\n chainId,\n userAddress: selectedAddress,\n });\n\n if (this.onNftAdded) {\n this.onNftAdded({\n address,\n symbol: nftContract.symbol,\n tokenId: tokenId.toString(),\n standard: nftMetadata.standard,\n source,\n tokenURI: nftMetadata.tokenURI,\n });\n }\n\n return newNfts;\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Adds an NFT contract to the stored NFT contracts list.\n *\n * @param address - Hex address of the NFT contract.\n * @param accountParams - The chain ID and address of network and account to which the nftContract should be added.\n * @param source - Whether the NFT was detected, added manually or suggested by a dapp.\n * @returns Promise resolving to the current NFT contracts list.\n */\n private async addNftContract(\n address: string,\n accountParams?: AccountParams,\n source?: Source,\n ): Promise {\n const releaseLock = await this.mutex.acquire();\n try {\n address = toChecksumHexAddress(address);\n const { allNftContracts } = this.state;\n let chainId, selectedAddress;\n if (accountParams) {\n chainId = accountParams.chainId;\n selectedAddress = accountParams.userAddress;\n } else {\n chainId = this.config.chainId;\n selectedAddress = this.config.selectedAddress;\n }\n\n const nftContracts = allNftContracts[selectedAddress]?.[chainId] || [];\n\n const existingEntry = nftContracts.find(\n (nftContract) =>\n nftContract.address.toLowerCase() === address.toLowerCase(),\n );\n if (existingEntry) {\n return nftContracts;\n }\n const contractInformation = await this.getNftContractInformation(address);\n const {\n asset_contract_type,\n created_date,\n schema_name,\n symbol,\n total_supply,\n description,\n external_link,\n collection: { name, image_url },\n } = contractInformation;\n\n // If the nft is auto-detected we want some valid metadata to be present\n if (\n source === Source.Detected &&\n Object.entries(contractInformation).every(([k, v]: [string, any]) => {\n if (k === 'address') {\n return true; // address will always be present\n }\n // collection will always be an object, we need to check the internal values\n if (k === 'collection') {\n return v?.name === null && v?.image_url === null;\n }\n return Boolean(v) === false;\n })\n ) {\n return nftContracts;\n }\n\n /* istanbul ignore next */\n const newEntry: NftContract = Object.assign(\n {},\n { address },\n description && { description },\n name && { name },\n image_url && { logo: image_url },\n symbol && { symbol },\n total_supply !== null &&\n typeof total_supply !== 'undefined' && { totalSupply: total_supply },\n asset_contract_type && { assetContractType: asset_contract_type },\n created_date && { createdDate: created_date },\n schema_name && { schemaName: schema_name },\n external_link && { externalLink: external_link },\n );\n const newNftContracts = [...nftContracts, newEntry];\n this.updateNestedNftState(newNftContracts, ALL_NFTS_CONTRACTS_STATE_KEY, {\n chainId,\n userAddress: selectedAddress,\n });\n\n return newNftContracts;\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Removes an individual NFT from the stored token list and saves it in ignored NFTs list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Token identifier of the NFT.\n */\n private removeAndIgnoreIndividualNft(address: string, tokenId: string) {\n address = toChecksumHexAddress(address);\n const { allNfts, ignoredNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const newIgnoredNfts = [...ignoredNfts];\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const newNfts = nfts.filter((nft) => {\n if (\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId\n ) {\n const alreadyIgnored = newIgnoredNfts.find(\n (c) => c.address === address && c.tokenId === tokenId,\n );\n !alreadyIgnored && newIgnoredNfts.push(nft);\n return false;\n }\n return true;\n });\n\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY);\n\n this.update({\n ignoredNfts: newIgnoredNfts,\n });\n }\n\n /**\n * Removes an individual NFT from the stored token list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Token identifier of the NFT.\n */\n private removeIndividualNft(address: string, tokenId: string) {\n address = toChecksumHexAddress(address);\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const newNfts = nfts.filter(\n (nft) =>\n !(\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId\n ),\n );\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY);\n }\n\n /**\n * Removes an NFT contract to the stored NFT contracts list.\n *\n * @param address - Hex address of the NFT contract.\n * @returns Promise resolving to the current NFT contracts list.\n */\n private removeNftContract(address: string): NftContract[] {\n address = toChecksumHexAddress(address);\n const { allNftContracts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nftContracts = allNftContracts[selectedAddress]?.[chainId] || [];\n\n const newNftContracts = nftContracts.filter(\n (nftContract) =>\n !(nftContract.address.toLowerCase() === address.toLowerCase()),\n );\n this.updateNestedNftState(newNftContracts, ALL_NFTS_CONTRACTS_STATE_KEY);\n\n return newNftContracts;\n }\n\n /**\n * EventEmitter instance used to listen to specific EIP747 events\n */\n hub = new EventEmitter();\n\n /**\n * Optional API key to use with opensea\n */\n openSeaApiKey?: string;\n\n /**\n * Name of this controller used during composition\n */\n override name = 'NftController';\n\n private getERC721AssetName: AssetsContractController['getERC721AssetName'];\n\n private getERC721AssetSymbol: AssetsContractController['getERC721AssetSymbol'];\n\n private getERC721TokenURI: AssetsContractController['getERC721TokenURI'];\n\n private getERC721OwnerOf: AssetsContractController['getERC721OwnerOf'];\n\n private getERC1155BalanceOf: AssetsContractController['getERC1155BalanceOf'];\n\n private getERC1155TokenURI: AssetsContractController['getERC1155TokenURI'];\n\n private onNftAdded?: (data: {\n address: string;\n symbol: string | undefined;\n tokenId: string;\n standard: string | null;\n source: string;\n tokenURI?: string;\n }) => void;\n\n /**\n * Creates an NftController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onPreferencesStateChange - Allows subscribing to preference controller state changes.\n * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.\n * @param options.getERC721AssetName - Gets the name of the asset at the given address.\n * @param options.getERC721AssetSymbol - Gets the symbol of the asset at the given address.\n * @param options.getERC721TokenURI - Gets the URI of the ERC721 token at the given address, with the given ID.\n * @param options.getERC721OwnerOf - Get the owner of a ERC-721 NFT.\n * @param options.getERC1155BalanceOf - Gets balance of a ERC-1155 NFT.\n * @param options.getERC1155TokenURI - Gets the URI of the ERC1155 token at the given address, with the given ID.\n * @param options.onNftAdded - Callback that is called when an NFT is added. Currently used pass data\n * for tracking the NFT added event.\n * @param options.messenger - The controller messenger.\n * @param config - Initial options used to configure this controller.\n * @param state - Initial state to set on this controller.\n */\n constructor(\n {\n chainId: initialChainId,\n onPreferencesStateChange,\n onNetworkStateChange,\n getERC721AssetName,\n getERC721AssetSymbol,\n getERC721TokenURI,\n getERC721OwnerOf,\n getERC1155BalanceOf,\n getERC1155TokenURI,\n onNftAdded,\n messenger,\n }: {\n chainId: Hex;\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n getERC721AssetName: AssetsContractController['getERC721AssetName'];\n getERC721AssetSymbol: AssetsContractController['getERC721AssetSymbol'];\n getERC721TokenURI: AssetsContractController['getERC721TokenURI'];\n getERC721OwnerOf: AssetsContractController['getERC721OwnerOf'];\n getERC1155BalanceOf: AssetsContractController['getERC1155BalanceOf'];\n getERC1155TokenURI: AssetsContractController['getERC1155TokenURI'];\n onNftAdded?: (data: {\n address: string;\n symbol: string | undefined;\n tokenId: string;\n standard: string | null;\n source: string;\n }) => void;\n messenger: NftControllerMessenger;\n },\n config?: Partial,\n state?: Partial,\n ) {\n super(config, state);\n this.defaultConfig = {\n selectedAddress: '',\n chainId: initialChainId,\n ipfsGateway: IPFS_DEFAULT_GATEWAY_URL,\n displayNftMedia: true,\n useIPFSSubdomains: true,\n isIpfsGatewayEnabled: true,\n };\n\n this.defaultState = {\n allNftContracts: {},\n allNfts: {},\n ignoredNfts: [],\n };\n this.initialize();\n this.getERC721AssetName = getERC721AssetName;\n this.getERC721AssetSymbol = getERC721AssetSymbol;\n this.getERC721TokenURI = getERC721TokenURI;\n this.getERC721OwnerOf = getERC721OwnerOf;\n this.getERC1155BalanceOf = getERC1155BalanceOf;\n this.getERC1155TokenURI = getERC1155TokenURI;\n this.onNftAdded = onNftAdded;\n this.messagingSystem = messenger;\n\n onPreferencesStateChange(\n ({\n selectedAddress,\n ipfsGateway,\n displayNftMedia,\n isIpfsGatewayEnabled,\n }) => {\n this.configure({\n selectedAddress,\n ipfsGateway,\n displayNftMedia,\n isIpfsGatewayEnabled,\n });\n },\n );\n\n onNetworkStateChange(({ providerConfig }) => {\n const { chainId } = providerConfig;\n this.configure({ chainId });\n });\n }\n\n async validateWatchNft(\n asset: NftAsset,\n type: NFTStandardType,\n accountAddress: string,\n ) {\n const { address: contractAddress, tokenId } = asset;\n\n // Validate parameters\n if (!type) {\n throw rpcErrors.invalidParams('Asset type is required');\n }\n\n if (type !== ERC721 && type !== ERC1155) {\n throw rpcErrors.invalidParams(\n `Non NFT asset type ${type} not supported by watchNft`,\n );\n }\n\n if (!contractAddress || !tokenId) {\n throw rpcErrors.invalidParams('Both address and tokenId are required');\n }\n\n if (!isAddress(contractAddress)) {\n throw rpcErrors.invalidParams('Invalid address');\n }\n\n if (!/^\\d+$/u.test(tokenId)) {\n throw rpcErrors.invalidParams('Invalid tokenId');\n }\n\n // Check if the user owns the suggested NFT\n try {\n const isOwner = await this.isNftOwner(\n accountAddress,\n contractAddress,\n tokenId,\n );\n if (!isOwner) {\n throw rpcErrors.invalidInput(\n 'Suggested NFT is not owned by the selected account',\n );\n }\n } catch (error: any) {\n // error thrown here: \"Unable to verify ownership. Possibly because the standard is not supported or the user's currently selected network does not match the chain of the asset in question.\"\n throw rpcErrors.resourceUnavailable(error.message);\n }\n }\n\n /**\n * Adds a new suggestedAsset to state. Parameters will be validated according to\n * asset type being watched. A `:pending` hub event will be emitted once added.\n *\n * @param asset - The asset to be watched. For now ERC721 and ERC1155 tokens are accepted.\n * @param asset.address - The address of the asset contract.\n * @param asset.tokenId - The ID of the asset.\n * @param type - The asset type.\n * @param origin - Domain origin to register the asset from.\n * @returns Object containing a Promise resolving to the suggestedAsset address if accepted.\n */\n async watchNft(asset: NftAsset, type: NFTStandardType, origin: string) {\n const { selectedAddress, chainId } = this.config;\n\n await this.validateWatchNft(asset, type, selectedAddress);\n\n const nftMetadata = await this.getNftInformation(\n asset.address,\n asset.tokenId,\n );\n\n if (nftMetadata.standard && nftMetadata.standard !== type) {\n throw rpcErrors.invalidInput(\n `Suggested NFT of type ${nftMetadata.standard} does not match received type ${type}`,\n );\n }\n\n const suggestedNftMeta: SuggestedNftMeta = {\n asset: { ...asset, ...nftMetadata },\n type,\n id: random(),\n time: Date.now(),\n interactingAddress: selectedAddress,\n origin,\n };\n await this._requestApproval(suggestedNftMeta);\n const { address, tokenId } = asset;\n const { name, standard, description, image } = nftMetadata;\n\n await this.addNft(\n address,\n tokenId,\n {\n name: name ?? null,\n description: description ?? null,\n image: image ?? null,\n standard: standard ?? null,\n },\n {\n chainId,\n userAddress: selectedAddress,\n },\n Source.Dapp,\n );\n }\n\n /**\n * Sets an OpenSea API key to retrieve NFT information.\n *\n * @param openSeaApiKey - OpenSea API key.\n */\n setApiKey(openSeaApiKey: string) {\n this.openSeaApiKey = openSeaApiKey;\n }\n\n /**\n * Checks the ownership of a ERC-721 or ERC-1155 NFT for a given address.\n *\n * @param ownerAddress - User public address.\n * @param nftAddress - NFT contract address.\n * @param nftId - NFT token ID.\n * @returns Promise resolving the NFT ownership.\n */\n async isNftOwner(\n ownerAddress: string,\n nftAddress: string,\n nftId: string,\n ): Promise {\n // Checks the ownership for ERC-721.\n try {\n const owner = await this.getERC721OwnerOf(nftAddress, nftId);\n return ownerAddress.toLowerCase() === owner.toLowerCase();\n // eslint-disable-next-line no-empty\n } catch {\n // Ignore ERC-721 contract error\n }\n\n // Checks the ownership for ERC-1155.\n try {\n const balance = await this.getERC1155BalanceOf(\n ownerAddress,\n nftAddress,\n nftId,\n );\n return !balance.isZero();\n // eslint-disable-next-line no-empty\n } catch {\n // Ignore ERC-1155 contract error\n }\n\n throw new Error(\n `Unable to verify ownership. Possibly because the standard is not supported or the user's currently selected network does not match the chain of the asset in question.`,\n );\n }\n\n /**\n * Verifies currently selected address owns entered NFT address/tokenId combo and\n * adds the NFT and respective NFT contract to the stored NFT and NFT contracts lists.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n */\n async addNftVerifyOwnership(address: string, tokenId: string) {\n const { selectedAddress } = this.config;\n if (!(await this.isNftOwner(selectedAddress, address, tokenId))) {\n throw new Error('This NFT is not owned by the user');\n }\n await this.addNft(address, tokenId);\n }\n\n /**\n * Adds an NFT and respective NFT contract to the stored NFT and NFT contracts lists.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @param nftMetadata - NFT optional metadata.\n * @param accountParams - The chain ID and address of network and account to which the nftContract should be added.\n * @param source - Whether the NFT was detected, added manually or suggested by a dapp.\n * @returns Promise resolving to the current NFT list.\n */\n async addNft(\n address: string,\n tokenId: string,\n nftMetadata?: NftMetadata,\n accountParams?: AccountParams,\n source = Source.Custom,\n ) {\n address = toChecksumHexAddress(address);\n const newNftContracts = await this.addNftContract(\n address,\n accountParams,\n source,\n );\n nftMetadata =\n nftMetadata || (await this.getNftInformation(address, tokenId));\n\n // If NFT contract was not added, do not add individual NFT\n const nftContract = newNftContracts.find(\n (contract) => contract.address.toLowerCase() === address.toLowerCase(),\n );\n\n // If NFT contract information, add individual NFT\n if (nftContract) {\n await this.addIndividualNft(\n address,\n tokenId,\n nftMetadata,\n nftContract,\n accountParams,\n source,\n );\n }\n }\n\n /**\n * Removes an NFT from the stored token list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Token identifier of the NFT.\n */\n removeNft(address: string, tokenId: string) {\n address = toChecksumHexAddress(address);\n this.removeIndividualNft(address, tokenId);\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const remainingNft = nfts.find(\n (nft) => nft.address.toLowerCase() === address.toLowerCase(),\n );\n if (!remainingNft) {\n this.removeNftContract(address);\n }\n }\n\n /**\n * Removes an NFT from the stored token list and saves it in ignored NFTs list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Token identifier of the NFT.\n */\n removeAndIgnoreNft(address: string, tokenId: string) {\n address = toChecksumHexAddress(address);\n this.removeAndIgnoreIndividualNft(address, tokenId);\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const remainingNft = nfts.find(\n (nft) => nft.address.toLowerCase() === address.toLowerCase(),\n );\n if (!remainingNft) {\n this.removeNftContract(address);\n }\n }\n\n /**\n * Removes all NFTs from the ignored list.\n */\n clearIgnoredNfts() {\n this.update({ ignoredNfts: [] });\n }\n\n /**\n * Checks whether input NFT is still owned by the user\n * And updates the isCurrentlyOwned value on the NFT object accordingly.\n *\n * @param nft - The NFT object to check and update.\n * @param batch - A boolean indicating whether this method is being called as part of a batch or single update.\n * @param accountParams - The userAddress and chainId to check ownership against\n * @param accountParams.userAddress - the address passed through the confirmed transaction flow to ensure assets are stored to the correct account\n * @param accountParams.chainId - the chainId passed through the confirmed transaction flow to ensure assets are stored to the correct account\n * @returns the NFT with the updated isCurrentlyOwned value\n */\n async checkAndUpdateSingleNftOwnershipStatus(\n nft: Nft,\n batch: boolean,\n { userAddress, chainId } = {\n userAddress: this.config.selectedAddress,\n chainId: this.config.chainId,\n },\n ) {\n const { address, tokenId } = nft;\n let isOwned = nft.isCurrentlyOwned;\n try {\n isOwned = await this.isNftOwner(userAddress, address, tokenId);\n } catch (error) {\n if (\n !(\n error instanceof Error &&\n error.message.includes('Unable to verify ownership')\n )\n ) {\n throw error;\n }\n }\n\n nft.isCurrentlyOwned = isOwned;\n\n if (batch === true) {\n return nft;\n }\n\n // if this is not part of a batched update we update this one NFT in state\n const { allNfts } = this.state;\n const nfts = allNfts[userAddress]?.[chainId] || [];\n const nftToUpdate = nfts.find(\n (item) =>\n item.tokenId === tokenId &&\n item.address.toLowerCase() === address.toLowerCase(),\n );\n if (nftToUpdate) {\n nftToUpdate.isCurrentlyOwned = isOwned;\n this.updateNestedNftState(nfts, ALL_NFTS_STATE_KEY, {\n userAddress,\n chainId,\n });\n }\n return nft;\n }\n\n /**\n * Checks whether NFTs associated with current selectedAddress/chainId combination are still owned by the user\n * And updates the isCurrentlyOwned value on each accordingly.\n */\n async checkAndUpdateAllNftsOwnershipStatus() {\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const updatedNfts = await Promise.all(\n nfts.map(async (nft) => {\n return (\n (await this.checkAndUpdateSingleNftOwnershipStatus(nft, true)) ?? nft\n );\n }),\n );\n\n this.updateNestedNftState(updatedNfts, ALL_NFTS_STATE_KEY);\n }\n\n /**\n * Update NFT favorite status.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Hex address of the NFT contract.\n * @param favorite - NFT new favorite status.\n */\n updateNftFavoriteStatus(address: string, tokenId: string, favorite: boolean) {\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const index: number = nfts.findIndex(\n (nft) => nft.address === address && nft.tokenId === tokenId,\n );\n\n if (index === -1) {\n return;\n }\n\n const updatedNft: Nft = {\n ...nfts[index],\n favorite,\n };\n\n // Update Nfts array\n nfts[index] = updatedNft;\n\n this.updateNestedNftState(nfts, ALL_NFTS_STATE_KEY);\n }\n\n /**\n * Returns an NFT by the address and token id.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Number that represents the id of the token.\n * @param selectedAddress - Hex address of the user account.\n * @param chainId - Id of the current network.\n * @returns Object containing the NFT and its position in the array\n */\n findNftByAddressAndTokenId(\n address: string,\n tokenId: string,\n selectedAddress: string,\n chainId: Hex,\n ): { nft: Nft; index: number } | null {\n const { allNfts } = this.state;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const index: number = nfts.findIndex(\n (nft) =>\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId,\n );\n\n if (index === -1) {\n return null;\n }\n\n return { nft: nfts[index], index };\n }\n\n /**\n * Update NFT data.\n *\n * @param nft - NFT object to find the right NFT to updates.\n * @param updates - NFT partial object to update properties of the NFT.\n * @param selectedAddress - Hex address of the user account.\n * @param chainId - Id of the current network.\n */\n updateNft(\n nft: Nft,\n updates: Partial,\n selectedAddress: string,\n chainId: Hex,\n ) {\n const { allNfts } = this.state;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const nftInfo = this.findNftByAddressAndTokenId(\n nft.address,\n nft.tokenId,\n selectedAddress,\n chainId,\n );\n\n if (!nftInfo) {\n return;\n }\n\n const updatedNft: Nft = {\n ...nft,\n ...updates,\n };\n\n const newNfts = [\n ...nfts.slice(0, nftInfo.index),\n updatedNft,\n ...nfts.slice(nftInfo.index + 1),\n ];\n\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY);\n }\n\n /**\n * Resets the transaction status of an NFT.\n *\n * @param transactionId - NFT transaction id.\n * @param selectedAddress - Hex address of the user account.\n * @param chainId - Id of the current network.\n * @returns a boolean indicating if the reset was well succeded or not\n */\n resetNftTransactionStatusByTransactionId(\n transactionId: string,\n selectedAddress: string,\n chainId: Hex,\n ): boolean {\n const { allNfts } = this.state;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const index: number = nfts.findIndex(\n (nft) => nft.transactionId === transactionId,\n );\n\n if (index === -1) {\n return false;\n }\n const updatedNft: Nft = {\n ...nfts[index],\n transactionId: undefined,\n };\n\n const newNfts = [\n ...nfts.slice(0, index),\n updatedNft,\n ...nfts.slice(index + 1),\n ];\n\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY);\n return true;\n }\n\n async _requestApproval(suggestedNftMeta: SuggestedNftMeta) {\n return this.messagingSystem.call(\n 'ApprovalController:addRequest',\n {\n id: suggestedNftMeta.id,\n origin: suggestedNftMeta.origin,\n type: ApprovalType.WatchAsset,\n requestData: {\n id: suggestedNftMeta.id,\n interactingAddress: suggestedNftMeta.interactingAddress,\n asset: {\n address: suggestedNftMeta.asset.address,\n tokenId: suggestedNftMeta.asset.tokenId,\n name: suggestedNftMeta.asset.name,\n description: suggestedNftMeta.asset.description,\n image: suggestedNftMeta.asset.image,\n standard: suggestedNftMeta.asset.standard,\n },\n },\n },\n true,\n );\n }\n}\n\nexport default NftController;\n"]} ++{"version":3,"file":"NftController.js","sourceRoot":"","sources":["../src/NftController.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from 'events';\nimport { BN, stripHexPrefix } from 'ethereumjs-util';\nimport { isAddress } from '@ethersproject/address';\nimport { Mutex } from 'async-mutex';\nimport type { Hex } from '@metamask/utils';\nimport { v4 as random } from 'uuid';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport {\n BaseController,\n BaseConfig,\n BaseState,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport type { NetworkState } from '@metamask/network-controller';\nimport { AddApprovalRequest } from '@metamask/approval-controller';\nimport {\n safelyExecute,\n handleFetch,\n toChecksumHexAddress,\n BNToHex,\n fetchWithErrorHandling,\n IPFS_DEFAULT_GATEWAY_URL,\n ERC721,\n ERC1155,\n OPENSEA_PROXY_URL,\n ApprovalType,\n} from '@metamask/controller-utils';\nimport type {\n ApiNftCreator,\n ApiNftContract,\n ApiNftLastSale,\n} from './NftDetectionController';\nimport type { AssetsContractController } from './AssetsContractController';\nimport {\n compareNftMetadata,\n getFormattedIpfsUrl,\n mapOpenSeaContractV2ToV1,\n mapOpenSeaDetailedNftV2ToV1,\n} from './assetsUtil';\nimport { Source } from './constants';\n\ntype NFTStandardType = 'ERC721' | 'ERC1155';\n\ntype SuggestedNftMeta = {\n asset: { address: string; tokenId: string } & NftMetadata;\n id: string;\n time: number;\n type: NFTStandardType;\n interactingAddress: string;\n origin: string;\n};\n\n/**\n * @type Nft\n *\n * NFT representation\n * @property address - Hex address of a ERC721 contract\n * @property description - The NFT description\n * @property image - URI of custom NFT image associated with this tokenId\n * @property name - Name associated with this tokenId and contract address\n * @property tokenId - The NFT identifier\n * @property numberOfSales - Number of sales\n * @property backgroundColor - The background color to be displayed with the item\n * @property imagePreview - URI of a smaller image associated with this NFT\n * @property imageThumbnail - URI of a thumbnail image associated with this NFT\n * @property imageOriginal - URI of the original image associated with this NFT\n * @property animation - URI of a animation associated with this NFT\n * @property animationOriginal - URI of the original animation associated with this NFT\n * @property externalLink - External link containing additional information\n * @property creator - The NFT owner information object\n * @property isCurrentlyOwned - Boolean indicating whether the address/chainId combination where it's currently stored currently owns this NFT\n * @property transactionId - Transaction Id associated with the NFT\n */\nexport interface Nft extends NftMetadata {\n tokenId: string;\n address: string;\n isCurrentlyOwned?: boolean;\n}\ntype NftUpdate = {\n nft: Nft;\n newMetadata: NftMetadata;\n};\n\n/**\n * @type NftContract\n *\n * NFT contract information representation\n * @property name - Contract name\n * @property logo - Contract logo\n * @property address - Contract address\n * @property symbol - Contract symbol\n * @property description - Contract description\n * @property totalSupply - Total supply of NFTs\n * @property assetContractType - The NFT type, it could be `semi-fungible` or `non-fungible`\n * @property createdDate - Creation date\n * @property schemaName - The schema followed by the contract, it could be `ERC721` or `ERC1155`\n * @property externalLink - External link containing additional information\n */\nexport interface NftContract {\n name?: string;\n logo?: string;\n address: string;\n symbol?: string;\n description?: string;\n totalSupply?: string;\n assetContractType?: string;\n createdDate?: string;\n schemaName?: string;\n externalLink?: string;\n}\n\nexport enum OpenSeaV2ChainIds {\n ethereum = 'ethereum',\n}\n\nexport type OpenSeaV2GetNftResponse = { nft: OpenSeaV2DetailedNft };\n\nexport type OpenSeaV2Nft = {\n identifier: string;\n collection: string;\n contract: string;\n token_standard: string;\n name: string;\n description: string;\n image_url?: string;\n metadata_url?: string;\n updated_at: string;\n is_disabled: boolean;\n is_nsfw: boolean;\n};\n\nexport type OpenSeaV2DetailedNft = OpenSeaV2Nft & {\n animation_url?: string;\n is_suspicious: boolean;\n creator: string;\n traits: {\n trait_type: string;\n display_type?: string;\n max_value: string;\n trait_count?: number;\n value: number | string;\n }[];\n owners: {\n address: string;\n quantity: number;\n }[];\n rarity: { rank: number };\n};\n\nexport type OpenSeaV2ListNftsResponse = {\n nfts: OpenSeaV2Nft[];\n next?: string;\n};\n\nexport type OpenSeaV2Contract = {\n address: string;\n chain: string;\n collection: string;\n contract_standard: string;\n name: string;\n supply: number;\n};\n\nexport type OpenSeaV2Collection = {\n collection: string;\n name: string;\n description?: string;\n image_url?: string;\n owner: string;\n category: string;\n is_disabled: boolean;\n is_nsfw: boolean;\n trait_offers_enabled: boolean;\n opensea_url: string;\n project_url?: string;\n wiki_url?: string;\n discord_url?: string;\n telegram_url?: string;\n twitter_username?: string;\n instagram_username?: string;\n};\n\n/**\n * @type NftMetadata\n *\n * NFT custom information\n * @property name - NFT custom name\n * @property description - The NFT description\n * @property numberOfSales - Number of sales\n * @property backgroundColor - The background color to be displayed with the item\n * @property image - Image custom image URI\n * @property imagePreview - URI of a smaller image associated with this NFT\n * @property imageThumbnail - URI of a thumbnail image associated with this NFT\n * @property imageOriginal - URI of the original image associated with this NFT\n * @property animation - URI of a animation associated with this NFT\n * @property animationOriginal - URI of the original animation associated with this NFT\n * @property externalLink - External link containing additional information\n * @property creator - The NFT owner information object\n * @property standard - NFT standard name for the NFT, e.g., ERC-721 or ERC-1155\n */\nexport interface NftMetadata {\n name: string | null;\n description: string | null;\n image: string | null;\n standard: string | null;\n favorite?: boolean;\n numberOfSales?: number;\n backgroundColor?: string;\n imagePreview?: string;\n imageThumbnail?: string;\n imageOriginal?: string;\n animation?: string;\n animationOriginal?: string;\n externalLink?: string;\n creator?: ApiNftCreator;\n lastSale?: ApiNftLastSale;\n transactionId?: string;\n tokenURI?: string;\n error?: string;\n}\n\ninterface AccountParams {\n userAddress: string;\n chainId: Hex;\n}\n\n/**\n * @type NftConfig\n *\n * NFT controller configuration\n * @property selectedAddress - Vault selected address\n */\nexport interface NftConfig extends BaseConfig {\n selectedAddress: string;\n chainId: Hex;\n ipfsGateway: string;\n isIpfsGatewayEnabled: boolean;\n displayNftMedia: boolean;\n useIPFSSubdomains: boolean;\n}\n\n/**\n * @type NftState\n *\n * NFT controller state\n * @property allNftContracts - Object containing NFT contract information\n * @property allNfts - Object containing NFTs per account and network\n * @property ignoredNfts - List of NFTs that should be ignored\n */\nexport interface NftState extends BaseState {\n allNftContracts: {\n [key: string]: { [chainId: Hex]: NftContract[] };\n };\n allNfts: { [key: string]: { [chainId: Hex]: Nft[] } };\n ignoredNfts: Nft[];\n}\n\nconst ALL_NFTS_STATE_KEY = 'allNfts';\nconst ALL_NFTS_CONTRACTS_STATE_KEY = 'allNftContracts';\n\ninterface NftAsset {\n address: string;\n tokenId: string;\n}\n\n/**\n * The name of the {@link NftController}.\n */\nconst controllerName = 'NftController';\n\n/**\n * The external actions available to the {@link NftController}.\n */\ntype AllowedActions = AddApprovalRequest;\n\n/**\n * The messenger of the {@link NftController}.\n */\nexport type NftControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n AllowedActions,\n never,\n AllowedActions['type'],\n never\n>;\n\n/**\n * Controller that stores assets and exposes convenience methods\n */\nexport class NftController extends BaseController {\n private mutex = new Mutex();\n\n private messagingSystem: NftControllerMessenger;\n\n getNftApi({\n contractAddress,\n tokenId,\n }: {\n contractAddress: string;\n tokenId: string;\n }) {\n return `${OPENSEA_PROXY_URL}/chain/${OpenSeaV2ChainIds.ethereum}/contract/${contractAddress}/nfts/${tokenId}`;\n }\n\n private getNftContractInformationApi({\n contractAddress,\n }: {\n contractAddress: string;\n }) {\n return `${OPENSEA_PROXY_URL}/chain/${OpenSeaV2ChainIds.ethereum}/contract/${contractAddress}`;\n }\n\n private getNftCollectionInformationApi({\n collectionSlug,\n }: {\n collectionSlug: string;\n }) {\n return `${OPENSEA_PROXY_URL}/collections/${collectionSlug}`;\n }\n\n /**\n * Helper method to update nested state for allNfts and allNftContracts.\n *\n * @param newCollection - the modified piece of state to update in the controller's store\n * @param baseStateKey - The root key in the store to update.\n * @param passedConfig - An object containing the selectedAddress and chainId that are passed through the auto-detection flow.\n * @param passedConfig.userAddress - the address passed through the NFT detection flow to ensure assets are stored to the correct account\n * @param passedConfig.chainId - the chainId passed through the NFT detection flow to ensure assets are stored to the correct account\n */\n private updateNestedNftState(\n newCollection: Nft[] | NftContract[],\n baseStateKey: 'allNfts' | 'allNftContracts',\n { userAddress, chainId } = {\n userAddress: this.config.selectedAddress,\n chainId: this.config.chainId,\n },\n ) {\n const { [baseStateKey]: oldState } = this.state;\n\n const addressState = oldState[userAddress];\n const newAddressState = {\n ...addressState,\n ...{ [chainId]: newCollection },\n };\n const newState = {\n ...oldState,\n ...{ [userAddress]: newAddressState },\n };\n\n this.update({\n [baseStateKey]: newState,\n });\n }\n\n /**\n * Request individual NFT information from OpenSea API.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformationFromApi(\n contractAddress: string,\n tokenId: string,\n ): Promise {\n try {\n // Attempt to fetch the data with the proxy\n const nftInformation: { nft: OpenSeaV2DetailedNft } | undefined =\n await fetchWithErrorHandling({\n url: this.getNftApi({\n contractAddress,\n tokenId,\n }),\n });\n\n // if we were still unable to fetch the data we return out the default/null of `NftMetadata`\n if (!nftInformation?.nft) {\n return {\n name: null,\n description: null,\n image: null,\n standard: null,\n };\n }\n\n // if we've reached this point, we have successfully fetched some data for nftInformation\n // now we reconfigure the data to conform to the `NftMetadata` type for storage.\n const {\n num_sales,\n background_color,\n image_url,\n image_preview_url,\n image_thumbnail_url,\n image_original_url,\n animation_url,\n animation_original_url,\n name,\n description,\n external_link,\n creator,\n last_sale,\n asset_contract: { schema_name },\n } = mapOpenSeaDetailedNftV2ToV1(nftInformation.nft);\n\n /* istanbul ignore next */\n const nftMetadata: NftMetadata = Object.assign(\n {},\n { name: name || null },\n { description: description || null },\n { image: image_url || null },\n creator && { creator },\n num_sales && { numberOfSales: num_sales },\n background_color && { backgroundColor: background_color },\n image_preview_url && { imagePreview: image_preview_url },\n image_thumbnail_url && { imageThumbnail: image_thumbnail_url },\n image_original_url && { imageOriginal: image_original_url },\n animation_url && { animation: animation_url },\n animation_original_url && {\n animationOriginal: animation_original_url,\n },\n external_link && { externalLink: external_link },\n last_sale && { lastSale: last_sale },\n schema_name && { standard: schema_name },\n );\n\n return nftMetadata;\n } catch (error) {\n return {\n name: null,\n description: null,\n image: null,\n standard: null,\n error: 'Opensea import error',\n };\n }\n }\n\n /**\n * Request individual NFT information from contracts that follows Metadata Interface.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformationFromTokenURI(\n contractAddress: string,\n tokenId: string,\n ): Promise {\n const {\n ipfsGateway,\n useIPFSSubdomains,\n isIpfsGatewayEnabled,\n displayNftMedia,\n } = this.config;\n const result = await this.getNftURIAndStandard(contractAddress, tokenId);\n let tokenURI = result[0];\n const standard = result[1];\n\n if (!displayNftMedia && !isIpfsGatewayEnabled) {\n return {\n image: null,\n name: null,\n description: null,\n standard: standard || null,\n favorite: false,\n tokenURI,\n };\n }\n\n const hasIpfsTokenURI = tokenURI.startsWith('ipfs://');\n\n if (hasIpfsTokenURI && !isIpfsGatewayEnabled) {\n return {\n image: null,\n name: null,\n description: null,\n standard: standard || null,\n favorite: false,\n tokenURI: tokenURI ?? null,\n };\n }\n if (hasIpfsTokenURI) {\n tokenURI = getFormattedIpfsUrl(ipfsGateway, tokenURI, useIPFSSubdomains);\n }\n\n if (!hasIpfsTokenURI && !displayNftMedia) {\n return {\n image: null,\n name: null,\n description: null,\n standard: standard || null,\n favorite: false,\n tokenURI: tokenURI ?? null,\n };\n }\n\n try {\n const object = await handleFetch(tokenURI);\n // TODO: Check image_url existence. This is not part of EIP721 nor EIP1155\n const image = Object.prototype.hasOwnProperty.call(object, 'image')\n ? 'image'\n : /* istanbul ignore next */ 'image_url';\n\n return {\n image: object[image],\n name: object.name,\n description: object.description,\n standard,\n favorite: false,\n tokenURI: tokenURI ?? null,\n };\n } catch {\n return {\n image: null,\n name: null,\n description: null,\n standard: standard || null,\n favorite: false,\n tokenURI: tokenURI ?? null,\n error: 'URI import error',\n };\n }\n }\n\n /**\n * Retrieve NFT uri with metadata. TODO Update method to use IPFS.\n *\n * @param contractAddress - NFT contract address.\n * @param tokenId - NFT token id.\n * @returns Promise resolving NFT uri and token standard.\n */\n private async getNftURIAndStandard(\n contractAddress: string,\n tokenId: string,\n ): Promise<[string, string]> {\n // try ERC721 uri\n try {\n const uri = await this.getERC721TokenURI(contractAddress, tokenId);\n return [uri, ERC721];\n } catch {\n // Ignore error\n }\n\n // try ERC1155 uri\n try {\n const tokenURI = await this.getERC1155TokenURI(contractAddress, tokenId);\n\n /**\n * According to EIP1155 the URI value allows for ID substitution\n * in case the string `{id}` exists.\n * https://eips.ethereum.org/EIPS/eip-1155#metadata\n */\n\n if (!tokenURI.includes('{id}')) {\n return [tokenURI, ERC1155];\n }\n\n const hexTokenId = stripHexPrefix(BNToHex(new BN(tokenId)))\n .padStart(64, '0')\n .toLowerCase();\n return [tokenURI.replace('{id}', hexTokenId), ERC1155];\n } catch {\n // Ignore error\n }\n\n return ['', ''];\n }\n\n /**\n * Request individual NFT information (name, image url and description).\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformation(\n contractAddress: string,\n tokenId: string,\n ): Promise {\n const blockchainMetadata = await safelyExecute(async () => {\n return await this.getNftInformationFromTokenURI(contractAddress, tokenId);\n });\n\n let openSeaMetadata;\n if (this.config.displayNftMedia) {\n openSeaMetadata = await safelyExecute(async () => {\n return await this.getNftInformationFromApi(contractAddress, tokenId);\n });\n }\n\n if (blockchainMetadata.error && openSeaMetadata?.error) {\n return {\n image: null,\n name: null,\n description: null,\n standard: blockchainMetadata.standard ?? null,\n favorite: false,\n tokenURI: blockchainMetadata.tokenURI ?? null,\n error: 'Both import failed',\n };\n }\n\n return {\n ...openSeaMetadata,\n tokenURI:\n blockchainMetadata.tokenURI ?? openSeaMetadata?.tokenURI ?? null,\n name: blockchainMetadata.name ?? openSeaMetadata?.name ?? null,\n description:\n blockchainMetadata.description ?? openSeaMetadata?.description ?? null,\n image: blockchainMetadata.image ?? openSeaMetadata?.image ?? null,\n standard:\n blockchainMetadata.standard ?? openSeaMetadata?.standard ?? null,\n };\n }\n\n /**\n * Request NFT contract information from OpenSea API.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftContractInformationFromApi(\n contractAddress: string,\n ): Promise {\n /* istanbul ignore if */\n const apiNftContractObject: OpenSeaV2Contract | undefined =\n await fetchWithErrorHandling({\n url: this.getNftContractInformationApi({\n contractAddress,\n }),\n });\n\n // if we successfully fetched return the fetched data immediately\n if (apiNftContractObject) {\n // If we successfully fetched the contract\n if (apiNftContractObject) {\n // Then fetch some additional details from the collection\n const collection: OpenSeaV2Collection | undefined =\n await fetchWithErrorHandling({\n url: this.getNftCollectionInformationApi({\n collectionSlug: apiNftContractObject.collection,\n }),\n });\n\n return mapOpenSeaContractV2ToV1(apiNftContractObject, collection);\n }\n }\n\n // If we've reached this point we were unable to fetch data from either the proxy or opensea so we return\n // the default/null of ApiNftContract\n return {\n address: contractAddress,\n asset_contract_type: null,\n created_date: null,\n schema_name: null,\n symbol: null,\n total_supply: null,\n description: null,\n external_link: null,\n collection: {\n name: null,\n image_url: null,\n },\n };\n }\n\n /**\n * Request NFT contract information from the contract itself.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftContractInformationFromContract(\n contractAddress: string,\n ): Promise<\n Partial &\n Pick &\n Pick\n > {\n const name = await this.getERC721AssetName(contractAddress);\n const symbol = await this.getERC721AssetSymbol(contractAddress);\n return {\n collection: { name },\n symbol,\n address: contractAddress,\n };\n }\n\n /**\n * Request NFT contract information from OpenSea API.\n *\n * @param contractAddress - Hex address of the NFT contract.\n * @returns Promise resolving to the NFT contract name, image and description.\n */\n private async getNftContractInformation(\n contractAddress: string,\n ): Promise<\n Partial &\n Pick &\n Pick\n > {\n const blockchainContractData: Partial &\n Pick &\n Pick = await safelyExecute(async () => {\n return await this.getNftContractInformationFromContract(contractAddress);\n });\n\n let openSeaContractData: Partial | undefined;\n if (this.config.displayNftMedia) {\n openSeaContractData = await safelyExecute(async () => {\n return await this.getNftContractInformationFromApi(contractAddress);\n });\n }\n\n if (blockchainContractData || openSeaContractData) {\n return {\n ...openSeaContractData,\n ...blockchainContractData,\n collection: {\n image_url: null,\n ...openSeaContractData?.collection,\n ...blockchainContractData?.collection,\n },\n };\n }\n\n /* istanbul ignore next */\n return {\n address: contractAddress,\n asset_contract_type: null,\n created_date: null,\n schema_name: null,\n symbol: null,\n total_supply: null,\n description: null,\n external_link: null,\n collection: { name: null, image_url: null },\n };\n }\n\n /**\n * Adds an individual NFT to the stored NFT list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @param nftMetadata - NFT optional information (name, image and description).\n * @param nftContract - An object containing contract data of the NFT being added.\n * @param accountParams - The chain ID and address of network and account to which the nftContract should be added.\n * @param source - Whether the NFT was detected, added manually or suggested by a dapp.\n * @returns Promise resolving to the current NFT list.\n */\n private async addIndividualNft(\n address: string,\n tokenId: string,\n nftMetadata: NftMetadata,\n nftContract: NftContract,\n accountParams?: AccountParams,\n source = Source.Custom,\n ): Promise {\n // TODO: Remove unused return\n const releaseLock = await this.mutex.acquire();\n try {\n address = toChecksumHexAddress(address);\n const { allNfts } = this.state;\n let chainId, selectedAddress;\n if (accountParams) {\n chainId = accountParams.chainId;\n selectedAddress = accountParams.userAddress;\n } else {\n chainId = this.config.chainId;\n selectedAddress = this.config.selectedAddress;\n }\n\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n\n const existingEntry: Nft | undefined = nfts.find(\n (nft) =>\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId,\n );\n\n if (existingEntry) {\n const differentMetadata = compareNftMetadata(\n nftMetadata,\n existingEntry,\n );\n if (differentMetadata || !existingEntry.isCurrentlyOwned) {\n // TODO: Switch to indexToUpdate\n const indexToRemove = nfts.findIndex(\n (nft) =>\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId,\n );\n /* istanbul ignore next */\n if (indexToRemove !== -1) {\n nfts.splice(indexToRemove, 1);\n }\n } else {\n return nfts;\n }\n }\n\n const newEntry: Nft = {\n address,\n tokenId,\n favorite: existingEntry?.favorite || false,\n isCurrentlyOwned: true,\n ...nftMetadata,\n };\n\n const newNfts = [...nfts, newEntry];\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY, {\n chainId,\n userAddress: selectedAddress,\n });\n\n if (this.onNftAdded) {\n this.onNftAdded({\n address,\n symbol: nftContract.symbol,\n tokenId: tokenId.toString(),\n standard: nftMetadata.standard,\n source,\n tokenURI: nftMetadata.tokenURI,\n });\n }\n\n return newNfts;\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Adds an NFT contract to the stored NFT contracts list.\n *\n * @param address - Hex address of the NFT contract.\n * @param accountParams - The chain ID and address of network and account to which the nftContract should be added.\n * @param source - Whether the NFT was detected, added manually or suggested by a dapp.\n * @returns Promise resolving to the current NFT contracts list.\n */\n private async addNftContract(\n address: string,\n accountParams?: AccountParams,\n source?: Source,\n ): Promise {\n const releaseLock = await this.mutex.acquire();\n try {\n address = toChecksumHexAddress(address);\n const { allNftContracts } = this.state;\n let chainId, selectedAddress;\n if (accountParams) {\n chainId = accountParams.chainId;\n selectedAddress = accountParams.userAddress;\n } else {\n chainId = this.config.chainId;\n selectedAddress = this.config.selectedAddress;\n }\n\n const nftContracts = allNftContracts[selectedAddress]?.[chainId] || [];\n\n const existingEntry = nftContracts.find(\n (nftContract) =>\n nftContract.address.toLowerCase() === address.toLowerCase(),\n );\n if (existingEntry) {\n return nftContracts;\n }\n const contractInformation = await this.getNftContractInformation(address);\n const {\n asset_contract_type,\n created_date,\n schema_name,\n symbol,\n total_supply,\n description,\n external_link,\n collection: { name, image_url },\n } = contractInformation;\n\n // If the nft is auto-detected we want some valid metadata to be present\n if (\n source === Source.Detected &&\n Object.entries(contractInformation).every(([k, v]: [string, any]) => {\n if (k === 'address') {\n return true; // address will always be present\n }\n // collection will always be an object, we need to check the internal values\n if (k === 'collection') {\n return v?.name === null && v?.image_url === null;\n }\n return Boolean(v) === false;\n })\n ) {\n return nftContracts;\n }\n\n /* istanbul ignore next */\n const newEntry: NftContract = Object.assign(\n {},\n { address },\n description && { description },\n name && { name },\n image_url && { logo: image_url },\n symbol && { symbol },\n total_supply !== null &&\n typeof total_supply !== 'undefined' && { totalSupply: total_supply },\n asset_contract_type && { assetContractType: asset_contract_type },\n created_date && { createdDate: created_date },\n schema_name && { schemaName: schema_name },\n external_link && { externalLink: external_link },\n );\n const newNftContracts = [...nftContracts, newEntry];\n this.updateNestedNftState(newNftContracts, ALL_NFTS_CONTRACTS_STATE_KEY, {\n chainId,\n userAddress: selectedAddress,\n });\n\n return newNftContracts;\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Removes an individual NFT from the stored token list and saves it in ignored NFTs list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Token identifier of the NFT.\n */\n private removeAndIgnoreIndividualNft(address: string, tokenId: string) {\n address = toChecksumHexAddress(address);\n const { allNfts, ignoredNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const newIgnoredNfts = [...ignoredNfts];\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const newNfts = nfts.filter((nft) => {\n if (\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId\n ) {\n const alreadyIgnored = newIgnoredNfts.find(\n (c) => c.address === address && c.tokenId === tokenId,\n );\n !alreadyIgnored && newIgnoredNfts.push(nft);\n return false;\n }\n return true;\n });\n\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY);\n\n this.update({\n ignoredNfts: newIgnoredNfts,\n });\n }\n\n /**\n * Removes an individual NFT from the stored token list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Token identifier of the NFT.\n */\n private removeIndividualNft(address: string, tokenId: string) {\n address = toChecksumHexAddress(address);\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const newNfts = nfts.filter(\n (nft) =>\n !(\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId\n ),\n );\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY);\n }\n\n /**\n * Removes an NFT contract to the stored NFT contracts list.\n *\n * @param address - Hex address of the NFT contract.\n * @returns Promise resolving to the current NFT contracts list.\n */\n private removeNftContract(address: string): NftContract[] {\n address = toChecksumHexAddress(address);\n const { allNftContracts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nftContracts = allNftContracts[selectedAddress]?.[chainId] || [];\n\n const newNftContracts = nftContracts.filter(\n (nftContract) =>\n !(nftContract.address.toLowerCase() === address.toLowerCase()),\n );\n this.updateNestedNftState(newNftContracts, ALL_NFTS_CONTRACTS_STATE_KEY);\n\n return newNftContracts;\n }\n\n /**\n * EventEmitter instance used to listen to specific EIP747 events\n */\n hub = new EventEmitter();\n\n /**\n * Optional API key to use with opensea\n */\n openSeaApiKey?: string;\n\n /**\n * Name of this controller used during composition\n */\n override name = 'NftController';\n\n private getERC721AssetName: AssetsContractController['getERC721AssetName'];\n\n private getERC721AssetSymbol: AssetsContractController['getERC721AssetSymbol'];\n\n private getERC721TokenURI: AssetsContractController['getERC721TokenURI'];\n\n private getERC721OwnerOf: AssetsContractController['getERC721OwnerOf'];\n\n private getERC1155BalanceOf: AssetsContractController['getERC1155BalanceOf'];\n\n private getERC1155TokenURI: AssetsContractController['getERC1155TokenURI'];\n\n private onNftAdded?: (data: {\n address: string;\n symbol: string | undefined;\n tokenId: string;\n standard: string | null;\n source: string;\n tokenURI?: string;\n }) => void;\n\n /**\n * Creates an NftController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onPreferencesStateChange - Allows subscribing to preference controller state changes.\n * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.\n * @param options.getERC721AssetName - Gets the name of the asset at the given address.\n * @param options.getERC721AssetSymbol - Gets the symbol of the asset at the given address.\n * @param options.getERC721TokenURI - Gets the URI of the ERC721 token at the given address, with the given ID.\n * @param options.getERC721OwnerOf - Get the owner of a ERC-721 NFT.\n * @param options.getERC1155BalanceOf - Gets balance of a ERC-1155 NFT.\n * @param options.getERC1155TokenURI - Gets the URI of the ERC1155 token at the given address, with the given ID.\n * @param options.onNftAdded - Callback that is called when an NFT is added. Currently used pass data\n * for tracking the NFT added event.\n * @param options.messenger - The controller messenger.\n * @param config - Initial options used to configure this controller.\n * @param state - Initial state to set on this controller.\n */\n constructor(\n {\n chainId: initialChainId,\n onPreferencesStateChange,\n onNetworkStateChange,\n getERC721AssetName,\n getERC721AssetSymbol,\n getERC721TokenURI,\n getERC721OwnerOf,\n getERC1155BalanceOf,\n getERC1155TokenURI,\n onNftAdded,\n messenger,\n }: {\n chainId: Hex;\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n getERC721AssetName: AssetsContractController['getERC721AssetName'];\n getERC721AssetSymbol: AssetsContractController['getERC721AssetSymbol'];\n getERC721TokenURI: AssetsContractController['getERC721TokenURI'];\n getERC721OwnerOf: AssetsContractController['getERC721OwnerOf'];\n getERC1155BalanceOf: AssetsContractController['getERC1155BalanceOf'];\n getERC1155TokenURI: AssetsContractController['getERC1155TokenURI'];\n onNftAdded?: (data: {\n address: string;\n symbol: string | undefined;\n tokenId: string;\n standard: string | null;\n source: string;\n }) => void;\n messenger: NftControllerMessenger;\n },\n config?: Partial,\n state?: Partial,\n ) {\n super(config, state);\n this.defaultConfig = {\n selectedAddress: '',\n chainId: initialChainId,\n ipfsGateway: IPFS_DEFAULT_GATEWAY_URL,\n displayNftMedia: true,\n useIPFSSubdomains: true,\n isIpfsGatewayEnabled: true,\n };\n\n this.defaultState = {\n allNftContracts: {},\n allNfts: {},\n ignoredNfts: [],\n };\n this.initialize();\n this.getERC721AssetName = getERC721AssetName;\n this.getERC721AssetSymbol = getERC721AssetSymbol;\n this.getERC721TokenURI = getERC721TokenURI;\n this.getERC721OwnerOf = getERC721OwnerOf;\n this.getERC1155BalanceOf = getERC1155BalanceOf;\n this.getERC1155TokenURI = getERC1155TokenURI;\n this.onNftAdded = onNftAdded;\n this.messagingSystem = messenger;\n\n onPreferencesStateChange(\n async ({\n selectedAddress,\n ipfsGateway,\n displayNftMedia,\n isIpfsGatewayEnabled,\n }) => {\n this.configure({\n selectedAddress,\n ipfsGateway,\n displayNftMedia,\n isIpfsGatewayEnabled,\n });\n\n const needsUpdateNftMetadata =\n (isIpfsGatewayEnabled && ipfsGateway !== '') || displayNftMedia;\n\n if (needsUpdateNftMetadata) {\n const { chainId } = this.config;\n const nfts: Nft[] =\n this.state.allNfts[selectedAddress]?.[chainId] ?? [];\n // filter only nfts\n const nftsToUpdate = nfts.filter(\n (singleNft) =>\n !singleNft.name && !singleNft.description && !singleNft.image,\n );\n if (nftsToUpdate.length !== 0) {\n await this.updateNftMetadata({\n nfts: nftsToUpdate,\n userAddress: selectedAddress,\n });\n }\n }\n },\n );\n\n onNetworkStateChange(({ providerConfig }) => {\n const { chainId } = providerConfig;\n this.configure({ chainId });\n });\n }\n\n async validateWatchNft(\n asset: NftAsset,\n type: NFTStandardType,\n accountAddress: string,\n ) {\n const { address: contractAddress, tokenId } = asset;\n\n // Validate parameters\n if (!type) {\n throw rpcErrors.invalidParams('Asset type is required');\n }\n\n if (type !== ERC721 && type !== ERC1155) {\n throw rpcErrors.invalidParams(\n `Non NFT asset type ${type} not supported by watchNft`,\n );\n }\n\n if (!contractAddress || !tokenId) {\n throw rpcErrors.invalidParams('Both address and tokenId are required');\n }\n\n if (!isAddress(contractAddress)) {\n throw rpcErrors.invalidParams('Invalid address');\n }\n\n if (!/^\\d+$/u.test(tokenId)) {\n throw rpcErrors.invalidParams('Invalid tokenId');\n }\n\n // Check if the user owns the suggested NFT\n try {\n const isOwner = await this.isNftOwner(\n accountAddress,\n contractAddress,\n tokenId,\n );\n if (!isOwner) {\n throw rpcErrors.invalidInput(\n 'Suggested NFT is not owned by the selected account',\n );\n }\n } catch (error: any) {\n // error thrown here: \"Unable to verify ownership. Possibly because the standard is not supported or the user's currently selected network does not match the chain of the asset in question.\"\n throw rpcErrors.resourceUnavailable(error.message);\n }\n }\n\n /**\n * Adds a new suggestedAsset to state. Parameters will be validated according to\n * asset type being watched. A `:pending` hub event will be emitted once added.\n *\n * @param asset - The asset to be watched. For now ERC721 and ERC1155 tokens are accepted.\n * @param asset.address - The address of the asset contract.\n * @param asset.tokenId - The ID of the asset.\n * @param type - The asset type.\n * @param origin - Domain origin to register the asset from.\n * @returns Object containing a Promise resolving to the suggestedAsset address if accepted.\n */\n async watchNft(asset: NftAsset, type: NFTStandardType, origin: string) {\n const { selectedAddress, chainId } = this.config;\n\n await this.validateWatchNft(asset, type, selectedAddress);\n\n const nftMetadata = await this.getNftInformation(\n asset.address,\n asset.tokenId,\n );\n\n if (nftMetadata.standard && nftMetadata.standard !== type) {\n throw rpcErrors.invalidInput(\n `Suggested NFT of type ${nftMetadata.standard} does not match received type ${type}`,\n );\n }\n\n const suggestedNftMeta: SuggestedNftMeta = {\n asset: { ...asset, ...nftMetadata },\n type,\n id: random(),\n time: Date.now(),\n interactingAddress: selectedAddress,\n origin,\n };\n await this._requestApproval(suggestedNftMeta);\n const { address, tokenId } = asset;\n const { name, standard, description, image } = nftMetadata;\n\n await this.addNft(\n address,\n tokenId,\n {\n name: name ?? null,\n description: description ?? null,\n image: image ?? null,\n standard: standard ?? null,\n },\n {\n chainId,\n userAddress: selectedAddress,\n },\n Source.Dapp,\n );\n }\n\n /**\n * Sets an OpenSea API key to retrieve NFT information.\n *\n * @param openSeaApiKey - OpenSea API key.\n */\n setApiKey(openSeaApiKey: string) {\n this.openSeaApiKey = openSeaApiKey;\n }\n\n /**\n * Checks the ownership of a ERC-721 or ERC-1155 NFT for a given address.\n *\n * @param ownerAddress - User public address.\n * @param nftAddress - NFT contract address.\n * @param nftId - NFT token ID.\n * @returns Promise resolving the NFT ownership.\n */\n async isNftOwner(\n ownerAddress: string,\n nftAddress: string,\n nftId: string,\n ): Promise {\n // Checks the ownership for ERC-721.\n try {\n const owner = await this.getERC721OwnerOf(nftAddress, nftId);\n return ownerAddress.toLowerCase() === owner.toLowerCase();\n // eslint-disable-next-line no-empty\n } catch {\n // Ignore ERC-721 contract error\n }\n\n // Checks the ownership for ERC-1155.\n try {\n const balance = await this.getERC1155BalanceOf(\n ownerAddress,\n nftAddress,\n nftId,\n );\n return !balance.isZero();\n // eslint-disable-next-line no-empty\n } catch {\n // Ignore ERC-1155 contract error\n }\n\n throw new Error(\n `Unable to verify ownership. Possibly because the standard is not supported or the user's currently selected network does not match the chain of the asset in question.`,\n );\n }\n\n /**\n * Verifies currently selected address owns entered NFT address/tokenId combo and\n * adds the NFT and respective NFT contract to the stored NFT and NFT contracts lists.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n */\n async addNftVerifyOwnership(address: string, tokenId: string) {\n const { selectedAddress } = this.config;\n if (!(await this.isNftOwner(selectedAddress, address, tokenId))) {\n throw new Error('This NFT is not owned by the user');\n }\n await this.addNft(address, tokenId);\n }\n\n /**\n * Adds an NFT and respective NFT contract to the stored NFT and NFT contracts lists.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @param nftMetadata - NFT optional metadata.\n * @param accountParams - The chain ID and address of network and account to which the nftContract should be added.\n * @param source - Whether the NFT was detected, added manually or suggested by a dapp.\n * @returns Promise resolving to the current NFT list.\n */\n async addNft(\n address: string,\n tokenId: string,\n nftMetadata?: NftMetadata,\n accountParams?: AccountParams,\n source = Source.Custom,\n ) {\n address = toChecksumHexAddress(address);\n const newNftContracts = await this.addNftContract(\n address,\n accountParams,\n source,\n );\n nftMetadata =\n nftMetadata || (await this.getNftInformation(address, tokenId));\n\n // If NFT contract was not added, do not add individual NFT\n const nftContract = newNftContracts.find(\n (contract) => contract.address.toLowerCase() === address.toLowerCase(),\n );\n\n // If NFT contract information, add individual NFT\n if (nftContract) {\n await this.addIndividualNft(\n address,\n tokenId,\n nftMetadata,\n nftContract,\n accountParams,\n source,\n );\n }\n }\n\n /**\n * Refetches NFT metadata and updates the state\n *\n * @param options - Options for refetching NFT metadata\n * @param options.nfts - nfts to update metadata for.\n * @param options.userAddress - The current user address\n */\n async updateNftMetadata({\n nfts,\n userAddress = this.config.selectedAddress,\n }: {\n nfts: Nft[];\n userAddress?: string;\n }) {\n const { chainId } = this.config;\n\n const nftsWithChecksumAdr = nfts.map((nft) => {\n return {\n ...nft,\n address: toChecksumHexAddress(nft.address),\n };\n });\n const nftMetadataResults = await Promise.allSettled(\n nftsWithChecksumAdr.map(async (nft) => {\n const resMetadata = await this.getNftInformation(\n nft.address,\n nft.tokenId,\n );\n return {\n nft,\n newMetadata: resMetadata,\n };\n }),\n );\n const successfulNewFetchedNfts = nftMetadataResults.filter(\n (result): result is PromiseFulfilledResult =>\n result.status === 'fulfilled',\n );\n // We want to avoid updating the state if the state and fetched nft info are the same\n const nftsWithDifferentMetadata: PromiseFulfilledResult[] = [];\n const { allNfts } = this.state;\n const stateNfts = allNfts[userAddress]?.[chainId] || [];\n\n successfulNewFetchedNfts.forEach((singleNft) => {\n const existingEntry: Nft | undefined = stateNfts.find(\n (nft) =>\n nft.address.toLowerCase() ===\n singleNft.value.nft.address.toLowerCase() &&\n nft.tokenId === singleNft.value.nft.tokenId,\n );\n\n if (existingEntry) {\n const differentMetadata = compareNftMetadata(\n singleNft.value.newMetadata,\n existingEntry,\n );\n\n if (differentMetadata) {\n nftsWithDifferentMetadata.push(singleNft);\n }\n }\n });\n\n if (nftsWithDifferentMetadata.length !== 0) {\n nftsWithDifferentMetadata.forEach((elm) =>\n this.updateNft(\n elm.value.nft,\n elm.value.newMetadata,\n userAddress,\n chainId,\n ),\n );\n }\n }\n\n\n /**\n * Removes an NFT from the stored token list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Token identifier of the NFT.\n */\n removeNft(address: string, tokenId: string) {\n address = toChecksumHexAddress(address);\n this.removeIndividualNft(address, tokenId);\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const remainingNft = nfts.find(\n (nft) => nft.address.toLowerCase() === address.toLowerCase(),\n );\n if (!remainingNft) {\n this.removeNftContract(address);\n }\n }\n\n /**\n * Removes an NFT from the stored token list and saves it in ignored NFTs list.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Token identifier of the NFT.\n */\n removeAndIgnoreNft(address: string, tokenId: string) {\n address = toChecksumHexAddress(address);\n this.removeAndIgnoreIndividualNft(address, tokenId);\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const remainingNft = nfts.find(\n (nft) => nft.address.toLowerCase() === address.toLowerCase(),\n );\n if (!remainingNft) {\n this.removeNftContract(address);\n }\n }\n\n /**\n * Removes all NFTs from the ignored list.\n */\n clearIgnoredNfts() {\n this.update({ ignoredNfts: [] });\n }\n\n /**\n * Checks whether input NFT is still owned by the user\n * And updates the isCurrentlyOwned value on the NFT object accordingly.\n *\n * @param nft - The NFT object to check and update.\n * @param batch - A boolean indicating whether this method is being called as part of a batch or single update.\n * @param accountParams - The userAddress and chainId to check ownership against\n * @param accountParams.userAddress - the address passed through the confirmed transaction flow to ensure assets are stored to the correct account\n * @param accountParams.chainId - the chainId passed through the confirmed transaction flow to ensure assets are stored to the correct account\n * @returns the NFT with the updated isCurrentlyOwned value\n */\n async checkAndUpdateSingleNftOwnershipStatus(\n nft: Nft,\n batch: boolean,\n { userAddress, chainId } = {\n userAddress: this.config.selectedAddress,\n chainId: this.config.chainId,\n },\n ) {\n const { address, tokenId } = nft;\n let isOwned = nft.isCurrentlyOwned;\n try {\n isOwned = await this.isNftOwner(userAddress, address, tokenId);\n } catch (error) {\n if (\n !(\n error instanceof Error &&\n error.message.includes('Unable to verify ownership')\n )\n ) {\n throw error;\n }\n }\n\n nft.isCurrentlyOwned = isOwned;\n\n if (batch === true) {\n return nft;\n }\n\n // if this is not part of a batched update we update this one NFT in state\n const { allNfts } = this.state;\n const nfts = allNfts[userAddress]?.[chainId] || [];\n const nftToUpdate = nfts.find(\n (item) =>\n item.tokenId === tokenId &&\n item.address.toLowerCase() === address.toLowerCase(),\n );\n if (nftToUpdate) {\n nftToUpdate.isCurrentlyOwned = isOwned;\n this.updateNestedNftState(nfts, ALL_NFTS_STATE_KEY, {\n userAddress,\n chainId,\n });\n }\n return nft;\n }\n\n /**\n * Checks whether NFTs associated with current selectedAddress/chainId combination are still owned by the user\n * And updates the isCurrentlyOwned value on each accordingly.\n */\n async checkAndUpdateAllNftsOwnershipStatus() {\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const updatedNfts = await Promise.all(\n nfts.map(async (nft) => {\n return (\n (await this.checkAndUpdateSingleNftOwnershipStatus(nft, true)) ?? nft\n );\n }),\n );\n\n this.updateNestedNftState(updatedNfts, ALL_NFTS_STATE_KEY);\n }\n\n /**\n * Update NFT favorite status.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Hex address of the NFT contract.\n * @param favorite - NFT new favorite status.\n */\n updateNftFavoriteStatus(address: string, tokenId: string, favorite: boolean) {\n const { allNfts } = this.state;\n const { chainId, selectedAddress } = this.config;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const index: number = nfts.findIndex(\n (nft) => nft.address === address && nft.tokenId === tokenId,\n );\n\n if (index === -1) {\n return;\n }\n\n const updatedNft: Nft = {\n ...nfts[index],\n favorite,\n };\n\n // Update Nfts array\n nfts[index] = updatedNft;\n\n this.updateNestedNftState(nfts, ALL_NFTS_STATE_KEY);\n }\n\n /**\n * Returns an NFT by the address and token id.\n *\n * @param address - Hex address of the NFT contract.\n * @param tokenId - Number that represents the id of the token.\n * @param selectedAddress - Hex address of the user account.\n * @param chainId - Id of the current network.\n * @returns Object containing the NFT and its position in the array\n */\n findNftByAddressAndTokenId(\n address: string,\n tokenId: string,\n selectedAddress: string,\n chainId: Hex,\n ): { nft: Nft; index: number } | null {\n const { allNfts } = this.state;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const index: number = nfts.findIndex(\n (nft) =>\n nft.address.toLowerCase() === address.toLowerCase() &&\n nft.tokenId === tokenId,\n );\n\n if (index === -1) {\n return null;\n }\n\n return { nft: nfts[index], index };\n }\n\n /**\n * Update NFT data.\n *\n * @param nft - NFT object to find the right NFT to updates.\n * @param updates - NFT partial object to update properties of the NFT.\n * @param selectedAddress - Hex address of the user account.\n * @param chainId - Id of the current network.\n */\n updateNft(\n nft: Nft,\n updates: Partial,\n selectedAddress: string,\n chainId: Hex,\n ) {\n const { allNfts } = this.state;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const nftInfo = this.findNftByAddressAndTokenId(\n nft.address,\n nft.tokenId,\n selectedAddress,\n chainId,\n );\n\n if (!nftInfo) {\n return;\n }\n\n const updatedNft: Nft = {\n ...nft,\n ...updates,\n };\n\n const newNfts = [\n ...nfts.slice(0, nftInfo.index),\n updatedNft,\n ...nfts.slice(nftInfo.index + 1),\n ];\n\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY);\n }\n\n /**\n * Resets the transaction status of an NFT.\n *\n * @param transactionId - NFT transaction id.\n * @param selectedAddress - Hex address of the user account.\n * @param chainId - Id of the current network.\n * @returns a boolean indicating if the reset was well succeded or not\n */\n resetNftTransactionStatusByTransactionId(\n transactionId: string,\n selectedAddress: string,\n chainId: Hex,\n ): boolean {\n const { allNfts } = this.state;\n const nfts = allNfts[selectedAddress]?.[chainId] || [];\n const index: number = nfts.findIndex(\n (nft) => nft.transactionId === transactionId,\n );\n\n if (index === -1) {\n return false;\n }\n const updatedNft: Nft = {\n ...nfts[index],\n transactionId: undefined,\n };\n\n const newNfts = [\n ...nfts.slice(0, index),\n updatedNft,\n ...nfts.slice(index + 1),\n ];\n\n this.updateNestedNftState(newNfts, ALL_NFTS_STATE_KEY);\n return true;\n }\n\n async _requestApproval(suggestedNftMeta: SuggestedNftMeta) {\n return this.messagingSystem.call(\n 'ApprovalController:addRequest',\n {\n id: suggestedNftMeta.id,\n origin: suggestedNftMeta.origin,\n type: ApprovalType.WatchAsset,\n requestData: {\n id: suggestedNftMeta.id,\n interactingAddress: suggestedNftMeta.interactingAddress,\n asset: {\n address: suggestedNftMeta.asset.address,\n tokenId: suggestedNftMeta.asset.tokenId,\n name: suggestedNftMeta.asset.name,\n description: suggestedNftMeta.asset.description,\n image: suggestedNftMeta.asset.image,\n standard: suggestedNftMeta.asset.standard,\n },\n },\n },\n true,\n );\n }\n}\n\nexport default NftController;\n"]} \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/NftDetectionController.d.ts b/node_modules/@metamask/assets-controllers/dist/NftDetectionController.d.ts index 60b4330..881a358 100644 @@ -871,7 +955,7 @@ index e75c004..1bbd8ab 100644 +{"version":3,"file":"NftDetectionController.d.ts","sourceRoot":"","sources":["../src/NftDetectionController.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/NftDetectionController.js b/node_modules/@metamask/assets-controllers/dist/NftDetectionController.js -index f5df1af..7432085 100644 +index f5df1af..b30b79f 100644 --- a/node_modules/@metamask/assets-controllers/dist/NftDetectionController.js +++ b/node_modules/@metamask/assets-controllers/dist/NftDetectionController.js @@ -12,6 +12,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); @@ -897,16 +981,7 @@ index f5df1af..7432085 100644 super(config, state); /** * Name of this controller used during composition -@@ -57,8 +60,6 @@ class NftDetectionController extends base_controller_1.BaseController { - if (selectedAddress !== previouslySelectedAddress || - !useNftDetection !== disabled) { - this.configure({ selectedAddress, disabled: !useNftDetection }); -- } -- if (useNftDetection !== undefined) { - if (useNftDetection) { - this.start(); - } -@@ -74,31 +75,40 @@ class NftDetectionController extends base_controller_1.BaseController { +@@ -74,31 +77,40 @@ class NftDetectionController extends base_controller_1.BaseController { }); this.getOpenSeaApiKey = getOpenSeaApiKey; this.addNft = addNft; @@ -2203,16 +2278,16 @@ index f0bdb55..9d14190 100644 //# sourceMappingURL=assetsUtil.d.ts.map \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/assetsUtil.d.ts.map b/node_modules/@metamask/assets-controllers/dist/assetsUtil.d.ts.map -index 88e81d5..fd60799 100644 +index 88e81d5..09342c0 100644 --- a/node_modules/@metamask/assets-controllers/dist/assetsUtil.d.ts.map +++ b/node_modules/@metamask/assets-controllers/dist/assetsUtil.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"assetsUtil.d.ts","sourceRoot":"","sources":["../src/assetsUtil.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAO1D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,EAAE,EAAkB,MAAM,iBAAiB,CAAC;AAGrD,OAAO,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAEpD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,WAkBvE;AA+BD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,gBAAiB,MAAM,EAAE,aAM1D,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB;aAIxB,GAAG;kBACE,MAAM;YAIrB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,QA2BhD;AAED;;GAEG;AACH,oBAAY,+BAA+B;IACzC,OAAO,QAAQ;IACf,GAAG,SAAS;IACZ,OAAO,SAAS;IAChB,IAAI,WAAW;IACf,MAAM,eAAe;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAEzE;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAIpE;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,UAQvD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAeA;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,kBAAkB,EAAE,OAAO,GAC1B,MAAM,CAQR;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,SAAS,GAAG,EAAE,CAE5D"} \ No newline at end of file -+{"version":3,"file":"assetsUtil.d.ts","sourceRoot":"","sources":["../src/assetsUtil.ts"],"names":[],"mappings":"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"} ++{"version":3,"file":"assetsUtil.d.ts","sourceRoot":"","sources":["../src/assetsUtil.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/assetsUtil.js b/node_modules/@metamask/assets-controllers/dist/assetsUtil.js -index 521fd94..f25f518 100644 +index 521fd94..87c5877 100644 --- a/node_modules/@metamask/assets-controllers/dist/assetsUtil.js +++ b/node_modules/@metamask/assets-controllers/dist/assetsUtil.js @@ -1,10 +1,19 @@ @@ -2238,7 +2313,15 @@ index 521fd94..f25f518 100644 /** * Compares nft metadata entries to any nft entry. * We need this method when comparing a new fetched nft metadata, in case a entry changed to a defined value, -@@ -121,6 +130,12 @@ var SupportedTokenDetectionNetworks; +@@ -24,6 +33,7 @@ function compareNftMetadata(newNftMetadata, nft) { + 'animation', + 'animationOriginal', + 'externalLink', ++ 'tokenURI', + ]; + const differentValues = keys.reduce((value, key) => { + if (newNftMetadata[key] && newNftMetadata[key] !== nft[key]) { +@@ -121,6 +131,12 @@ var SupportedTokenDetectionNetworks; SupportedTokenDetectionNetworks["polygon"] = "0x89"; SupportedTokenDetectionNetworks["avax"] = "0xa86a"; SupportedTokenDetectionNetworks["aurora"] = "0x4e454152"; @@ -2251,7 +2334,7 @@ index 521fd94..f25f518 100644 })(SupportedTokenDetectionNetworks = exports.SupportedTokenDetectionNetworks || (exports.SupportedTokenDetectionNetworks = {})); /** * Check if token detection is enabled for certain networks. -@@ -224,4 +239,128 @@ function ethersBigNumberToBN(bigNumber) { +@@ -224,4 +240,128 @@ function ethersBigNumberToBN(bigNumber) { return new ethereumjs_util_1.BN((0, ethereumjs_util_1.stripHexPrefix)(bigNumber.toHexString()), 'hex'); } exports.ethersBigNumberToBN = ethersBigNumberToBN; @@ -2382,13 +2465,13 @@ index 521fd94..f25f518 100644 //# sourceMappingURL=assetsUtil.js.map \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/assetsUtil.js.map b/node_modules/@metamask/assets-controllers/dist/assetsUtil.js.map -index 0640431..7511800 100644 +index 0640431..8e6fed1 100644 --- a/node_modules/@metamask/assets-controllers/dist/assetsUtil.js.map +++ b/node_modules/@metamask/assets-controllers/dist/assetsUtil.js.map @@ -1 +1 @@ -{"version":3,"file":"assetsUtil.js","sourceRoot":"","sources":["../src/assetsUtil.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport {\n convertHexToDecimal,\n isValidHexAddress,\n GANACHE_CHAIN_ID,\n} from '@metamask/controller-utils';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\nimport { BN, stripHexPrefix } from 'ethereumjs-util';\nimport { CID } from 'multiformats/cid';\n\nimport type { Nft, NftMetadata } from './NftController';\nimport type { Token } from './TokenRatesController';\n\n/**\n * Compares nft metadata entries to any nft entry.\n * We need this method when comparing a new fetched nft metadata, in case a entry changed to a defined value,\n * there's a need to update the nft in state.\n *\n * @param newNftMetadata - Nft metadata object.\n * @param nft - Nft object to compare with.\n * @returns Whether there are differences.\n */\nexport function compareNftMetadata(newNftMetadata: NftMetadata, nft: Nft) {\n const keys: (keyof NftMetadata)[] = [\n 'image',\n 'backgroundColor',\n 'imagePreview',\n 'imageThumbnail',\n 'imageOriginal',\n 'animation',\n 'animationOriginal',\n 'externalLink',\n ];\n const differentValues = keys.reduce((value, key) => {\n if (newNftMetadata[key] && newNftMetadata[key] !== nft[key]) {\n return value + 1;\n }\n return value;\n }, 0);\n return differentValues > 0;\n}\n\nconst aggregatorNameByKey: Record = {\n aave: 'Aave',\n bancor: 'Bancor',\n cmc: 'CMC',\n cryptocom: 'Crypto.com',\n coinGecko: 'CoinGecko',\n oneInch: '1inch',\n paraswap: 'Paraswap',\n pmm: 'PMM',\n zapper: 'Zapper',\n zerion: 'Zerion',\n zeroEx: '0x',\n synthetix: 'Synthetix',\n yearn: 'Yearn',\n apeswap: 'ApeSwap',\n binanceDex: 'BinanceDex',\n pancakeTop100: 'PancakeTop100',\n pancakeExtended: 'PancakeExtended',\n balancer: 'Balancer',\n quickswap: 'QuickSwap',\n matcha: 'Matcha',\n pangolinDex: 'PangolinDex',\n pangolinDexStableCoin: 'PangolinDexStableCoin',\n pangolinDexAvaxBridge: 'PangolinDexAvaxBridge',\n traderJoe: 'TraderJoe',\n airswapLight: 'AirswapLight',\n kleros: 'Kleros',\n};\n\n/**\n * Formats aggregator names to presentable format.\n *\n * @param aggregators - List of token list names in camelcase.\n * @returns Formatted aggregator names.\n */\nexport const formatAggregatorNames = (aggregators: string[]) => {\n return aggregators.map(\n (key) =>\n aggregatorNameByKey[key] ||\n `${key[0].toUpperCase()}${key.substring(1, key.length)}`,\n );\n};\n\n/**\n * Format token list assets to use image proxy from Codefi.\n *\n * @param params - Object that contains chainID and tokenAddress.\n * @param params.chainId - ChainID of network in 0x-prefixed hexadecimal format.\n * @param params.tokenAddress - Address of token in mixed or lowercase.\n * @returns Formatted image url\n */\nexport const formatIconUrlWithProxy = ({\n chainId,\n tokenAddress,\n}: {\n chainId: Hex;\n tokenAddress: string;\n}) => {\n const chainIdDecimal = convertHexToDecimal(chainId).toString();\n return `https://static.metafi.codefi.network/api/v1/tokenIcons/${chainIdDecimal}/${tokenAddress.toLowerCase()}.png`;\n};\n\n/**\n * Validates a ERC20 token to be added with EIP747.\n *\n * @param token - Token object to validate.\n */\nexport function validateTokenToWatch(token: Token) {\n const { address, symbol, decimals } = token;\n if (!address || !symbol || typeof decimals === 'undefined') {\n throw rpcErrors.invalidParams(\n `Must specify address, symbol, and decimals.`,\n );\n }\n\n if (typeof symbol !== 'string') {\n throw rpcErrors.invalidParams(`Invalid symbol: not a string.`);\n }\n\n if (symbol.length > 11) {\n throw rpcErrors.invalidParams(\n `Invalid symbol \"${symbol}\": longer than 11 characters.`,\n );\n }\n const numDecimals = parseInt(decimals as unknown as string, 10);\n if (isNaN(numDecimals) || numDecimals > 36 || numDecimals < 0) {\n throw rpcErrors.invalidParams(\n `Invalid decimals \"${decimals}\": must be 0 <= 36.`,\n );\n }\n\n if (!isValidHexAddress(address)) {\n throw rpcErrors.invalidParams(`Invalid address \"${address}\".`);\n }\n}\n\n/**\n * Networks where token detection is supported - Values are in decimal format\n */\nexport enum SupportedTokenDetectionNetworks {\n mainnet = '0x1', // decimal: 1\n bsc = '0x38', // decimal: 56\n polygon = '0x89', // decimal: 137\n avax = '0xa86a', // decimal: 43114\n aurora = '0x4e454152', // decimal: 1313161554\n}\n\n/**\n * Check if token detection is enabled for certain networks.\n *\n * @param chainId - ChainID of network\n * @returns Whether the current network supports token detection\n */\nexport function isTokenDetectionSupportedForNetwork(chainId: Hex): boolean {\n return Object.values(SupportedTokenDetectionNetworks).includes(chainId);\n}\n\n/**\n * Check if token list polling is enabled for a given network.\n * Currently this method is used to support e2e testing for consumers of this package.\n *\n * @param chainId - ChainID of network\n * @returns Whether the current network supports tokenlists\n */\nexport function isTokenListSupportedForNetwork(chainId: Hex): boolean {\n return (\n isTokenDetectionSupportedForNetwork(chainId) || chainId === GANACHE_CHAIN_ID\n );\n}\n\n/**\n * Removes IPFS protocol prefix from input string.\n *\n * @param ipfsUrl - An IPFS url (e.g. ipfs://{content id})\n * @returns IPFS content identifier and (possibly) path in a string\n * @throws Will throw if the url passed is not IPFS.\n */\nexport function removeIpfsProtocolPrefix(ipfsUrl: string) {\n if (ipfsUrl.startsWith('ipfs://ipfs/')) {\n return ipfsUrl.replace('ipfs://ipfs/', '');\n } else if (ipfsUrl.startsWith('ipfs://')) {\n return ipfsUrl.replace('ipfs://', '');\n }\n // this method should not be used with non-ipfs urls (i.e. startsWith('ipfs://') === true)\n throw new Error('this method should not be used with non ipfs urls');\n}\n\n/**\n * Extracts content identifier and path from an input string.\n *\n * @param ipfsUrl - An IPFS URL minus the IPFS protocol prefix\n * @returns IFPS content identifier (cid) and sub path as string.\n * @throws Will throw if the url passed is not ipfs.\n */\nexport function getIpfsCIDv1AndPath(ipfsUrl: string): {\n cid: string;\n path?: string;\n} {\n const url = removeIpfsProtocolPrefix(ipfsUrl);\n\n // check if there is a path\n // (CID is everything preceding first forward slash, path is everything after)\n const index = url.indexOf('/');\n const cid = index !== -1 ? url.substring(0, index) : url;\n const path = index !== -1 ? url.substring(index) : undefined;\n\n // We want to ensure that the CID is v1 (https://docs.ipfs.io/concepts/content-addressing/#identifier-formats)\n // because most cid v0s appear to be incompatible with IPFS subdomains\n return {\n cid: CID.parse(cid).toV1().toString(),\n path,\n };\n}\n\n/**\n * Formats URL correctly for use retrieving assets hosted on IPFS.\n *\n * @param ipfsGateway - The users preferred IPFS gateway (full URL or just host).\n * @param ipfsUrl - The IFPS URL pointed at the asset.\n * @param subdomainSupported - Boolean indicating whether the URL should be formatted with subdomains or not.\n * @returns A formatted URL, with the user's preferred IPFS gateway and format (subdomain or not), pointing to an asset hosted on IPFS.\n */\nexport function getFormattedIpfsUrl(\n ipfsGateway: string,\n ipfsUrl: string,\n subdomainSupported: boolean,\n): string {\n const { host, protocol, origin } = new URL(addUrlProtocolPrefix(ipfsGateway));\n if (subdomainSupported) {\n const { cid, path } = getIpfsCIDv1AndPath(ipfsUrl);\n return `${protocol}//${cid}.ipfs.${host}${path ?? ''}`;\n }\n const cidAndPath = removeIpfsProtocolPrefix(ipfsUrl);\n return `${origin}/ipfs/${cidAndPath}`;\n}\n\n/**\n * Adds URL protocol prefix to input URL string if missing.\n *\n * @param urlString - An IPFS URL.\n * @returns A URL with a https:// prepended.\n */\nexport function addUrlProtocolPrefix(urlString: string): string {\n if (!urlString.match(/(^http:\\/\\/)|(^https:\\/\\/)/u)) {\n return `https://${urlString}`;\n }\n return urlString;\n}\n\n/**\n * Converts an Ethers BigNumber to a BN.\n *\n * @param bigNumber - An Ethers BigNumber instance.\n * @returns A BN object.\n */\nexport function ethersBigNumberToBN(bigNumber: BigNumber): BN {\n return new BN(stripHexPrefix(bigNumber.toHexString()), 'hex');\n}\n"]} \ No newline at end of file -+{"version":3,"file":"assetsUtil.js","sourceRoot":"","sources":["../src/assetsUtil.ts"],"names":[],"mappings":"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","sourcesContent":["import { rpcErrors } from '@metamask/rpc-errors';\nimport { CID } from 'multiformats/cid';\nimport type { Hex } from '@metamask/utils';\nimport {\n convertHexToDecimal,\n isValidHexAddress,\n GANACHE_CHAIN_ID,\n} from '@metamask/controller-utils';\nimport { BigNumber } from '@ethersproject/bignumber';\nimport { BN, stripHexPrefix } from 'ethereumjs-util';\nimport {\n Nft,\n NftMetadata,\n OpenSeaV2Collection,\n OpenSeaV2Contract,\n OpenSeaV2DetailedNft,\n OpenSeaV2Nft,\n} from './NftController';\nimport { Token } from './TokenRatesController';\nimport { ApiNft, ApiNftContract } from './NftDetectionController';\n\n/**\n * Compares nft metadata entries to any nft entry.\n * We need this method when comparing a new fetched nft metadata, in case a entry changed to a defined value,\n * there's a need to update the nft in state.\n *\n * @param newNftMetadata - Nft metadata object.\n * @param nft - Nft object to compare with.\n * @returns Whether there are differences.\n */\nexport function compareNftMetadata(newNftMetadata: NftMetadata, nft: Nft) {\n const keys: (keyof NftMetadata)[] = [\n 'image',\n 'backgroundColor',\n 'imagePreview',\n 'imageThumbnail',\n 'imageOriginal',\n 'animation',\n 'animationOriginal',\n 'externalLink',\n ];\n const differentValues = keys.reduce((value, key) => {\n if (newNftMetadata[key] && newNftMetadata[key] !== nft[key]) {\n return value + 1;\n }\n return value;\n }, 0);\n return differentValues > 0;\n}\n\nconst aggregatorNameByKey: Record = {\n aave: 'Aave',\n bancor: 'Bancor',\n cmc: 'CMC',\n cryptocom: 'Crypto.com',\n coinGecko: 'CoinGecko',\n oneInch: '1inch',\n paraswap: 'Paraswap',\n pmm: 'PMM',\n zapper: 'Zapper',\n zerion: 'Zerion',\n zeroEx: '0x',\n synthetix: 'Synthetix',\n yearn: 'Yearn',\n apeswap: 'ApeSwap',\n binanceDex: 'BinanceDex',\n pancakeTop100: 'PancakeTop100',\n pancakeExtended: 'PancakeExtended',\n balancer: 'Balancer',\n quickswap: 'QuickSwap',\n matcha: 'Matcha',\n pangolinDex: 'PangolinDex',\n pangolinDexStableCoin: 'PangolinDexStableCoin',\n pangolinDexAvaxBridge: 'PangolinDexAvaxBridge',\n traderJoe: 'TraderJoe',\n airswapLight: 'AirswapLight',\n kleros: 'Kleros',\n};\n\n/**\n * Formats aggregator names to presentable format.\n *\n * @param aggregators - List of token list names in camelcase.\n * @returns Formatted aggregator names.\n */\nexport const formatAggregatorNames = (aggregators: string[]) => {\n return aggregators.map(\n (key) =>\n aggregatorNameByKey[key] ||\n `${key[0].toUpperCase()}${key.substring(1, key.length)}`,\n );\n};\n\n/**\n * Format token list assets to use image proxy from Codefi.\n *\n * @param params - Object that contains chainID and tokenAddress.\n * @param params.chainId - ChainID of network in 0x-prefixed hexadecimal format.\n * @param params.tokenAddress - Address of token in mixed or lowercase.\n * @returns Formatted image url\n */\nexport const formatIconUrlWithProxy = ({\n chainId,\n tokenAddress,\n}: {\n chainId: Hex;\n tokenAddress: string;\n}) => {\n const chainIdDecimal = convertHexToDecimal(chainId).toString();\n return `https://static.metafi.codefi.network/api/v1/tokenIcons/${chainIdDecimal}/${tokenAddress.toLowerCase()}.png`;\n};\n\n/**\n * Validates a ERC20 token to be added with EIP747.\n *\n * @param token - Token object to validate.\n */\nexport function validateTokenToWatch(token: Token) {\n const { address, symbol, decimals } = token;\n if (!address || !symbol || typeof decimals === 'undefined') {\n throw rpcErrors.invalidParams(\n `Must specify address, symbol, and decimals.`,\n );\n }\n\n if (typeof symbol !== 'string') {\n throw rpcErrors.invalidParams(`Invalid symbol: not a string.`);\n }\n\n if (symbol.length > 11) {\n throw rpcErrors.invalidParams(\n `Invalid symbol \"${symbol}\": longer than 11 characters.`,\n );\n }\n const numDecimals = parseInt(decimals as unknown as string, 10);\n if (isNaN(numDecimals) || numDecimals > 36 || numDecimals < 0) {\n throw rpcErrors.invalidParams(\n `Invalid decimals \"${decimals}\": must be 0 <= 36.`,\n );\n }\n\n if (!isValidHexAddress(address)) {\n throw rpcErrors.invalidParams(`Invalid address \"${address}\".`);\n }\n}\n\n/**\n * Networks where token detection is supported - Values are in decimal format\n */\nexport enum SupportedTokenDetectionNetworks {\n mainnet = '0x1', // decimal: 1\n bsc = '0x38', // decimal: 56\n polygon = '0x89', // decimal: 137\n avax = '0xa86a', // decimal: 43114\n aurora = '0x4e454152', // decimal: 1313161554\n linea_goerli = '0xe704', // decimal: 59140\n linea_mainnet = '0xe708', // decimal: 59144\n arbitrum = '0xa4b1', // decimal: 42161\n optimism = '0xa', // decimal: 10\n base = '0x2105', // decimal: 8453\n zksync = '0x144', // decimal: 324\n}\n\n/**\n * Check if token detection is enabled for certain networks.\n *\n * @param chainId - ChainID of network\n * @returns Whether the current network supports token detection\n */\nexport function isTokenDetectionSupportedForNetwork(chainId: Hex): boolean {\n return Object.values(SupportedTokenDetectionNetworks).includes(chainId);\n}\n\n/**\n * Check if token list polling is enabled for a given network.\n * Currently this method is used to support e2e testing for consumers of this package.\n *\n * @param chainId - ChainID of network\n * @returns Whether the current network supports tokenlists\n */\nexport function isTokenListSupportedForNetwork(chainId: Hex): boolean {\n return (\n isTokenDetectionSupportedForNetwork(chainId) || chainId === GANACHE_CHAIN_ID\n );\n}\n\n/**\n * Removes IPFS protocol prefix from input string.\n *\n * @param ipfsUrl - An IPFS url (e.g. ipfs://{content id})\n * @returns IPFS content identifier and (possibly) path in a string\n * @throws Will throw if the url passed is not IPFS.\n */\nexport function removeIpfsProtocolPrefix(ipfsUrl: string) {\n if (ipfsUrl.startsWith('ipfs://ipfs/')) {\n return ipfsUrl.replace('ipfs://ipfs/', '');\n } else if (ipfsUrl.startsWith('ipfs://')) {\n return ipfsUrl.replace('ipfs://', '');\n }\n // this method should not be used with non-ipfs urls (i.e. startsWith('ipfs://') === true)\n throw new Error('this method should not be used with non ipfs urls');\n}\n\n/**\n * Extracts content identifier and path from an input string.\n *\n * @param ipfsUrl - An IPFS URL minus the IPFS protocol prefix\n * @returns IFPS content identifier (cid) and sub path as string.\n * @throws Will throw if the url passed is not ipfs.\n */\nexport function getIpfsCIDv1AndPath(ipfsUrl: string): {\n cid: string;\n path?: string;\n} {\n const url = removeIpfsProtocolPrefix(ipfsUrl);\n\n // check if there is a path\n // (CID is everything preceding first forward slash, path is everything after)\n const index = url.indexOf('/');\n const cid = index !== -1 ? url.substring(0, index) : url;\n const path = index !== -1 ? url.substring(index) : undefined;\n\n // We want to ensure that the CID is v1 (https://docs.ipfs.io/concepts/content-addressing/#identifier-formats)\n // because most cid v0s appear to be incompatible with IPFS subdomains\n return {\n cid: CID.parse(cid).toV1().toString(),\n path,\n };\n}\n\n/**\n * Formats URL correctly for use retrieving assets hosted on IPFS.\n *\n * @param ipfsGateway - The users preferred IPFS gateway (full URL or just host).\n * @param ipfsUrl - The IFPS URL pointed at the asset.\n * @param subdomainSupported - Boolean indicating whether the URL should be formatted with subdomains or not.\n * @returns A formatted URL, with the user's preferred IPFS gateway and format (subdomain or not), pointing to an asset hosted on IPFS.\n */\nexport function getFormattedIpfsUrl(\n ipfsGateway: string,\n ipfsUrl: string,\n subdomainSupported: boolean,\n): string {\n const { host, protocol, origin } = new URL(addUrlProtocolPrefix(ipfsGateway));\n if (subdomainSupported) {\n const { cid, path } = getIpfsCIDv1AndPath(ipfsUrl);\n return `${protocol}//${cid}.ipfs.${host}${path ?? ''}`;\n }\n const cidAndPath = removeIpfsProtocolPrefix(ipfsUrl);\n return `${origin}/ipfs/${cidAndPath}`;\n}\n\n/**\n * Adds URL protocol prefix to input URL string if missing.\n *\n * @param urlString - An IPFS URL.\n * @returns A URL with a https:// prepended.\n */\nexport function addUrlProtocolPrefix(urlString: string): string {\n if (!urlString.match(/(^http:\\/\\/)|(^https:\\/\\/)/u)) {\n return `https://${urlString}`;\n }\n return urlString;\n}\n\n/**\n * Converts an Ethers BigNumber to a BN.\n *\n * @param bigNumber - An Ethers BigNumber instance.\n * @returns A BN object.\n */\nexport function ethersBigNumberToBN(bigNumber: BigNumber): BN {\n return new BN(stripHexPrefix(bigNumber.toHexString()), 'hex');\n}\n\n/**\n * Partitions a list of values into groups that are at most `batchSize` in\n * length.\n *\n * @param values - The list of values.\n * @param args - The remaining arguments.\n * @param args.batchSize - The desired maximum number of values per batch.\n * @returns The list of batches.\n */\nexport function divideIntoBatches(\n values: Value[],\n { batchSize }: { batchSize: number },\n): Value[][] {\n const batches = [];\n for (let i = 0; i < values.length; i += batchSize) {\n batches.push(values.slice(i, i + batchSize));\n }\n return batches;\n}\n\n/**\n * Constructs an object from processing batches of the given values\n * sequentially.\n *\n * @param args - The arguments to this function.\n * @param args.values - A list of values to iterate over.\n * @param args.batchSize - The maximum number of values in each batch.\n * @param args.eachBatch - A function to call for each batch. This function is\n * similar to the function that `Array.prototype.reduce` takes, in that it\n * receives the object that is being built, each batch in the list of batches\n * and the index, and should return an updated version of the object.\n * @param args.initialResult - The initial value of the final data structure,\n * i.e., the value that will be fed into the first call of `eachBatch`.\n * @returns The built object.\n */\nexport async function reduceInBatchesSerially<\n Value,\n Result extends Record,\n>({\n values,\n batchSize,\n eachBatch,\n initialResult,\n}: {\n values: Value[];\n batchSize: number;\n eachBatch: (\n workingResult: Partial,\n batch: Value[],\n index: number,\n ) => Partial | Promise>;\n initialResult: Partial;\n}): Promise {\n const batches = divideIntoBatches(values, { batchSize });\n let workingResult = initialResult;\n for (const [index, batch] of batches.entries()) {\n workingResult = await eachBatch(workingResult, batch, index);\n }\n // There's no way around this — we have to assume that in the end, the result\n // matches the intended type.\n const finalResult = workingResult as Result;\n return finalResult;\n}\n\n/**\n * Maps an OpenSea V2 NFT to the V1 schema.\n * @param nft - The V2 NFT to map.\n * @returns The NFT in the V1 schema.\n */\nexport function mapOpenSeaNftV2ToV1(nft: OpenSeaV2Nft): ApiNft {\n return {\n token_id: nft.identifier,\n num_sales: null,\n background_color: null,\n image_url: nft.image_url ?? null,\n image_preview_url: null,\n image_thumbnail_url: null,\n image_original_url: null,\n animation_url: null,\n animation_original_url: null,\n name: nft.name,\n description: nft.description,\n external_link: null,\n asset_contract: {\n address: nft.contract,\n asset_contract_type: null,\n created_date: null,\n schema_name: nft.token_standard.toUpperCase(),\n symbol: null,\n total_supply: null,\n description: nft.description,\n external_link: null,\n collection: {\n name: nft.collection,\n image_url: null,\n },\n },\n creator: {\n user: { username: '' },\n profile_img_url: '',\n address: '',\n },\n last_sale: null,\n };\n}\n\n/**\n * Maps an OpenSea V2 detailed NFT to the V1 schema.\n * @param nft - The V2 detailed NFT to map.\n * @returns The NFT in the V1 schema.\n */\nexport function mapOpenSeaDetailedNftV2ToV1(nft: OpenSeaV2DetailedNft): ApiNft {\n const mapped = mapOpenSeaNftV2ToV1(nft);\n return {\n ...mapped,\n animation_url: nft.animation_url ?? null,\n creator: {\n ...mapped.creator,\n address: nft.creator,\n },\n };\n}\n\n/**\n * Maps an OpenSea V2 contract to the V1 schema.\n * @param contract - The v2 contract data.\n * @param collection - The v2 collection data.\n * @returns The contract in the v1 schema.\n */\nexport function mapOpenSeaContractV2ToV1(\n contract: OpenSeaV2Contract,\n collection?: OpenSeaV2Collection,\n): ApiNftContract {\n return {\n address: contract.address,\n asset_contract_type: null,\n created_date: null,\n schema_name: contract.contract_standard.toUpperCase(),\n symbol: null,\n total_supply: contract.supply?.toString(),\n description: collection?.description ?? null,\n external_link: collection?.project_url ?? null,\n collection: {\n name: collection?.name ?? contract.name,\n image_url: collection?.image_url,\n },\n };\n}\n"]} ++{"version":3,"file":"assetsUtil.js","sourceRoot":"","sources":["../src/assetsUtil.ts"],"names":[],"mappings":"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","sourcesContent":["import { rpcErrors } from '@metamask/rpc-errors';\nimport { CID } from 'multiformats/cid';\nimport type { Hex } from '@metamask/utils';\nimport {\n convertHexToDecimal,\n isValidHexAddress,\n GANACHE_CHAIN_ID,\n} from '@metamask/controller-utils';\nimport { BigNumber } from '@ethersproject/bignumber';\nimport { BN, stripHexPrefix } from 'ethereumjs-util';\nimport {\n Nft,\n NftMetadata,\n OpenSeaV2Collection,\n OpenSeaV2Contract,\n OpenSeaV2DetailedNft,\n OpenSeaV2Nft,\n} from './NftController';\nimport { Token } from './TokenRatesController';\nimport { ApiNft, ApiNftContract } from './NftDetectionController';\n\n/**\n * Compares nft metadata entries to any nft entry.\n * We need this method when comparing a new fetched nft metadata, in case a entry changed to a defined value,\n * there's a need to update the nft in state.\n *\n * @param newNftMetadata - Nft metadata object.\n * @param nft - Nft object to compare with.\n * @returns Whether there are differences.\n */\nexport function compareNftMetadata(newNftMetadata: NftMetadata, nft: Nft) {\n const keys: (keyof NftMetadata)[] = [\n 'image',\n 'backgroundColor',\n 'imagePreview',\n 'imageThumbnail',\n 'imageOriginal',\n 'animation',\n 'animationOriginal',\n 'externalLink',\n 'tokenURI',\n ];\n const differentValues = keys.reduce((value, key) => {\n if (newNftMetadata[key] && newNftMetadata[key] !== nft[key]) {\n return value + 1;\n }\n return value;\n }, 0);\n return differentValues > 0;\n}\n\nconst aggregatorNameByKey: Record = {\n aave: 'Aave',\n bancor: 'Bancor',\n cmc: 'CMC',\n cryptocom: 'Crypto.com',\n coinGecko: 'CoinGecko',\n oneInch: '1inch',\n paraswap: 'Paraswap',\n pmm: 'PMM',\n zapper: 'Zapper',\n zerion: 'Zerion',\n zeroEx: '0x',\n synthetix: 'Synthetix',\n yearn: 'Yearn',\n apeswap: 'ApeSwap',\n binanceDex: 'BinanceDex',\n pancakeTop100: 'PancakeTop100',\n pancakeExtended: 'PancakeExtended',\n balancer: 'Balancer',\n quickswap: 'QuickSwap',\n matcha: 'Matcha',\n pangolinDex: 'PangolinDex',\n pangolinDexStableCoin: 'PangolinDexStableCoin',\n pangolinDexAvaxBridge: 'PangolinDexAvaxBridge',\n traderJoe: 'TraderJoe',\n airswapLight: 'AirswapLight',\n kleros: 'Kleros',\n};\n\n/**\n * Formats aggregator names to presentable format.\n *\n * @param aggregators - List of token list names in camelcase.\n * @returns Formatted aggregator names.\n */\nexport const formatAggregatorNames = (aggregators: string[]) => {\n return aggregators.map(\n (key) =>\n aggregatorNameByKey[key] ||\n `${key[0].toUpperCase()}${key.substring(1, key.length)}`,\n );\n};\n\n/**\n * Format token list assets to use image proxy from Codefi.\n *\n * @param params - Object that contains chainID and tokenAddress.\n * @param params.chainId - ChainID of network in 0x-prefixed hexadecimal format.\n * @param params.tokenAddress - Address of token in mixed or lowercase.\n * @returns Formatted image url\n */\nexport const formatIconUrlWithProxy = ({\n chainId,\n tokenAddress,\n}: {\n chainId: Hex;\n tokenAddress: string;\n}) => {\n const chainIdDecimal = convertHexToDecimal(chainId).toString();\n return `https://static.metafi.codefi.network/api/v1/tokenIcons/${chainIdDecimal}/${tokenAddress.toLowerCase()}.png`;\n};\n\n/**\n * Validates a ERC20 token to be added with EIP747.\n *\n * @param token - Token object to validate.\n */\nexport function validateTokenToWatch(token: Token) {\n const { address, symbol, decimals } = token;\n if (!address || !symbol || typeof decimals === 'undefined') {\n throw rpcErrors.invalidParams(\n `Must specify address, symbol, and decimals.`,\n );\n }\n\n if (typeof symbol !== 'string') {\n throw rpcErrors.invalidParams(`Invalid symbol: not a string.`);\n }\n\n if (symbol.length > 11) {\n throw rpcErrors.invalidParams(\n `Invalid symbol \"${symbol}\": longer than 11 characters.`,\n );\n }\n const numDecimals = parseInt(decimals as unknown as string, 10);\n if (isNaN(numDecimals) || numDecimals > 36 || numDecimals < 0) {\n throw rpcErrors.invalidParams(\n `Invalid decimals \"${decimals}\": must be 0 <= 36.`,\n );\n }\n\n if (!isValidHexAddress(address)) {\n throw rpcErrors.invalidParams(`Invalid address \"${address}\".`);\n }\n}\n\n/**\n * Networks where token detection is supported - Values are in decimal format\n */\nexport enum SupportedTokenDetectionNetworks {\n mainnet = '0x1', // decimal: 1\n bsc = '0x38', // decimal: 56\n polygon = '0x89', // decimal: 137\n avax = '0xa86a', // decimal: 43114\n aurora = '0x4e454152', // decimal: 1313161554\n linea_goerli = '0xe704', // decimal: 59140\n linea_mainnet = '0xe708', // decimal: 59144\n arbitrum = '0xa4b1', // decimal: 42161\n optimism = '0xa', // decimal: 10\n base = '0x2105', // decimal: 8453\n zksync = '0x144', // decimal: 324\n}\n\n/**\n * Check if token detection is enabled for certain networks.\n *\n * @param chainId - ChainID of network\n * @returns Whether the current network supports token detection\n */\nexport function isTokenDetectionSupportedForNetwork(chainId: Hex): boolean {\n return Object.values(SupportedTokenDetectionNetworks).includes(chainId);\n}\n\n/**\n * Check if token list polling is enabled for a given network.\n * Currently this method is used to support e2e testing for consumers of this package.\n *\n * @param chainId - ChainID of network\n * @returns Whether the current network supports tokenlists\n */\nexport function isTokenListSupportedForNetwork(chainId: Hex): boolean {\n return (\n isTokenDetectionSupportedForNetwork(chainId) || chainId === GANACHE_CHAIN_ID\n );\n}\n\n/**\n * Removes IPFS protocol prefix from input string.\n *\n * @param ipfsUrl - An IPFS url (e.g. ipfs://{content id})\n * @returns IPFS content identifier and (possibly) path in a string\n * @throws Will throw if the url passed is not IPFS.\n */\nexport function removeIpfsProtocolPrefix(ipfsUrl: string) {\n if (ipfsUrl.startsWith('ipfs://ipfs/')) {\n return ipfsUrl.replace('ipfs://ipfs/', '');\n } else if (ipfsUrl.startsWith('ipfs://')) {\n return ipfsUrl.replace('ipfs://', '');\n }\n // this method should not be used with non-ipfs urls (i.e. startsWith('ipfs://') === true)\n throw new Error('this method should not be used with non ipfs urls');\n}\n\n/**\n * Extracts content identifier and path from an input string.\n *\n * @param ipfsUrl - An IPFS URL minus the IPFS protocol prefix\n * @returns IFPS content identifier (cid) and sub path as string.\n * @throws Will throw if the url passed is not ipfs.\n */\nexport function getIpfsCIDv1AndPath(ipfsUrl: string): {\n cid: string;\n path?: string;\n} {\n const url = removeIpfsProtocolPrefix(ipfsUrl);\n\n // check if there is a path\n // (CID is everything preceding first forward slash, path is everything after)\n const index = url.indexOf('/');\n const cid = index !== -1 ? url.substring(0, index) : url;\n const path = index !== -1 ? url.substring(index) : undefined;\n\n // We want to ensure that the CID is v1 (https://docs.ipfs.io/concepts/content-addressing/#identifier-formats)\n // because most cid v0s appear to be incompatible with IPFS subdomains\n return {\n cid: CID.parse(cid).toV1().toString(),\n path,\n };\n}\n\n/**\n * Formats URL correctly for use retrieving assets hosted on IPFS.\n *\n * @param ipfsGateway - The users preferred IPFS gateway (full URL or just host).\n * @param ipfsUrl - The IFPS URL pointed at the asset.\n * @param subdomainSupported - Boolean indicating whether the URL should be formatted with subdomains or not.\n * @returns A formatted URL, with the user's preferred IPFS gateway and format (subdomain or not), pointing to an asset hosted on IPFS.\n */\nexport function getFormattedIpfsUrl(\n ipfsGateway: string,\n ipfsUrl: string,\n subdomainSupported: boolean,\n): string {\n const { host, protocol, origin } = new URL(addUrlProtocolPrefix(ipfsGateway));\n if (subdomainSupported) {\n const { cid, path } = getIpfsCIDv1AndPath(ipfsUrl);\n return `${protocol}//${cid}.ipfs.${host}${path ?? ''}`;\n }\n const cidAndPath = removeIpfsProtocolPrefix(ipfsUrl);\n return `${origin}/ipfs/${cidAndPath}`;\n}\n\n/**\n * Adds URL protocol prefix to input URL string if missing.\n *\n * @param urlString - An IPFS URL.\n * @returns A URL with a https:// prepended.\n */\nexport function addUrlProtocolPrefix(urlString: string): string {\n if (!urlString.match(/(^http:\\/\\/)|(^https:\\/\\/)/u)) {\n return `https://${urlString}`;\n }\n return urlString;\n}\n\n/**\n * Converts an Ethers BigNumber to a BN.\n *\n * @param bigNumber - An Ethers BigNumber instance.\n * @returns A BN object.\n */\nexport function ethersBigNumberToBN(bigNumber: BigNumber): BN {\n return new BN(stripHexPrefix(bigNumber.toHexString()), 'hex');\n}\n\n/**\n * Partitions a list of values into groups that are at most `batchSize` in\n * length.\n *\n * @param values - The list of values.\n * @param args - The remaining arguments.\n * @param args.batchSize - The desired maximum number of values per batch.\n * @returns The list of batches.\n */\nexport function divideIntoBatches(\n values: Value[],\n { batchSize }: { batchSize: number },\n): Value[][] {\n const batches = [];\n for (let i = 0; i < values.length; i += batchSize) {\n batches.push(values.slice(i, i + batchSize));\n }\n return batches;\n}\n\n/**\n * Constructs an object from processing batches of the given values\n * sequentially.\n *\n * @param args - The arguments to this function.\n * @param args.values - A list of values to iterate over.\n * @param args.batchSize - The maximum number of values in each batch.\n * @param args.eachBatch - A function to call for each batch. This function is\n * similar to the function that `Array.prototype.reduce` takes, in that it\n * receives the object that is being built, each batch in the list of batches\n * and the index, and should return an updated version of the object.\n * @param args.initialResult - The initial value of the final data structure,\n * i.e., the value that will be fed into the first call of `eachBatch`.\n * @returns The built object.\n */\nexport async function reduceInBatchesSerially<\n Value,\n Result extends Record,\n>({\n values,\n batchSize,\n eachBatch,\n initialResult,\n}: {\n values: Value[];\n batchSize: number;\n eachBatch: (\n workingResult: Partial,\n batch: Value[],\n index: number,\n ) => Partial | Promise>;\n initialResult: Partial;\n}): Promise {\n const batches = divideIntoBatches(values, { batchSize });\n let workingResult = initialResult;\n for (const [index, batch] of batches.entries()) {\n workingResult = await eachBatch(workingResult, batch, index);\n }\n // There's no way around this — we have to assume that in the end, the result\n // matches the intended type.\n const finalResult = workingResult as Result;\n return finalResult;\n}\n\n/**\n * Maps an OpenSea V2 NFT to the V1 schema.\n * @param nft - The V2 NFT to map.\n * @returns The NFT in the V1 schema.\n */\nexport function mapOpenSeaNftV2ToV1(nft: OpenSeaV2Nft): ApiNft {\n return {\n token_id: nft.identifier,\n num_sales: null,\n background_color: null,\n image_url: nft.image_url ?? null,\n image_preview_url: null,\n image_thumbnail_url: null,\n image_original_url: null,\n animation_url: null,\n animation_original_url: null,\n name: nft.name,\n description: nft.description,\n external_link: null,\n asset_contract: {\n address: nft.contract,\n asset_contract_type: null,\n created_date: null,\n schema_name: nft.token_standard.toUpperCase(),\n symbol: null,\n total_supply: null,\n description: nft.description,\n external_link: null,\n collection: {\n name: nft.collection,\n image_url: null,\n },\n },\n creator: {\n user: { username: '' },\n profile_img_url: '',\n address: '',\n },\n last_sale: null,\n };\n}\n\n/**\n * Maps an OpenSea V2 detailed NFT to the V1 schema.\n * @param nft - The V2 detailed NFT to map.\n * @returns The NFT in the V1 schema.\n */\nexport function mapOpenSeaDetailedNftV2ToV1(nft: OpenSeaV2DetailedNft): ApiNft {\n const mapped = mapOpenSeaNftV2ToV1(nft);\n return {\n ...mapped,\n animation_url: nft.animation_url ?? null,\n creator: {\n ...mapped.creator,\n address: nft.creator,\n },\n };\n}\n\n/**\n * Maps an OpenSea V2 contract to the V1 schema.\n * @param contract - The v2 contract data.\n * @param collection - The v2 collection data.\n * @returns The contract in the v1 schema.\n */\nexport function mapOpenSeaContractV2ToV1(\n contract: OpenSeaV2Contract,\n collection?: OpenSeaV2Collection,\n): ApiNftContract {\n return {\n address: contract.address,\n asset_contract_type: null,\n created_date: null,\n schema_name: contract.contract_standard.toUpperCase(),\n symbol: null,\n total_supply: contract.supply?.toString(),\n description: collection?.description ?? null,\n external_link: collection?.project_url ?? null,\n collection: {\n name: collection?.name ?? contract.name,\n image_url: collection?.image_url,\n },\n };\n}\n"]} \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/index.d.ts b/node_modules/@metamask/assets-controllers/dist/index.d.ts index 9526321..5f08fce 100644 @@ -2537,7 +2620,7 @@ index 0000000..b91e096 \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/token-prices-service/codefi-v2.d.ts b/node_modules/@metamask/assets-controllers/dist/token-prices-service/codefi-v2.d.ts new file mode 100644 -index 0000000..0fa4154 +index 0000000..21a55e1 --- /dev/null +++ b/node_modules/@metamask/assets-controllers/dist/token-prices-service/codefi-v2.d.ts @@ -0,0 +1,80 @@ @@ -2558,7 +2641,7 @@ index 0000000..0fa4154 + * endpoint, but in hexadecimal form (for consistency with how we represent + * chain IDs in other places). + */ -+export declare const SUPPORTED_CHAIN_IDS: readonly ["0x1", "0xa", "0x19", "0x38", "0x39", "0x42", "0x46", "0x52", "0x58", "0x64", "0x6a", "0x7a", "0x80", "0x89", "0xfa", "0x120", "0x141", "0x144", "0x169", "0x440", "0x504", "0x505", "0x2105", "0x150", "0x2710", "0xa4b1", "0xa4ec", "0xa516", "0xa86a", "0x518af", "0x4e454152", "0x63564c40"]; ++export declare const SUPPORTED_CHAIN_IDS: readonly ["0x1", "0xa", "0x19", "0x38", "0x39", "0x42", "0x46", "0x52", "0x58", "0x64", "0x6a", "0x7a", "0x80", "0x89", "0xfa", "0x120", "0x141", "0x144", "0x169", "0x440", "0x504", "0x505", "0x2105", "0x150", "0x2710", "0xa4b1", "0xa4ec", "0xa516", "0xa86a", "0x518af", "0x4e454152", "0x63564c40", "0xe708"]; +/** + * A chain ID that can be supplied in the URL for the `/spot-prices` endpoint, + * but in hexadecimal form (for consistency with how we represent chain IDs in @@ -2624,15 +2707,15 @@ index 0000000..0fa4154 \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/token-prices-service/codefi-v2.d.ts.map b/node_modules/@metamask/assets-controllers/dist/token-prices-service/codefi-v2.d.ts.map new file mode 100644 -index 0000000..b07b8c0 +index 0000000..aab8b26 --- /dev/null +++ b/node_modules/@metamask/assets-controllers/dist/token-prices-service/codefi-v2.d.ts.map @@ -0,0 +1 @@ -+{"version":3,"file":"codefi-v2.d.ts","sourceRoot":"","sources":["../../src/token-prices-service/codefi-v2.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAY3C,OAAO,KAAK,EACV,0BAA0B,EAE1B,yBAAyB,EAC1B,MAAM,iCAAiC,CAAC;AAUzC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,ybA2HvB,CAAC;AAEX;;;GAGG;AACH,aAAK,iBAAiB,GAClB,OAAO,oBAAoB,CAAC,MAAM,CAAC,GACnC,SAAS,CAAC,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,4SAiEtB,CAAC;AACX;;;;GAIG;AACH,aAAK,gBAAgB,GAAG,OAAO,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAY3D;;;GAGG;AACH,qBAAa,0BACX,YACE,0BAA0B,CAAC,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,CAAC;;IAItE;;;;;;;;;OASG;gBACS,EACV,OAAqC,EACrC,0BAAyE,EACzE,oBAAqC,GACtC,GAAE;QACD,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,0BAA0B,CAAC,EAAE,MAAM,CAAC;QACpC,oBAAoB,CAAC,EAAE,MAAM,CAAC;KAC1B;IAcN;;;;;;;;;OASG;IACG,gBAAgB,CAAC,EACrB,OAAO,EACP,cAAc,EACd,QAAQ,GACT,EAAE;QACD,OAAO,EAAE,gBAAgB,CAAC;QAC1B,cAAc,EAAE,GAAG,EAAE,CAAC;QACtB,QAAQ,EAAE,iBAAiB,CAAC;KAC7B,GAAG,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAoDvE;;;;;;OAMG;IACH,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,gBAAgB;IAKvE;;;;;;;OAOG;IACH,yBAAyB,CAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,IAAI,iBAAiB;CAO5E"} ++{"version":3,"file":"codefi-v2.d.ts","sourceRoot":"","sources":["../../src/token-prices-service/codefi-v2.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAY3C,OAAO,KAAK,EACV,0BAA0B,EAE1B,yBAAyB,EAC1B,MAAM,iCAAiC,CAAC;AAUzC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,ybA2HvB,CAAC;AAEX;;;GAGG;AACH,aAAK,iBAAiB,GAClB,OAAO,oBAAoB,CAAC,MAAM,CAAC,GACnC,SAAS,CAAC,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,sTAmEtB,CAAC;AACX;;;;GAIG;AACH,aAAK,gBAAgB,GAAG,OAAO,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAY3D;;;GAGG;AACH,qBAAa,0BACX,YACE,0BAA0B,CAAC,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,CAAC;;IAItE;;;;;;;;;OASG;gBACS,EACV,OAAqC,EACrC,0BAAyE,EACzE,oBAAqC,GACtC,GAAE;QACD,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,0BAA0B,CAAC,EAAE,MAAM,CAAC;QACpC,oBAAoB,CAAC,EAAE,MAAM,CAAC;KAC1B;IAcN;;;;;;;;;OASG;IACG,gBAAgB,CAAC,EACrB,OAAO,EACP,cAAc,EACd,QAAQ,GACT,EAAE;QACD,OAAO,EAAE,gBAAgB,CAAC;QAC1B,cAAc,EAAE,GAAG,EAAE,CAAC;QACtB,QAAQ,EAAE,iBAAiB,CAAC;KAC7B,GAAG,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAoDvE;;;;;;OAMG;IACH,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,gBAAgB;IAKvE;;;;;;;OAOG;IACH,yBAAyB,CAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,IAAI,iBAAiB;CAO5E"} \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/token-prices-service/codefi-v2.js b/node_modules/@metamask/assets-controllers/dist/token-prices-service/codefi-v2.js new file mode 100644 -index 0000000..2e07fa7 +index 0000000..cd10d7f --- /dev/null +++ b/node_modules/@metamask/assets-controllers/dist/token-prices-service/codefi-v2.js @@ -0,0 +1,331 @@ @@ -2862,7 +2945,7 @@ index 0000000..2e07fa7 + // Harmony Mainnet Shard 0 + '0x63564c40', + // Linea Mainnet -+ '0xe708' ++ '0xe708', +]; +/** + * All requests to V2 of the Price API start with this. @@ -2970,11 +3053,11 @@ index 0000000..2e07fa7 \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/token-prices-service/codefi-v2.js.map b/node_modules/@metamask/assets-controllers/dist/token-prices-service/codefi-v2.js.map new file mode 100644 -index 0000000..6622712 +index 0000000..591491a --- /dev/null +++ b/node_modules/@metamask/assets-controllers/dist/token-prices-service/codefi-v2.js.map @@ -0,0 +1 @@ -+{"version":3,"file":"codefi-v2.js","sourceRoot":"","sources":["../../src/token-prices-service/codefi-v2.ts"],"names":[],"mappings":"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","sourcesContent":["import { handleFetch } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { hexToNumber } from '@metamask/utils';\nimport {\n circuitBreaker,\n ConsecutiveBreaker,\n ExponentialBackoff,\n handleAll,\n type IPolicy,\n retry,\n wrap,\n} from 'cockatiel';\n\nimport type {\n AbstractTokenPricesService,\n TokenPrice,\n TokenPricesByTokenAddress,\n} from './abstract-token-prices-service';\n\n/**\n * The shape of the data that the /spot-prices endpoint returns.\n */\ntype SpotPricesEndpointData<\n TokenAddress extends Hex,\n Currency extends string,\n> = Record>;\n\n/**\n * The list of currencies that can be supplied as the `vsCurrency` parameter to\n * the `/spot-prices` endpoint, in lowercase form.\n */\nexport const SUPPORTED_CURRENCIES = [\n // Bitcoin\n 'btc',\n // Ether\n 'eth',\n // Litecoin\n 'ltc',\n // Bitcoin Cash\n 'bch',\n // Binance Coin\n 'bnb',\n // EOS\n 'eos',\n // XRP\n 'xrp',\n // Lumens\n 'xlm',\n // Chainlink\n 'link',\n // Polkadot\n 'dot',\n // Yearn.finance\n 'yfi',\n // US Dollar\n 'usd',\n // United Arab Emirates Dirham\n 'aed',\n // Argentine Peso\n 'ars',\n // Australian Dollar\n 'aud',\n // Bangladeshi Taka\n 'bdt',\n // Bahraini Dinar\n 'bhd',\n // Bermudian Dollar\n 'bmd',\n // Brazil Real\n 'brl',\n // Canadian Dollar\n 'cad',\n // Swiss Franc\n 'chf',\n // Chilean Peso\n 'clp',\n // Chinese Yuan\n 'cny',\n // Czech Koruna\n 'czk',\n // Danish Krone\n 'dkk',\n // Euro\n 'eur',\n // British Pound Sterling\n 'gbp',\n // Hong Kong Dollar\n 'hkd',\n // Hungarian Forint\n 'huf',\n // Indonesian Rupiah\n 'idr',\n // Israeli New Shekel\n 'ils',\n // Indian Rupee\n 'inr',\n // Japanese Yen\n 'jpy',\n // South Korean Won\n 'krw',\n // Kuwaiti Dinar\n 'kwd',\n // Sri Lankan Rupee\n 'lkr',\n // Burmese Kyat\n 'mmk',\n // Mexican Peso\n 'mxn',\n // Malaysian Ringgit\n 'myr',\n // Nigerian Naira\n 'ngn',\n // Norwegian Krone\n 'nok',\n // New Zealand Dollar\n 'nzd',\n // Philippine Peso\n 'php',\n // Pakistani Rupee\n 'pkr',\n // Polish Zloty\n 'pln',\n // Russian Ruble\n 'rub',\n // Saudi Riyal\n 'sar',\n // Swedish Krona\n 'sek',\n // Singapore Dollar\n 'sgd',\n // Thai Baht\n 'thb',\n // Turkish Lira\n 'try',\n // New Taiwan Dollar\n 'twd',\n // Ukrainian hryvnia\n 'uah',\n // Venezuelan bolívar fuerte\n 'vef',\n // Vietnamese đồng\n 'vnd',\n // South African Rand\n 'zar',\n // IMF Special Drawing Rights\n 'xdr',\n // Silver - Troy Ounce\n 'xag',\n // Gold - Troy Ounce\n 'xau',\n // Bits\n 'bits',\n // Satoshi\n 'sats',\n] as const;\n\n/**\n * A currency that can be supplied as the `vsCurrency` parameter to\n * the `/spot-prices` endpoint. Covers both uppercase and lowercase versions.\n */\ntype SupportedCurrency =\n | typeof SUPPORTED_CURRENCIES[number]\n | Uppercase;\n\n/**\n * The list of chain IDs that can be supplied in the URL for the `/spot-prices`\n * endpoint, but in hexadecimal form (for consistency with how we represent\n * chain IDs in other places).\n */\nexport const SUPPORTED_CHAIN_IDS = [\n // Ethereum Mainnet\n '0x1',\n // OP Mainnet\n '0xa',\n // Cronos Mainnet\n '0x19',\n // BNB Smart Chain Mainnet\n '0x38',\n // Syscoin Mainnet\n '0x39',\n // OKXChain Mainnet\n '0x42',\n // Hoo Smart Chain\n '0x46',\n // Meter Mainnet\n '0x52',\n // TomoChain\n '0x58',\n // Gnosis\n '0x64',\n // Velas EVM Mainnet\n '0x6a',\n // Fuse Mainnet\n '0x7a',\n // Huobi ECO Chain Mainnet\n '0x80',\n // Polygon Mainnet\n '0x89',\n // Fantom Opera\n '0xfa',\n // Boba Network\n '0x120',\n // KCC Mainnet\n '0x141',\n // zkSync Era Mainnet\n '0x144',\n // Theta Mainnet\n '0x169',\n // Metis Andromeda Mainnet\n '0x440',\n // Moonbeam\n '0x504',\n // Moonriver\n '0x505',\n // Base\n '0x2105',\n // Shiden\n '0x150',\n // Smart Bitcoin Cash\n '0x2710',\n // Arbitrum One\n '0xa4b1',\n // Celo Mainnet\n '0xa4ec',\n // Oasis Emerald\n '0xa516',\n // Avalanche C-Chain\n '0xa86a',\n // Polis Mainnet\n '0x518af',\n // Aurora Mainnet\n '0x4e454152',\n // Harmony Mainnet Shard 0\n '0x63564c40',\n] as const;\n/**\n * A chain ID that can be supplied in the URL for the `/spot-prices` endpoint,\n * but in hexadecimal form (for consistency with how we represent chain IDs in\n * other places).\n */\ntype SupportedChainId = typeof SUPPORTED_CHAIN_IDS[number];\n\n/**\n * All requests to V2 of the Price API start with this.\n */\nconst BASE_URL = 'https://price-api.metafi.codefi.network/v2';\n\nconst DEFAULT_TOKEN_PRICE_RETRIES = 3;\n// Each update attempt will result (1 + retries) calls if the server is down\nconst DEFAULT_TOKEN_PRICE_MAX_CONSECUTIVE_FAILURES =\n (1 + DEFAULT_TOKEN_PRICE_RETRIES) * 3;\n\n/**\n * This version of the token prices service uses V2 of the Codefi Price API to\n * fetch token prices.\n */\nexport class CodefiTokenPricesServiceV2\n implements\n AbstractTokenPricesService\n{\n #tokenPricePolicy: IPolicy;\n\n /**\n * Construct a Codefi Token Price Service.\n *\n * @param options - Constructor options\n * @param options.retries - Number of retry attempts for each token price update.\n * @param options.maximumConsecutiveFailures - The maximum number of consecutive failures\n * allowed before breaking the circuit and pausing further updates.\n * @param options.circuitBreakDuration - The amount of time to wait when the circuit breaks\n * from too many consecutive failures.\n */\n constructor({\n retries = DEFAULT_TOKEN_PRICE_RETRIES,\n maximumConsecutiveFailures = DEFAULT_TOKEN_PRICE_MAX_CONSECUTIVE_FAILURES,\n circuitBreakDuration = 30 * 60 * 1000,\n }: {\n retries?: number;\n maximumConsecutiveFailures?: number;\n circuitBreakDuration?: number;\n } = {}) {\n // Construct a policy that will retry each update, and halt further updates\n // for a certain period after too many consecutive failures.\n const retryPolicy = retry(handleAll, {\n maxAttempts: retries,\n backoff: new ExponentialBackoff(),\n });\n const circuitBreakerPolicy = circuitBreaker(handleAll, {\n halfOpenAfter: circuitBreakDuration,\n breaker: new ConsecutiveBreaker(maximumConsecutiveFailures),\n });\n this.#tokenPricePolicy = wrap(retryPolicy, circuitBreakerPolicy);\n }\n\n /**\n * Retrieves prices in the given currency for the tokens identified by the\n * given addresses which are expected to live on the given chain.\n *\n * @param args - The arguments to function.\n * @param args.chainId - An EIP-155 chain ID.\n * @param args.tokenAddresses - Addresses for tokens that live on the chain.\n * @param args.currency - The desired currency of the token prices.\n * @returns The prices for the requested tokens.\n */\n async fetchTokenPrices({\n chainId,\n tokenAddresses,\n currency,\n }: {\n chainId: SupportedChainId;\n tokenAddresses: Hex[];\n currency: SupportedCurrency;\n }): Promise>> {\n const chainIdAsNumber = hexToNumber(chainId);\n\n const url = new URL(`${BASE_URL}/chains/${chainIdAsNumber}/spot-prices`);\n url.searchParams.append('tokenAddresses', tokenAddresses.join(','));\n url.searchParams.append('vsCurrency', currency);\n\n const pricesByCurrencyByTokenAddress: SpotPricesEndpointData<\n Lowercase,\n Lowercase\n > = await this.#tokenPricePolicy.execute(() => handleFetch(url));\n\n return tokenAddresses.reduce(\n (\n obj: Partial>,\n tokenAddress,\n ) => {\n // The Price API lowercases both currency and token addresses, so we have\n // to keep track of them and make sure we return the original versions.\n const lowercasedTokenAddress =\n tokenAddress.toLowerCase() as Lowercase;\n const lowercasedCurrency =\n currency.toLowerCase() as Lowercase;\n\n const price =\n pricesByCurrencyByTokenAddress[lowercasedTokenAddress]?.[\n lowercasedCurrency\n ];\n\n if (!price) {\n // console error instead of throwing to not interrupt the fetching of other tokens in case just one fails\n console.error(\n `Could not find price for \"${tokenAddress}\" in \"${currency}\"`,\n );\n }\n\n const tokenPrice: TokenPrice = {\n tokenAddress,\n value: price,\n currency,\n };\n return {\n ...obj,\n ...(tokenPrice.value !== undefined\n ? { [tokenAddress]: tokenPrice }\n : {}),\n };\n },\n {},\n ) as Partial>;\n }\n\n /**\n * Type guard for whether the API can return token prices for the given chain\n * ID.\n *\n * @param chainId - The chain ID to check.\n * @returns True if the API supports the chain ID, false otherwise.\n */\n validateChainIdSupported(chainId: unknown): chainId is SupportedChainId {\n const supportedChainIds: readonly string[] = SUPPORTED_CHAIN_IDS;\n return typeof chainId === 'string' && supportedChainIds.includes(chainId);\n }\n\n /**\n * Type guard for whether the API can return token prices in the given\n * currency.\n *\n * @param currency - The currency to check. If a string, can be either\n * lowercase or uppercase.\n * @returns True if the API supports the currency, false otherwise.\n */\n validateCurrencySupported(currency: unknown): currency is SupportedCurrency {\n const supportedCurrencies: readonly string[] = SUPPORTED_CURRENCIES;\n return (\n typeof currency === 'string' &&\n supportedCurrencies.includes(currency.toLowerCase())\n );\n }\n}\n"]} ++{"version":3,"file":"codefi-v2.js","sourceRoot":"","sources":["../../src/token-prices-service/codefi-v2.ts"],"names":[],"mappings":"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","sourcesContent":["import { handleFetch } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { hexToNumber } from '@metamask/utils';\nimport {\n circuitBreaker,\n ConsecutiveBreaker,\n ExponentialBackoff,\n handleAll,\n type IPolicy,\n retry,\n wrap,\n} from 'cockatiel';\n\nimport type {\n AbstractTokenPricesService,\n TokenPrice,\n TokenPricesByTokenAddress,\n} from './abstract-token-prices-service';\n\n/**\n * The shape of the data that the /spot-prices endpoint returns.\n */\ntype SpotPricesEndpointData<\n TokenAddress extends Hex,\n Currency extends string,\n> = Record>;\n\n/**\n * The list of currencies that can be supplied as the `vsCurrency` parameter to\n * the `/spot-prices` endpoint, in lowercase form.\n */\nexport const SUPPORTED_CURRENCIES = [\n // Bitcoin\n 'btc',\n // Ether\n 'eth',\n // Litecoin\n 'ltc',\n // Bitcoin Cash\n 'bch',\n // Binance Coin\n 'bnb',\n // EOS\n 'eos',\n // XRP\n 'xrp',\n // Lumens\n 'xlm',\n // Chainlink\n 'link',\n // Polkadot\n 'dot',\n // Yearn.finance\n 'yfi',\n // US Dollar\n 'usd',\n // United Arab Emirates Dirham\n 'aed',\n // Argentine Peso\n 'ars',\n // Australian Dollar\n 'aud',\n // Bangladeshi Taka\n 'bdt',\n // Bahraini Dinar\n 'bhd',\n // Bermudian Dollar\n 'bmd',\n // Brazil Real\n 'brl',\n // Canadian Dollar\n 'cad',\n // Swiss Franc\n 'chf',\n // Chilean Peso\n 'clp',\n // Chinese Yuan\n 'cny',\n // Czech Koruna\n 'czk',\n // Danish Krone\n 'dkk',\n // Euro\n 'eur',\n // British Pound Sterling\n 'gbp',\n // Hong Kong Dollar\n 'hkd',\n // Hungarian Forint\n 'huf',\n // Indonesian Rupiah\n 'idr',\n // Israeli New Shekel\n 'ils',\n // Indian Rupee\n 'inr',\n // Japanese Yen\n 'jpy',\n // South Korean Won\n 'krw',\n // Kuwaiti Dinar\n 'kwd',\n // Sri Lankan Rupee\n 'lkr',\n // Burmese Kyat\n 'mmk',\n // Mexican Peso\n 'mxn',\n // Malaysian Ringgit\n 'myr',\n // Nigerian Naira\n 'ngn',\n // Norwegian Krone\n 'nok',\n // New Zealand Dollar\n 'nzd',\n // Philippine Peso\n 'php',\n // Pakistani Rupee\n 'pkr',\n // Polish Zloty\n 'pln',\n // Russian Ruble\n 'rub',\n // Saudi Riyal\n 'sar',\n // Swedish Krona\n 'sek',\n // Singapore Dollar\n 'sgd',\n // Thai Baht\n 'thb',\n // Turkish Lira\n 'try',\n // New Taiwan Dollar\n 'twd',\n // Ukrainian hryvnia\n 'uah',\n // Venezuelan bolívar fuerte\n 'vef',\n // Vietnamese đồng\n 'vnd',\n // South African Rand\n 'zar',\n // IMF Special Drawing Rights\n 'xdr',\n // Silver - Troy Ounce\n 'xag',\n // Gold - Troy Ounce\n 'xau',\n // Bits\n 'bits',\n // Satoshi\n 'sats',\n] as const;\n\n/**\n * A currency that can be supplied as the `vsCurrency` parameter to\n * the `/spot-prices` endpoint. Covers both uppercase and lowercase versions.\n */\ntype SupportedCurrency =\n | typeof SUPPORTED_CURRENCIES[number]\n | Uppercase;\n\n/**\n * The list of chain IDs that can be supplied in the URL for the `/spot-prices`\n * endpoint, but in hexadecimal form (for consistency with how we represent\n * chain IDs in other places).\n */\nexport const SUPPORTED_CHAIN_IDS = [\n // Ethereum Mainnet\n '0x1',\n // OP Mainnet\n '0xa',\n // Cronos Mainnet\n '0x19',\n // BNB Smart Chain Mainnet\n '0x38',\n // Syscoin Mainnet\n '0x39',\n // OKXChain Mainnet\n '0x42',\n // Hoo Smart Chain\n '0x46',\n // Meter Mainnet\n '0x52',\n // TomoChain\n '0x58',\n // Gnosis\n '0x64',\n // Velas EVM Mainnet\n '0x6a',\n // Fuse Mainnet\n '0x7a',\n // Huobi ECO Chain Mainnet\n '0x80',\n // Polygon Mainnet\n '0x89',\n // Fantom Opera\n '0xfa',\n // Boba Network\n '0x120',\n // KCC Mainnet\n '0x141',\n // zkSync Era Mainnet\n '0x144',\n // Theta Mainnet\n '0x169',\n // Metis Andromeda Mainnet\n '0x440',\n // Moonbeam\n '0x504',\n // Moonriver\n '0x505',\n // Base\n '0x2105',\n // Shiden\n '0x150',\n // Smart Bitcoin Cash\n '0x2710',\n // Arbitrum One\n '0xa4b1',\n // Celo Mainnet\n '0xa4ec',\n // Oasis Emerald\n '0xa516',\n // Avalanche C-Chain\n '0xa86a',\n // Polis Mainnet\n '0x518af',\n // Aurora Mainnet\n '0x4e454152',\n // Harmony Mainnet Shard 0\n '0x63564c40',\n // Linea Mainnet\n '0xe708',\n] as const;\n/**\n * A chain ID that can be supplied in the URL for the `/spot-prices` endpoint,\n * but in hexadecimal form (for consistency with how we represent chain IDs in\n * other places).\n */\ntype SupportedChainId = typeof SUPPORTED_CHAIN_IDS[number];\n\n/**\n * All requests to V2 of the Price API start with this.\n */\nconst BASE_URL = 'https://price-api.metafi.codefi.network/v2';\n\nconst DEFAULT_TOKEN_PRICE_RETRIES = 3;\n// Each update attempt will result (1 + retries) calls if the server is down\nconst DEFAULT_TOKEN_PRICE_MAX_CONSECUTIVE_FAILURES =\n (1 + DEFAULT_TOKEN_PRICE_RETRIES) * 3;\n\n/**\n * This version of the token prices service uses V2 of the Codefi Price API to\n * fetch token prices.\n */\nexport class CodefiTokenPricesServiceV2\n implements\n AbstractTokenPricesService\n{\n #tokenPricePolicy: IPolicy;\n\n /**\n * Construct a Codefi Token Price Service.\n *\n * @param options - Constructor options\n * @param options.retries - Number of retry attempts for each token price update.\n * @param options.maximumConsecutiveFailures - The maximum number of consecutive failures\n * allowed before breaking the circuit and pausing further updates.\n * @param options.circuitBreakDuration - The amount of time to wait when the circuit breaks\n * from too many consecutive failures.\n */\n constructor({\n retries = DEFAULT_TOKEN_PRICE_RETRIES,\n maximumConsecutiveFailures = DEFAULT_TOKEN_PRICE_MAX_CONSECUTIVE_FAILURES,\n circuitBreakDuration = 30 * 60 * 1000,\n }: {\n retries?: number;\n maximumConsecutiveFailures?: number;\n circuitBreakDuration?: number;\n } = {}) {\n // Construct a policy that will retry each update, and halt further updates\n // for a certain period after too many consecutive failures.\n const retryPolicy = retry(handleAll, {\n maxAttempts: retries,\n backoff: new ExponentialBackoff(),\n });\n const circuitBreakerPolicy = circuitBreaker(handleAll, {\n halfOpenAfter: circuitBreakDuration,\n breaker: new ConsecutiveBreaker(maximumConsecutiveFailures),\n });\n this.#tokenPricePolicy = wrap(retryPolicy, circuitBreakerPolicy);\n }\n\n /**\n * Retrieves prices in the given currency for the tokens identified by the\n * given addresses which are expected to live on the given chain.\n *\n * @param args - The arguments to function.\n * @param args.chainId - An EIP-155 chain ID.\n * @param args.tokenAddresses - Addresses for tokens that live on the chain.\n * @param args.currency - The desired currency of the token prices.\n * @returns The prices for the requested tokens.\n */\n async fetchTokenPrices({\n chainId,\n tokenAddresses,\n currency,\n }: {\n chainId: SupportedChainId;\n tokenAddresses: Hex[];\n currency: SupportedCurrency;\n }): Promise>> {\n const chainIdAsNumber = hexToNumber(chainId);\n\n const url = new URL(`${BASE_URL}/chains/${chainIdAsNumber}/spot-prices`);\n url.searchParams.append('tokenAddresses', tokenAddresses.join(','));\n url.searchParams.append('vsCurrency', currency);\n\n const pricesByCurrencyByTokenAddress: SpotPricesEndpointData<\n Lowercase,\n Lowercase\n > = await this.#tokenPricePolicy.execute(() => handleFetch(url));\n\n return tokenAddresses.reduce(\n (\n obj: Partial>,\n tokenAddress,\n ) => {\n // The Price API lowercases both currency and token addresses, so we have\n // to keep track of them and make sure we return the original versions.\n const lowercasedTokenAddress =\n tokenAddress.toLowerCase() as Lowercase;\n const lowercasedCurrency =\n currency.toLowerCase() as Lowercase;\n\n const price =\n pricesByCurrencyByTokenAddress[lowercasedTokenAddress]?.[\n lowercasedCurrency\n ];\n\n if (!price) {\n // console error instead of throwing to not interrupt the fetching of other tokens in case just one fails\n console.error(\n `Could not find price for \"${tokenAddress}\" in \"${currency}\"`,\n );\n }\n\n const tokenPrice: TokenPrice = {\n tokenAddress,\n value: price,\n currency,\n };\n return {\n ...obj,\n ...(tokenPrice.value !== undefined\n ? { [tokenAddress]: tokenPrice }\n : {}),\n };\n },\n {},\n ) as Partial>;\n }\n\n /**\n * Type guard for whether the API can return token prices for the given chain\n * ID.\n *\n * @param chainId - The chain ID to check.\n * @returns True if the API supports the chain ID, false otherwise.\n */\n validateChainIdSupported(chainId: unknown): chainId is SupportedChainId {\n const supportedChainIds: readonly string[] = SUPPORTED_CHAIN_IDS;\n return typeof chainId === 'string' && supportedChainIds.includes(chainId);\n }\n\n /**\n * Type guard for whether the API can return token prices in the given\n * currency.\n *\n * @param currency - The currency to check. If a string, can be either\n * lowercase or uppercase.\n * @returns True if the API supports the currency, false otherwise.\n */\n validateCurrencySupported(currency: unknown): currency is SupportedCurrency {\n const supportedCurrencies: readonly string[] = SUPPORTED_CURRENCIES;\n return (\n typeof currency === 'string' &&\n supportedCurrencies.includes(currency.toLowerCase())\n );\n }\n}\n"]} \ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/token-prices-service/index.d.ts b/node_modules/@metamask/assets-controllers/dist/token-prices-service/index.d.ts new file mode 100644