@metamask/assets-controllers 15.0.0 → 16.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -1
- package/dist/AssetsContractController.d.ts.map +1 -1
- package/dist/AssetsContractController.js +2 -0
- package/dist/AssetsContractController.js.map +1 -1
- package/dist/NftController.d.ts.map +1 -1
- package/dist/NftController.js +11 -0
- package/dist/NftController.js.map +1 -1
- package/dist/TokenListController.d.ts +12 -10
- package/dist/TokenListController.d.ts.map +1 -1
- package/dist/TokenListController.js +42 -29
- package/dist/TokenListController.js.map +1 -1
- package/dist/assetsUtil.d.ts +3 -1
- package/dist/assetsUtil.d.ts.map +1 -1
- package/dist/assetsUtil.js +2 -0
- package/dist/assetsUtil.js.map +1 -1
- package/dist/token-service.d.ts +1 -1
- package/dist/token-service.d.ts.map +1 -1
- package/dist/token-service.js +3 -3
- package/dist/token-service.js.map +1 -1
- package/package.json +9 -8
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [16.0.0]
|
|
10
|
+
### Added
|
|
11
|
+
- Add way to start and stop different polling sessions for the same network client ID by providing extra scoping data ([#1776](https://github.com/MetaMask/core/pull/1776))
|
|
12
|
+
- Add optional second argument to `stopPollingByPollingToken` (formerly `stopPollingByNetworkClientId`)
|
|
13
|
+
- Add optional second argument to `onPollingCompleteByNetworkClientId`
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- **BREAKING:** Bump dependency and peer dependency on `@metamask/network-controller` to ^15.0.0
|
|
17
|
+
- **BREAKING:** Make `executePoll` in TokenListController private ([#1810](https://github.com/MetaMask/core/pull/1810))
|
|
18
|
+
- **BREAKING:** Update TokenListController to rename `stopPollingByNetworkClientId` to `stopPollingByPollingToken` ([#1810](https://github.com/MetaMask/core/pull/1810))
|
|
19
|
+
- Add missing dependency on `@metamask/polling-controller` ([#1831](https://github.com/MetaMask/core/pull/1831))
|
|
20
|
+
- Bump dependency and peer dependency on `@metamask/approval-controller` to ^4.0.1
|
|
21
|
+
- Bump dependency and peer dependency on `@metamask/preferences-controller` to ^4.4.3
|
|
22
|
+
|
|
9
23
|
## [15.0.0]
|
|
10
24
|
### Changed
|
|
11
25
|
- **BREAKING**: `NftController` now expects `getNetworkClientById` in constructor options ([#1698](https://github.com/MetaMask/core/pull/1698))
|
|
@@ -320,7 +334,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
320
334
|
### Changed
|
|
321
335
|
- Use Ethers for AssetsContractController ([#845](https://github.com/MetaMask/core/pull/845))
|
|
322
336
|
|
|
323
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@
|
|
337
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@16.0.0...HEAD
|
|
338
|
+
[16.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@15.0.0...@metamask/assets-controllers@16.0.0
|
|
324
339
|
[15.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@14.0.0...@metamask/assets-controllers@15.0.0
|
|
325
340
|
[14.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@13.0.0...@metamask/assets-controllers@14.0.0
|
|
326
341
|
[13.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@12.0.0...@metamask/assets-controllers@13.0.0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetsContractController.d.ts","sourceRoot":"","sources":["../src/AssetsContractController.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,iBAAiB,EAClB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAI1C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,kDAAkD,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,gDAAgD,CAAC;AAEhF;;;;;GAKG;AACH,eAAO,MAAM,uCAAuC,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"AssetsContractController.d.ts","sourceRoot":"","sources":["../src/AssetsContractController.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,6 +34,8 @@ exports.SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID = {
|
|
|
34
34
|
[assetsUtil_1.SupportedTokenDetectionNetworks.polygon]: '0x2352c63A83f9Fd126af8676146721Fa00924d7e4',
|
|
35
35
|
[assetsUtil_1.SupportedTokenDetectionNetworks.avax]: '0xD023D153a0DFa485130ECFdE2FAA7e612EF94818',
|
|
36
36
|
[assetsUtil_1.SupportedTokenDetectionNetworks.aurora]: '0x1286415D333855237f89Df27D388127181448538',
|
|
37
|
+
[assetsUtil_1.SupportedTokenDetectionNetworks.linea_goerli]: '0x10dAd7Ca3921471f616db788D9300DC97Db01783',
|
|
38
|
+
[assetsUtil_1.SupportedTokenDetectionNetworks.linea_mainnet]: '0xF62e6a41561b3650a69Bb03199C735e3E3328c0D',
|
|
37
39
|
};
|
|
38
40
|
exports.MISSING_PROVIDER_ERROR = 'AssetsContractController failed to set the provider correctly. A provider must be set for this method to be available';
|
|
39
41
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetsContractController.js","sourceRoot":"","sources":["../src/AssetsContractController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport type { BaseConfig, BaseState } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { IPFS_DEFAULT_GATEWAY_URL } from '@metamask/controller-utils';\nimport type {\n NetworkClientId,\n NetworkState,\n NetworkController,\n} from '@metamask/network-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport type { Hex } from '@metamask/utils';\nimport type { BN } from 'ethereumjs-util';\nimport abiSingleCallBalancesContract from 'single-call-balance-checker-abi';\n\nimport { SupportedTokenDetectionNetworks } from './assetsUtil';\nimport { ERC20Standard } from './Standards/ERC20Standard';\nimport { ERC1155Standard } from './Standards/NftStandards/ERC1155/ERC1155Standard';\nimport { ERC721Standard } from './Standards/NftStandards/ERC721/ERC721Standard';\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 const SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID: Record<Hex, string> = {\n [SupportedTokenDetectionNetworks.mainnet]:\n '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39',\n [SupportedTokenDetectionNetworks.bsc]:\n '0x2352c63A83f9Fd126af8676146721Fa00924d7e4',\n [SupportedTokenDetectionNetworks.polygon]:\n '0x2352c63A83f9Fd126af8676146721Fa00924d7e4',\n [SupportedTokenDetectionNetworks.avax]:\n '0xD023D153a0DFa485130ECFdE2FAA7e612EF94818',\n [SupportedTokenDetectionNetworks.aurora]:\n '0x1286415D333855237f89Df27D388127181448538',\n};\n\nexport const MISSING_PROVIDER_ERROR =\n 'AssetsContractController failed to set the provider correctly. A provider must be set for this method to be available';\n\n/**\n * @type AssetsContractConfig\n *\n * Assets Contract controller configuration\n * @property provider - Provider used to create a new web3 instance\n */\nexport interface AssetsContractConfig extends BaseConfig {\n provider: any;\n ipfsGateway: string;\n chainId: Hex;\n}\n\n/**\n * @type BalanceMap\n *\n * Key value object containing the balance for each tokenAddress\n * @property [tokenAddress] - Address of the token\n */\nexport interface BalanceMap {\n [tokenAddress: string]: BN;\n}\n\n/**\n * Controller that interacts with contracts on mainnet through web3\n */\nexport class AssetsContractController extends BaseController<\n AssetsContractConfig,\n BaseState\n> {\n private _provider?: any;\n\n /**\n * Name of this controller used during composition\n */\n override name = 'AssetsContractController';\n\n private readonly getNetworkClientById: NetworkController['getNetworkClientById'];\n\n /**\n * Creates a AssetsContractController 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.getNetworkClientById - Gets the network client with the given id from the NetworkController.\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 getNetworkClientById,\n }: {\n chainId: Hex;\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n getNetworkClientById: NetworkController['getNetworkClientById'];\n },\n config?: Partial<AssetsContractConfig>,\n state?: Partial<BaseState>,\n ) {\n super(config, state);\n this.defaultConfig = {\n provider: undefined,\n ipfsGateway: IPFS_DEFAULT_GATEWAY_URL,\n chainId: initialChainId,\n };\n this.initialize();\n this.getNetworkClientById = getNetworkClientById;\n\n onPreferencesStateChange(({ ipfsGateway }) => {\n this.configure({ ipfsGateway });\n });\n\n onNetworkStateChange((networkState) => {\n if (this.config.chainId !== networkState.providerConfig.chainId) {\n this.configure({\n chainId: networkState.providerConfig.chainId,\n });\n }\n });\n }\n\n /**\n * Sets a new provider.\n *\n * TODO: Replace this wth a method.\n *\n * @property provider - Provider used to create a new underlying Web3 instance\n */\n set provider(provider: any) {\n this._provider = provider;\n }\n\n get provider() {\n throw new Error('Property only used for setting');\n }\n\n /**\n * Get the relevant provider instance.\n *\n * @param networkClientId - Network Client ID.\n * @returns Web3Provider instance.\n */\n getProvider(networkClientId?: NetworkClientId): Web3Provider {\n const provider = networkClientId\n ? this.getNetworkClientById(networkClientId).provider\n : this._provider;\n\n if (provider === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n\n return new Web3Provider(provider);\n }\n\n /**\n * Get the relevant chain ID.\n *\n * @param networkClientId - Network Client ID used to get the provider.\n * @returns Hex chain ID.\n */\n getChainId(networkClientId?: NetworkClientId): Hex {\n return networkClientId\n ? this.getNetworkClientById(networkClientId).configuration.chainId\n : this.config.chainId;\n }\n\n /**\n * Get a ERC20Standard instance using the relevant provider instance.\n *\n * @param networkClientId - Network Client ID used to get the provider.\n * @returns ERC20Standard instance.\n */\n getERC20Standard(networkClientId?: NetworkClientId): ERC20Standard {\n const provider = this.getProvider(networkClientId);\n return new ERC20Standard(provider);\n }\n\n /**\n * Get a ERC721Standard instance using the relevant provider instance.\n *\n * @param networkClientId - Network Client ID used to get the provider.\n * @returns ERC721Standard instance.\n */\n getERC721Standard(networkClientId?: NetworkClientId): ERC721Standard {\n const provider = this.getProvider(networkClientId);\n return new ERC721Standard(provider);\n }\n\n /**\n * Get a ERC1155Standard instance using the relevant provider instance.\n *\n * @param networkClientId - Network Client ID used to get the provider.\n * @returns ERC1155Standard instance.\n */\n getERC1155Standard(networkClientId?: NetworkClientId): ERC1155Standard {\n const provider = this.getProvider(networkClientId);\n return new ERC1155Standard(provider);\n }\n\n /**\n * Get balance or count for current account on specific asset contract.\n *\n * @param address - Asset ERC20 contract address.\n * @param selectedAddress - Current account public address.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to BN object containing balance for current account on specific asset contract.\n */\n async getERC20BalanceOf(\n address: string,\n selectedAddress: string,\n networkClientId?: NetworkClientId,\n ): Promise<BN> {\n const erc20Standard = this.getERC20Standard(networkClientId);\n return erc20Standard.getBalanceOf(address, selectedAddress);\n }\n\n /**\n * Query for the decimals for a given ERC20 asset.\n *\n * @param address - ERC20 asset contract address.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'decimals'.\n */\n async getERC20TokenDecimals(\n address: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc20Standard = this.getERC20Standard(networkClientId);\n return erc20Standard.getTokenDecimals(address);\n }\n\n /**\n * Query for the name for a given ERC20 asset.\n *\n * @param address - ERC20 asset contract address.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'decimals'.\n */\n async getERC20TokenName(\n address: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc20Standard = this.getERC20Standard(networkClientId);\n return erc20Standard.getTokenName(address);\n }\n\n /**\n * Enumerate assets assigned to an owner.\n *\n * @param address - ERC721 asset contract address.\n * @param selectedAddress - Current account public address.\n * @param index - An NFT counter less than `balanceOf(selectedAddress)`.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to token identifier for the 'index'th asset assigned to 'selectedAddress'.\n */\n getERC721NftTokenId(\n address: string,\n selectedAddress: string,\n index: number,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc721Standard = this.getERC721Standard(networkClientId);\n return erc721Standard.getNftTokenId(address, selectedAddress, index);\n }\n\n /**\n * Enumerate assets assigned to an owner.\n *\n * @param tokenAddress - ERC721 asset contract address.\n * @param userAddress - Current account public address.\n * @param tokenId - ERC721 asset identifier.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to an object containing the token standard and a set of details which depend on which standard the token supports.\n */\n async getTokenStandardAndDetails(\n tokenAddress: string,\n userAddress?: string,\n tokenId?: string,\n networkClientId?: NetworkClientId,\n ): Promise<{\n standard: string;\n tokenURI?: string | undefined;\n symbol?: string | undefined;\n name?: string | undefined;\n decimals?: string | undefined;\n balance?: BN | undefined;\n }> {\n // Asserts provider is available\n this.getProvider(networkClientId);\n\n const { ipfsGateway } = this.config;\n\n // ERC721\n try {\n const erc721Standard = this.getERC721Standard(networkClientId);\n return {\n ...(await erc721Standard.getDetails(\n tokenAddress,\n ipfsGateway,\n tokenId,\n )),\n };\n } catch {\n // Ignore\n }\n\n // ERC1155\n try {\n const erc1155Standard = this.getERC1155Standard(networkClientId);\n return {\n ...(await erc1155Standard.getDetails(\n tokenAddress,\n ipfsGateway,\n tokenId,\n )),\n };\n } catch {\n // Ignore\n }\n\n // ERC20\n try {\n const erc20Standard = this.getERC20Standard(networkClientId);\n return {\n ...(await erc20Standard.getDetails(tokenAddress, userAddress)),\n };\n } catch {\n // Ignore\n }\n\n throw new Error('Unable to determine contract standard');\n }\n\n /**\n * Query for tokenURI for a given ERC721 asset.\n *\n * @param address - ERC721 asset contract address.\n * @param tokenId - ERC721 asset identifier.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'tokenURI'.\n */\n async getERC721TokenURI(\n address: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc721Standard = this.getERC721Standard(networkClientId);\n return erc721Standard.getTokenURI(address, tokenId);\n }\n\n /**\n * Query for name for a given asset.\n *\n * @param address - ERC721 or ERC20 asset contract address.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'name'.\n */\n async getERC721AssetName(\n address: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc721Standard = this.getERC721Standard(networkClientId);\n return erc721Standard.getAssetName(address);\n }\n\n /**\n * Query for symbol for a given asset.\n *\n * @param address - ERC721 or ERC20 asset contract address.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'symbol'.\n */\n async getERC721AssetSymbol(\n address: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc721Standard = this.getERC721Standard(networkClientId);\n return erc721Standard.getAssetSymbol(address);\n }\n\n /**\n * Query for owner for a given ERC721 asset.\n *\n * @param address - ERC721 asset contract address.\n * @param tokenId - ERC721 asset identifier.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the owner address.\n */\n async getERC721OwnerOf(\n address: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc721Standard = this.getERC721Standard(networkClientId);\n return erc721Standard.getOwnerOf(address, tokenId);\n }\n\n /**\n * Query for tokenURI for a given asset.\n *\n * @param address - ERC1155 asset contract address.\n * @param tokenId - ERC1155 asset identifier.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'tokenURI'.\n */\n async getERC1155TokenURI(\n address: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc1155Standard = this.getERC1155Standard(networkClientId);\n return erc1155Standard.getTokenURI(address, tokenId);\n }\n\n /**\n * Query for balance of a given ERC 1155 token.\n *\n * @param userAddress - Wallet public address.\n * @param nftAddress - ERC1155 asset contract address.\n * @param nftId - ERC1155 asset identifier.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'balanceOf'.\n */\n async getERC1155BalanceOf(\n userAddress: string,\n nftAddress: string,\n nftId: string,\n networkClientId?: NetworkClientId,\n ): Promise<BN> {\n const erc1155Standard = this.getERC1155Standard(networkClientId);\n return erc1155Standard.getBalanceOf(nftAddress, userAddress, nftId);\n }\n\n /**\n * Transfer single ERC1155 token.\n *\n * @param nftAddress - ERC1155 token address.\n * @param senderAddress - ERC1155 token sender.\n * @param recipientAddress - ERC1155 token recipient.\n * @param nftId - ERC1155 token id.\n * @param qty - Quantity of tokens to be sent.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'transferSingle' ERC1155 token.\n */\n async transferSingleERC1155(\n nftAddress: string,\n senderAddress: string,\n recipientAddress: string,\n nftId: string,\n qty: string,\n networkClientId?: NetworkClientId,\n ): Promise<void> {\n const erc1155Standard = this.getERC1155Standard(networkClientId);\n return erc1155Standard.transferSingle(\n nftAddress,\n senderAddress,\n recipientAddress,\n nftId,\n qty,\n );\n }\n\n /**\n * Get the token balance for a list of token addresses in a single call. Only non-zero balances\n * are returned.\n *\n * @param selectedAddress - The address to check token balances for.\n * @param tokensToDetect - The token addresses to detect balances for.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns The list of non-zero token balances.\n */\n async getBalancesInSingleCall(\n selectedAddress: string,\n tokensToDetect: string[],\n networkClientId?: NetworkClientId,\n ) {\n const chainId = this.getChainId(networkClientId);\n const provider = this.getProvider(networkClientId);\n if (!(chainId in SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID)) {\n // Only fetch balance if contract address exists\n return {};\n }\n const contractAddress = SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID[chainId];\n\n const contract = new Contract(\n contractAddress,\n abiSingleCallBalancesContract,\n provider,\n );\n const result = await contract.balances([selectedAddress], tokensToDetect);\n const nonZeroBalances: BalanceMap = {};\n /* istanbul ignore else */\n if (result.length > 0) {\n tokensToDetect.forEach((tokenAddress, index) => {\n const balance: BN = result[index];\n /* istanbul ignore else */\n if (String(balance) !== '0') {\n nonZeroBalances[tokenAddress] = balance;\n }\n });\n }\n return nonZeroBalances;\n }\n}\n\nexport default AssetsContractController;\n"]}
|
|
1
|
+
{"version":3,"file":"AssetsContractController.js","sourceRoot":"","sources":["../src/AssetsContractController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,wDAAoD;AACpD,wDAAwD;AAExD,+DAA2D;AAC3D,iEAAsE;AAStE,sGAA4E;AAE5E,6CAA+D;AAC/D,6DAA0D;AAC1D,sFAAmF;AACnF,mFAAgF;AAEhF;;;;;GAKG;AACU,QAAA,uCAAuC,GAAwB;IAC1E,CAAC,4CAA+B,CAAC,OAAO,CAAC,EACvC,4CAA4C;IAC9C,CAAC,4CAA+B,CAAC,GAAG,CAAC,EACnC,4CAA4C;IAC9C,CAAC,4CAA+B,CAAC,OAAO,CAAC,EACvC,4CAA4C;IAC9C,CAAC,4CAA+B,CAAC,IAAI,CAAC,EACpC,4CAA4C;IAC9C,CAAC,4CAA+B,CAAC,MAAM,CAAC,EACtC,4CAA4C;IAC9C,CAAC,4CAA+B,CAAC,YAAY,CAAC,EAC5C,4CAA4C;IAC9C,CAAC,4CAA+B,CAAC,aAAa,CAAC,EAC7C,4CAA4C;CAC/C,CAAC;AAEW,QAAA,sBAAsB,GACjC,uHAAuH,CAAC;AAwB1H;;GAEG;AACH,MAAa,wBAAyB,SAAQ,gCAG7C;IAUC;;;;;;;;;;OAUG;IACH,YACE,EACE,OAAO,EAAE,cAAc,EACvB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,GAUrB,EACD,MAAsC,EACtC,KAA0B;QAE1B,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QArCvB;;WAEG;QACM,SAAI,GAAG,0BAA0B,CAAC;QAmCzC,IAAI,CAAC,aAAa,GAAG;YACnB,QAAQ,EAAE,SAAS;YACnB,WAAW,EAAE,2CAAwB;YACrC,OAAO,EAAE,cAAc;SACxB,CAAC;QACF,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,oBAAoB,GAAG,oBAAoB,CAAC;QAEjD,wBAAwB,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE;YAC3C,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,oBAAoB,CAAC,CAAC,YAAY,EAAE,EAAE;YACpC,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,KAAK,YAAY,CAAC,cAAc,CAAC,OAAO,EAAE;gBAC/D,IAAI,CAAC,SAAS,CAAC;oBACb,OAAO,EAAE,YAAY,CAAC,cAAc,CAAC,OAAO;iBAC7C,CAAC,CAAC;aACJ;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,IAAI,QAAQ,CAAC,QAAa;QACxB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED,IAAI,QAAQ;QACV,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED;;;;;OAKG;IACH,WAAW,CAAC,eAAiC;QAC3C,MAAM,QAAQ,GAAG,eAAe;YAC9B,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC,QAAQ;YACrD,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;QAEnB,IAAI,QAAQ,KAAK,SAAS,EAAE;YAC1B,MAAM,IAAI,KAAK,CAAC,8BAAsB,CAAC,CAAC;SACzC;QAED,OAAO,IAAI,wBAAY,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,eAAiC;QAC1C,OAAO,eAAe;YACpB,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC,aAAa,CAAC,OAAO;YAClE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;IAC1B,CAAC;IAED;;;;;OAKG;IACH,gBAAgB,CAAC,eAAiC;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;QACnD,OAAO,IAAI,6BAAa,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED;;;;;OAKG;IACH,iBAAiB,CAAC,eAAiC;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;QACnD,OAAO,IAAI,+BAAc,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAED;;;;;OAKG;IACH,kBAAkB,CAAC,eAAiC;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;QACnD,OAAO,IAAI,iCAAe,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAED;;;;;;;OAOG;IACG,iBAAiB,CACrB,OAAe,EACf,eAAuB,EACvB,eAAiC;;YAEjC,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;YAC7D,OAAO,aAAa,CAAC,YAAY,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAC9D,CAAC;KAAA;IAED;;;;;;OAMG;IACG,qBAAqB,CACzB,OAAe,EACf,eAAiC;;YAEjC,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;YAC7D,OAAO,aAAa,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACjD,CAAC;KAAA;IAED;;;;;;OAMG;IACG,iBAAiB,CACrB,OAAe,EACf,eAAiC;;YAEjC,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;YAC7D,OAAO,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC7C,CAAC;KAAA;IAED;;;;;;;;OAQG;IACH,mBAAmB,CACjB,OAAe,EACf,eAAuB,EACvB,KAAa,EACb,eAAiC;QAEjC,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;QAC/D,OAAO,cAAc,CAAC,aAAa,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,CAAC,CAAC;IACvE,CAAC;IAED;;;;;;;;OAQG;IACG,0BAA0B,CAC9B,YAAoB,EACpB,WAAoB,EACpB,OAAgB,EAChB,eAAiC;;YASjC,gCAAgC;YAChC,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;YAElC,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;YAEpC,SAAS;YACT,IAAI;gBACF,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;gBAC/D,yBACK,CAAC,MAAM,cAAc,CAAC,UAAU,CACjC,YAAY,EACZ,WAAW,EACX,OAAO,CACR,CAAC,EACF;aACH;YAAC,WAAM;gBACN,SAAS;aACV;YAED,UAAU;YACV,IAAI;gBACF,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;gBACjE,yBACK,CAAC,MAAM,eAAe,CAAC,UAAU,CAClC,YAAY,EACZ,WAAW,EACX,OAAO,CACR,CAAC,EACF;aACH;YAAC,WAAM;gBACN,SAAS;aACV;YAED,QAAQ;YACR,IAAI;gBACF,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;gBAC7D,yBACK,CAAC,MAAM,aAAa,CAAC,UAAU,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,EAC9D;aACH;YAAC,WAAM;gBACN,SAAS;aACV;YAED,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;KAAA;IAED;;;;;;;OAOG;IACG,iBAAiB,CACrB,OAAe,EACf,OAAe,EACf,eAAiC;;YAEjC,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;YAC/D,OAAO,cAAc,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACtD,CAAC;KAAA;IAED;;;;;;OAMG;IACG,kBAAkB,CACtB,OAAe,EACf,eAAiC;;YAEjC,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;YAC/D,OAAO,cAAc,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC9C,CAAC;KAAA;IAED;;;;;;OAMG;IACG,oBAAoB,CACxB,OAAe,EACf,eAAiC;;YAEjC,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;YAC/D,OAAO,cAAc,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAChD,CAAC;KAAA;IAED;;;;;;;OAOG;IACG,gBAAgB,CACpB,OAAe,EACf,OAAe,EACf,eAAiC;;YAEjC,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;YAC/D,OAAO,cAAc,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACrD,CAAC;KAAA;IAED;;;;;;;OAOG;IACG,kBAAkB,CACtB,OAAe,EACf,OAAe,EACf,eAAiC;;YAEjC,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;YACjE,OAAO,eAAe,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACvD,CAAC;KAAA;IAED;;;;;;;;OAQG;IACG,mBAAmB,CACvB,WAAmB,EACnB,UAAkB,EAClB,KAAa,EACb,eAAiC;;YAEjC,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;YACjE,OAAO,eAAe,CAAC,YAAY,CAAC,UAAU,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;QACtE,CAAC;KAAA;IAED;;;;;;;;;;OAUG;IACG,qBAAqB,CACzB,UAAkB,EAClB,aAAqB,EACrB,gBAAwB,EACxB,KAAa,EACb,GAAW,EACX,eAAiC;;YAEjC,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;YACjE,OAAO,eAAe,CAAC,cAAc,CACnC,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,KAAK,EACL,GAAG,CACJ,CAAC;QACJ,CAAC;KAAA;IAED;;;;;;;;OAQG;IACG,uBAAuB,CAC3B,eAAuB,EACvB,cAAwB,EACxB,eAAiC;;YAEjC,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;YACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;YACnD,IAAI,CAAC,CAAC,OAAO,IAAI,+CAAuC,CAAC,EAAE;gBACzD,gDAAgD;gBAChD,OAAO,EAAE,CAAC;aACX;YACD,MAAM,eAAe,GAAG,+CAAuC,CAAC,OAAO,CAAC,CAAC;YAEzE,MAAM,QAAQ,GAAG,IAAI,oBAAQ,CAC3B,eAAe,EACf,yCAA6B,EAC7B,QAAQ,CACT,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,EAAE,cAAc,CAAC,CAAC;YAC1E,MAAM,eAAe,GAAe,EAAE,CAAC;YACvC,0BAA0B;YAC1B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;gBACrB,cAAc,CAAC,OAAO,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE,EAAE;oBAC7C,MAAM,OAAO,GAAO,MAAM,CAAC,KAAK,CAAC,CAAC;oBAClC,0BAA0B;oBAC1B,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE;wBAC3B,eAAe,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC;qBACzC;gBACH,CAAC,CAAC,CAAC;aACJ;YACD,OAAO,eAAe,CAAC;QACzB,CAAC;KAAA;CACF;AA/bD,4DA+bC;AAED,kBAAe,wBAAwB,CAAC","sourcesContent":["import { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport type { BaseConfig, BaseState } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { IPFS_DEFAULT_GATEWAY_URL } from '@metamask/controller-utils';\nimport type {\n NetworkClientId,\n NetworkState,\n NetworkController,\n} from '@metamask/network-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport type { Hex } from '@metamask/utils';\nimport type { BN } from 'ethereumjs-util';\nimport abiSingleCallBalancesContract from 'single-call-balance-checker-abi';\n\nimport { SupportedTokenDetectionNetworks } from './assetsUtil';\nimport { ERC20Standard } from './Standards/ERC20Standard';\nimport { ERC1155Standard } from './Standards/NftStandards/ERC1155/ERC1155Standard';\nimport { ERC721Standard } from './Standards/NftStandards/ERC721/ERC721Standard';\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 const SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID: Record<Hex, string> = {\n [SupportedTokenDetectionNetworks.mainnet]:\n '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39',\n [SupportedTokenDetectionNetworks.bsc]:\n '0x2352c63A83f9Fd126af8676146721Fa00924d7e4',\n [SupportedTokenDetectionNetworks.polygon]:\n '0x2352c63A83f9Fd126af8676146721Fa00924d7e4',\n [SupportedTokenDetectionNetworks.avax]:\n '0xD023D153a0DFa485130ECFdE2FAA7e612EF94818',\n [SupportedTokenDetectionNetworks.aurora]:\n '0x1286415D333855237f89Df27D388127181448538',\n [SupportedTokenDetectionNetworks.linea_goerli]:\n '0x10dAd7Ca3921471f616db788D9300DC97Db01783',\n [SupportedTokenDetectionNetworks.linea_mainnet]:\n '0xF62e6a41561b3650a69Bb03199C735e3E3328c0D',\n};\n\nexport const MISSING_PROVIDER_ERROR =\n 'AssetsContractController failed to set the provider correctly. A provider must be set for this method to be available';\n\n/**\n * @type AssetsContractConfig\n *\n * Assets Contract controller configuration\n * @property provider - Provider used to create a new web3 instance\n */\nexport interface AssetsContractConfig extends BaseConfig {\n provider: any;\n ipfsGateway: string;\n chainId: Hex;\n}\n\n/**\n * @type BalanceMap\n *\n * Key value object containing the balance for each tokenAddress\n * @property [tokenAddress] - Address of the token\n */\nexport interface BalanceMap {\n [tokenAddress: string]: BN;\n}\n\n/**\n * Controller that interacts with contracts on mainnet through web3\n */\nexport class AssetsContractController extends BaseController<\n AssetsContractConfig,\n BaseState\n> {\n private _provider?: any;\n\n /**\n * Name of this controller used during composition\n */\n override name = 'AssetsContractController';\n\n private readonly getNetworkClientById: NetworkController['getNetworkClientById'];\n\n /**\n * Creates a AssetsContractController 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.getNetworkClientById - Gets the network client with the given id from the NetworkController.\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 getNetworkClientById,\n }: {\n chainId: Hex;\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n getNetworkClientById: NetworkController['getNetworkClientById'];\n },\n config?: Partial<AssetsContractConfig>,\n state?: Partial<BaseState>,\n ) {\n super(config, state);\n this.defaultConfig = {\n provider: undefined,\n ipfsGateway: IPFS_DEFAULT_GATEWAY_URL,\n chainId: initialChainId,\n };\n this.initialize();\n this.getNetworkClientById = getNetworkClientById;\n\n onPreferencesStateChange(({ ipfsGateway }) => {\n this.configure({ ipfsGateway });\n });\n\n onNetworkStateChange((networkState) => {\n if (this.config.chainId !== networkState.providerConfig.chainId) {\n this.configure({\n chainId: networkState.providerConfig.chainId,\n });\n }\n });\n }\n\n /**\n * Sets a new provider.\n *\n * TODO: Replace this wth a method.\n *\n * @property provider - Provider used to create a new underlying Web3 instance\n */\n set provider(provider: any) {\n this._provider = provider;\n }\n\n get provider() {\n throw new Error('Property only used for setting');\n }\n\n /**\n * Get the relevant provider instance.\n *\n * @param networkClientId - Network Client ID.\n * @returns Web3Provider instance.\n */\n getProvider(networkClientId?: NetworkClientId): Web3Provider {\n const provider = networkClientId\n ? this.getNetworkClientById(networkClientId).provider\n : this._provider;\n\n if (provider === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n\n return new Web3Provider(provider);\n }\n\n /**\n * Get the relevant chain ID.\n *\n * @param networkClientId - Network Client ID used to get the provider.\n * @returns Hex chain ID.\n */\n getChainId(networkClientId?: NetworkClientId): Hex {\n return networkClientId\n ? this.getNetworkClientById(networkClientId).configuration.chainId\n : this.config.chainId;\n }\n\n /**\n * Get a ERC20Standard instance using the relevant provider instance.\n *\n * @param networkClientId - Network Client ID used to get the provider.\n * @returns ERC20Standard instance.\n */\n getERC20Standard(networkClientId?: NetworkClientId): ERC20Standard {\n const provider = this.getProvider(networkClientId);\n return new ERC20Standard(provider);\n }\n\n /**\n * Get a ERC721Standard instance using the relevant provider instance.\n *\n * @param networkClientId - Network Client ID used to get the provider.\n * @returns ERC721Standard instance.\n */\n getERC721Standard(networkClientId?: NetworkClientId): ERC721Standard {\n const provider = this.getProvider(networkClientId);\n return new ERC721Standard(provider);\n }\n\n /**\n * Get a ERC1155Standard instance using the relevant provider instance.\n *\n * @param networkClientId - Network Client ID used to get the provider.\n * @returns ERC1155Standard instance.\n */\n getERC1155Standard(networkClientId?: NetworkClientId): ERC1155Standard {\n const provider = this.getProvider(networkClientId);\n return new ERC1155Standard(provider);\n }\n\n /**\n * Get balance or count for current account on specific asset contract.\n *\n * @param address - Asset ERC20 contract address.\n * @param selectedAddress - Current account public address.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to BN object containing balance for current account on specific asset contract.\n */\n async getERC20BalanceOf(\n address: string,\n selectedAddress: string,\n networkClientId?: NetworkClientId,\n ): Promise<BN> {\n const erc20Standard = this.getERC20Standard(networkClientId);\n return erc20Standard.getBalanceOf(address, selectedAddress);\n }\n\n /**\n * Query for the decimals for a given ERC20 asset.\n *\n * @param address - ERC20 asset contract address.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'decimals'.\n */\n async getERC20TokenDecimals(\n address: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc20Standard = this.getERC20Standard(networkClientId);\n return erc20Standard.getTokenDecimals(address);\n }\n\n /**\n * Query for the name for a given ERC20 asset.\n *\n * @param address - ERC20 asset contract address.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'decimals'.\n */\n async getERC20TokenName(\n address: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc20Standard = this.getERC20Standard(networkClientId);\n return erc20Standard.getTokenName(address);\n }\n\n /**\n * Enumerate assets assigned to an owner.\n *\n * @param address - ERC721 asset contract address.\n * @param selectedAddress - Current account public address.\n * @param index - An NFT counter less than `balanceOf(selectedAddress)`.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to token identifier for the 'index'th asset assigned to 'selectedAddress'.\n */\n getERC721NftTokenId(\n address: string,\n selectedAddress: string,\n index: number,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc721Standard = this.getERC721Standard(networkClientId);\n return erc721Standard.getNftTokenId(address, selectedAddress, index);\n }\n\n /**\n * Enumerate assets assigned to an owner.\n *\n * @param tokenAddress - ERC721 asset contract address.\n * @param userAddress - Current account public address.\n * @param tokenId - ERC721 asset identifier.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to an object containing the token standard and a set of details which depend on which standard the token supports.\n */\n async getTokenStandardAndDetails(\n tokenAddress: string,\n userAddress?: string,\n tokenId?: string,\n networkClientId?: NetworkClientId,\n ): Promise<{\n standard: string;\n tokenURI?: string | undefined;\n symbol?: string | undefined;\n name?: string | undefined;\n decimals?: string | undefined;\n balance?: BN | undefined;\n }> {\n // Asserts provider is available\n this.getProvider(networkClientId);\n\n const { ipfsGateway } = this.config;\n\n // ERC721\n try {\n const erc721Standard = this.getERC721Standard(networkClientId);\n return {\n ...(await erc721Standard.getDetails(\n tokenAddress,\n ipfsGateway,\n tokenId,\n )),\n };\n } catch {\n // Ignore\n }\n\n // ERC1155\n try {\n const erc1155Standard = this.getERC1155Standard(networkClientId);\n return {\n ...(await erc1155Standard.getDetails(\n tokenAddress,\n ipfsGateway,\n tokenId,\n )),\n };\n } catch {\n // Ignore\n }\n\n // ERC20\n try {\n const erc20Standard = this.getERC20Standard(networkClientId);\n return {\n ...(await erc20Standard.getDetails(tokenAddress, userAddress)),\n };\n } catch {\n // Ignore\n }\n\n throw new Error('Unable to determine contract standard');\n }\n\n /**\n * Query for tokenURI for a given ERC721 asset.\n *\n * @param address - ERC721 asset contract address.\n * @param tokenId - ERC721 asset identifier.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'tokenURI'.\n */\n async getERC721TokenURI(\n address: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc721Standard = this.getERC721Standard(networkClientId);\n return erc721Standard.getTokenURI(address, tokenId);\n }\n\n /**\n * Query for name for a given asset.\n *\n * @param address - ERC721 or ERC20 asset contract address.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'name'.\n */\n async getERC721AssetName(\n address: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc721Standard = this.getERC721Standard(networkClientId);\n return erc721Standard.getAssetName(address);\n }\n\n /**\n * Query for symbol for a given asset.\n *\n * @param address - ERC721 or ERC20 asset contract address.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'symbol'.\n */\n async getERC721AssetSymbol(\n address: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc721Standard = this.getERC721Standard(networkClientId);\n return erc721Standard.getAssetSymbol(address);\n }\n\n /**\n * Query for owner for a given ERC721 asset.\n *\n * @param address - ERC721 asset contract address.\n * @param tokenId - ERC721 asset identifier.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the owner address.\n */\n async getERC721OwnerOf(\n address: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc721Standard = this.getERC721Standard(networkClientId);\n return erc721Standard.getOwnerOf(address, tokenId);\n }\n\n /**\n * Query for tokenURI for a given asset.\n *\n * @param address - ERC1155 asset contract address.\n * @param tokenId - ERC1155 asset identifier.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'tokenURI'.\n */\n async getERC1155TokenURI(\n address: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<string> {\n const erc1155Standard = this.getERC1155Standard(networkClientId);\n return erc1155Standard.getTokenURI(address, tokenId);\n }\n\n /**\n * Query for balance of a given ERC 1155 token.\n *\n * @param userAddress - Wallet public address.\n * @param nftAddress - ERC1155 asset contract address.\n * @param nftId - ERC1155 asset identifier.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'balanceOf'.\n */\n async getERC1155BalanceOf(\n userAddress: string,\n nftAddress: string,\n nftId: string,\n networkClientId?: NetworkClientId,\n ): Promise<BN> {\n const erc1155Standard = this.getERC1155Standard(networkClientId);\n return erc1155Standard.getBalanceOf(nftAddress, userAddress, nftId);\n }\n\n /**\n * Transfer single ERC1155 token.\n *\n * @param nftAddress - ERC1155 token address.\n * @param senderAddress - ERC1155 token sender.\n * @param recipientAddress - ERC1155 token recipient.\n * @param nftId - ERC1155 token id.\n * @param qty - Quantity of tokens to be sent.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns Promise resolving to the 'transferSingle' ERC1155 token.\n */\n async transferSingleERC1155(\n nftAddress: string,\n senderAddress: string,\n recipientAddress: string,\n nftId: string,\n qty: string,\n networkClientId?: NetworkClientId,\n ): Promise<void> {\n const erc1155Standard = this.getERC1155Standard(networkClientId);\n return erc1155Standard.transferSingle(\n nftAddress,\n senderAddress,\n recipientAddress,\n nftId,\n qty,\n );\n }\n\n /**\n * Get the token balance for a list of token addresses in a single call. Only non-zero balances\n * are returned.\n *\n * @param selectedAddress - The address to check token balances for.\n * @param tokensToDetect - The token addresses to detect balances for.\n * @param networkClientId - Network Client ID to fetch the provider with.\n * @returns The list of non-zero token balances.\n */\n async getBalancesInSingleCall(\n selectedAddress: string,\n tokensToDetect: string[],\n networkClientId?: NetworkClientId,\n ) {\n const chainId = this.getChainId(networkClientId);\n const provider = this.getProvider(networkClientId);\n if (!(chainId in SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID)) {\n // Only fetch balance if contract address exists\n return {};\n }\n const contractAddress = SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID[chainId];\n\n const contract = new Contract(\n contractAddress,\n abiSingleCallBalancesContract,\n provider,\n );\n const result = await contract.balances([selectedAddress], tokensToDetect);\n const nonZeroBalances: BalanceMap = {};\n /* istanbul ignore else */\n if (result.length > 0) {\n tokensToDetect.forEach((tokenAddress, index) => {\n const balance: BN = result[index];\n /* istanbul ignore else */\n if (String(balance) !== '0') {\n nonZeroBalances[tokenAddress] = balance;\n }\n });\n }\n return nonZeroBalances;\n }\n}\n\nexport default AssetsContractController;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NftController.d.ts","sourceRoot":"","sources":["../src/NftController.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"NftController.d.ts","sourceRoot":"","sources":["../src/NftController.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,EACV,UAAU,EACV,SAAS,EACT,6BAA6B,EAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAa3D,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,YAAY,EACb,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAG3C,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAE3E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAEV,aAAa,EAEb,cAAc,EACf,MAAM,0BAA0B,CAAC;AAElC,aAAK,eAAe,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE5C,aAAK,gBAAgB,GAAG;IACtB,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,WAAW,CAAC;IAC1D,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,eAAe,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,GAAI,SAAQ,WAAW;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,SAAU,SAAQ,UAAU;IAC3C,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,GAAG,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,QAAS,SAAQ,SAAS;IACzC,eAAe,EAAE;QACf,CAAC,GAAG,EAAE,MAAM,GAAG;YAAE,CAAC,OAAO,EAAE,GAAG,GAAG,WAAW,EAAE,CAAA;SAAE,CAAC;KAClD,CAAC;IACF,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG;YAAE,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,EAAE,CAAA;SAAE,CAAA;KAAE,CAAC;IACtD,WAAW,EAAE,GAAG,EAAE,CAAC;CACpB;AAKD,UAAU,QAAQ;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,QAAA,MAAM,cAAc,kBAAkB,CAAC;AAEvC;;GAEG;AACH,aAAK,cAAc,GAAG,kBAAkB,CAAC;AAEzC;;GAEG;AACH,oBAAY,sBAAsB,GAAG,6BAA6B,CAChE,OAAO,cAAc,EACrB,cAAc,EACd,KAAK,EACL,cAAc,CAAC,MAAM,CAAC,EACtB,KAAK,CACN,CAAC;AAEF;;GAEG;AACH,qBAAa,aAAc,SAAQ,cAAc,CAAC,SAAS,EAAE,QAAQ,CAAC;IACpE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyB;IAEzD,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,4BAA4B;IAQpC;;;;;;;;OAQG;IACH,OAAO,CAAC,oBAAoB;IAyB5B;;;;;;OAMG;YACW,wBAAwB;IAkEtC;;;;;;;OAOG;YACW,6BAA6B;IAuE3C;;;;;;;OAOG;YACW,oBAAoB;IA8ClC;;;;;;;OAOG;YACW,iBAAiB;IAuC/B;;;;;OAKG;YACW,gCAAgC;IAkC9C;;;;;;OAMG;YACW,qCAAqC;IAuBnD;;;;;;OAMG;YACW,yBAAyB;IAwDvC;;;;;;;;;;;OAWG;YACW,gBAAgB;IA0E9B;;;;;;;;;;OAUG;YACW,cAAc;IA+F5B;;;;;OAKG;IACH,OAAO,CAAC,4BAA4B;IA2BpC;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAe3B;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAezB;;OAEG;IACH,GAAG,eAAsB;IAEzB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACM,IAAI,SAAmB;IAEhC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAiD;IAEpF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAmD;IAExF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgD;IAElF,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA+C;IAEhF,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAkD;IAEtF,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAiD;IAEpF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA4C;IAEjF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAMjB;IAEX;;;;;;;;;;;;;;;;;;;OAmBG;gBAED,EACE,OAAO,EAAE,cAAc,EACvB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,UAAU,EACV,SAAS,GACV,EAAE;QACD,OAAO,EAAE,GAAG,CAAC;QACb,wBAAwB,EAAE,CACxB,QAAQ,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,KAAK,IAAI,KACnD,IAAI,CAAC;QACV,oBAAoB,EAAE,CACpB,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,IAAI,KAC3C,IAAI,CAAC;QACV,kBAAkB,EAAE,wBAAwB,CAAC,oBAAoB,CAAC,CAAC;QACnE,oBAAoB,EAAE,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QACvE,iBAAiB,EAAE,wBAAwB,CAAC,mBAAmB,CAAC,CAAC;QACjE,gBAAgB,EAAE,wBAAwB,CAAC,kBAAkB,CAAC,CAAC;QAC/D,mBAAmB,EAAE,wBAAwB,CAAC,qBAAqB,CAAC,CAAC;QACrE,kBAAkB,EAAE,wBAAwB,CAAC,oBAAoB,CAAC,CAAC;QACnE,oBAAoB,EAAE,iBAAiB,CAAC,sBAAsB,CAAC,CAAC;QAChE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;YAClB,OAAO,EAAE,MAAM,CAAC;YAChB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;YAC3B,OAAO,EAAE,MAAM,CAAC;YAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;YACxB,MAAM,EAAE,MAAM,CAAC;SAChB,KAAK,IAAI,CAAC;QACX,SAAS,EAAE,sBAAsB,CAAC;KACnC,EACD,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,EAC5B,KAAK,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC;IAkDrB,gBAAgB,CACpB,KAAK,EAAE,QAAQ,EACf,IAAI,EAAE,eAAe,EACrB,WAAW,EAAE,MAAM;IA+CrB,OAAO,CAAC,iBAAiB;IAezB;;;;;;;;;;;OAWG;IACG,QAAQ,CACZ,KAAK,EAAE,QAAQ,EACf,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,MAAM,EACd,eAAe,CAAC,EAAE,eAAe;IA4CnC;;;;OAIG;IACH,SAAS,CAAC,aAAa,EAAE,MAAM;IAI/B;;;;;;;;OAQG;IACG,UAAU,CACd,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,eAAe,GAChC,OAAO,CAAC,OAAO,CAAC;IAiCnB;;;;;;;;OAQG;IACG,qBAAqB,CACzB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,eAAe,EACjC,MAAM,CAAC,EAAE,MAAM;IAgBjB;;;;;;;;;;;;OAYG;IACG,MAAM,CACV,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,EACE,WAAW,EACX,OAAO,EAAE,6JAA6J;IACtK,WAAW,EACX,MAAsB,EACtB,eAAe,GAChB,GAAE;QACD,WAAW,CAAC,EAAE,WAAW,CAAC;QAC1B,OAAO,CAAC,EAAE,GAAG,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,eAAe,CAAC,EAAE,eAAe,CAAC;KAC9B;IAuCR;;;;;OAKG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAc1C;;;;;OAKG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAcnD;;OAEG;IACH,gBAAgB;IAIhB;;;;;;;;;;OAUG;IACG,sCAAsC,CAC1C,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,OAAO,EACd,EAAE,WAAW,EAAE,OAAO,EAAE;;;KAGvB;IAyCH;;;OAGG;IACG,oCAAoC;IAe1C;;;;;;OAMG;IACH,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO;IAuB3E;;;;;;;;OAQG;IACH,0BAA0B,CACxB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,GAAG,GACX;QAAE,GAAG,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAgBrC;;;;;;;OAOG;IACH,SAAS,CACP,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EACrB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,GAAG;IA6Bd;;;;;;;OAOG;IACH,wCAAwC,CACtC,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,GAAG,GACX,OAAO;IAyBJ,gBAAgB,CAAC,gBAAgB,EAAE,gBAAgB;CAuB1D;AAED,eAAe,aAAa,CAAC"}
|
package/dist/NftController.js
CHANGED
|
@@ -185,6 +185,17 @@ class NftController extends base_controller_1.BaseController {
|
|
|
185
185
|
tokenURI: tokenURI !== null && tokenURI !== void 0 ? tokenURI : null,
|
|
186
186
|
};
|
|
187
187
|
}
|
|
188
|
+
const isDisplayNFTMediaToggleEnabled = this.config.openSeaEnabled;
|
|
189
|
+
if (!hasIpfsTokenURI && !isDisplayNFTMediaToggleEnabled) {
|
|
190
|
+
return {
|
|
191
|
+
image: null,
|
|
192
|
+
name: null,
|
|
193
|
+
description: null,
|
|
194
|
+
standard: standard || null,
|
|
195
|
+
favorite: false,
|
|
196
|
+
tokenURI: tokenURI !== null && tokenURI !== void 0 ? tokenURI : null,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
188
199
|
if (hasIpfsTokenURI) {
|
|
189
200
|
tokenURI = (0, assetsUtil_1.getFormattedIpfsUrl)(ipfsGateway, tokenURI, useIPFSSubdomains);
|
|
190
201
|
}
|
|
@@ -1 +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 {\n NetworkClientId,\n NetworkController,\n NetworkState,\n} 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\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<NftConfig, NftState> {\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<NftMetadata> {\n // TODO Parameterize this by chainId for non-mainnet token detection\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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformationFromTokenURI(\n contractAddress: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<NftMetadata> {\n const { ipfsGateway, useIPFSSubdomains, isIpfsGatewayEnabled } =\n this.config;\n const result = await this.getNftURIAndStandard(\n contractAddress,\n tokenId,\n networkClientId,\n );\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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving NFT uri and token standard.\n */\n private async getNftURIAndStandard(\n contractAddress: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<[string, string]> {\n // try ERC721 uri\n try {\n const uri = await this.getERC721TokenURI(\n contractAddress,\n tokenId,\n networkClientId,\n );\n return [uri, ERC721];\n } catch {\n // Ignore error\n }\n\n // try ERC1155 uri\n try {\n const tokenURI = await this.getERC1155TokenURI(\n contractAddress,\n tokenId,\n networkClientId,\n );\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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformation(\n contractAddress: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<NftMetadata> {\n let { chainId } = this.config;\n if (networkClientId) {\n chainId =\n this.getNetworkClientById(networkClientId).configuration.chainId;\n }\n\n const blockchainMetadata = await safelyExecute(async () => {\n return await this.getNftInformationFromTokenURI(\n contractAddress,\n tokenId,\n networkClientId,\n );\n });\n\n let openSeaMetadata;\n // currently we only need to enter this block if we are on mainnet\n if (this.config.openSeaEnabled && chainId === '0x1') {\n openSeaMetadata = await safelyExecute(async () => {\n return await this.getNftInformationFromApi(contractAddress, tokenId);\n });\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<ApiNftContract> {\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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftContractInformationFromContract(\n contractAddress: string,\n networkClientId?: NetworkClientId,\n ): Promise<\n Partial<ApiNftContract> &\n Pick<ApiNftContract, 'address'> &\n Pick<ApiNftContract, 'collection'>\n > {\n const name = await this.getERC721AssetName(\n contractAddress,\n networkClientId,\n );\n const symbol = await this.getERC721AssetSymbol(\n contractAddress,\n networkClientId,\n );\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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving to the NFT contract name, image and description.\n */\n private async getNftContractInformation(\n contractAddress: string,\n networkClientId?: NetworkClientId,\n ): Promise<\n Partial<ApiNftContract> &\n Pick<ApiNftContract, 'address'> &\n Pick<ApiNftContract, 'collection'>\n > {\n const blockchainContractData: Partial<ApiNftContract> &\n Pick<ApiNftContract, 'address'> &\n Pick<ApiNftContract, 'collection'> = await safelyExecute(async () => {\n return await this.getNftContractInformationFromContract(\n contractAddress,\n networkClientId,\n );\n });\n\n const { chainId } = this.config;\n const getCurrentChainId = this.getCorrectChainId({\n chainId,\n networkClientId,\n });\n\n let openSeaContractData: Partial<ApiNftContract> | undefined;\n if (this.config.openSeaEnabled && getCurrentChainId === '0x1') {\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 tokenAddress - 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 chainId - The chainId of the network where the NFT is being added.\n * @param userAddress - The address of the account where the NFT is being 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 tokenAddress: string,\n tokenId: string,\n nftMetadata: NftMetadata,\n nftContract: NftContract,\n chainId: Hex,\n userAddress: string,\n source: Source,\n ): Promise<Nft[]> {\n // TODO: Remove unused return\n const releaseLock = await this.mutex.acquire();\n try {\n tokenAddress = toChecksumHexAddress(tokenAddress);\n const { allNfts } = this.state;\n\n const nfts = allNfts[userAddress]?.[chainId] || [];\n\n const existingEntry: Nft | undefined = nfts.find(\n (nft) =>\n nft.address.toLowerCase() === tokenAddress.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() === tokenAddress.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: tokenAddress,\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,\n });\n\n if (this.onNftAdded) {\n this.onNftAdded({\n address: tokenAddress,\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 options - options.\n * @param options.tokenAddress - Hex address of the NFT contract.\n * @param options.chainId - The chainId of the network where the NFT is being added.\n * @param options.userAddress - The address of the account where the NFT is being added.\n * @param options.networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @param options.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 tokenAddress,\n chainId,\n userAddress,\n networkClientId,\n source,\n }: {\n tokenAddress: string;\n chainId?: Hex;\n userAddress?: string;\n networkClientId?: NetworkClientId;\n source?: Source;\n }): Promise<NftContract[]> {\n const releaseLock = await this.mutex.acquire();\n try {\n tokenAddress = toChecksumHexAddress(tokenAddress);\n const { allNftContracts } = this.state;\n const currentChainId = this.getCorrectChainId({\n chainId,\n networkClientId,\n });\n const selectedAddress = userAddress ?? this.config.selectedAddress;\n\n const nftContracts =\n allNftContracts[selectedAddress]?.[currentChainId] || [];\n\n const existingEntry = nftContracts.find(\n (nftContract) =>\n nftContract.address.toLowerCase() === tokenAddress.toLowerCase(),\n );\n if (existingEntry) {\n return nftContracts;\n }\n\n // this doesn't work currently for detection if the user switches networks while the detection is processing\n // will be fixed once detection uses networkClientIds\n const contractInformation = await this.getNftContractInformation(\n tokenAddress,\n networkClientId,\n );\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: tokenAddress },\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: currentChainId,\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 getNetworkClientById: NetworkController['getNetworkClientById'];\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.getNetworkClientById - Gets the network client for the given networkClientId.\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 getNetworkClientById,\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 getNetworkClientById: NetworkController['getNetworkClientById'];\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<BaseConfig>,\n state?: Partial<NftState>,\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.getNetworkClientById = getNetworkClientById;\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 userAddress: 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 userAddress,\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 // temporary method to get the correct chainId until we remove chainId from the config & the chainId arg from the detection logic\n // Just a helper method to prefer the networkClient chainId first then the chainId argument and then finally the config chainId\n private getCorrectChainId({\n chainId,\n networkClientId,\n }: {\n chainId?: Hex;\n networkClientId?: NetworkClientId;\n }) {\n if (networkClientId) {\n return this.getNetworkClientById(networkClientId).configuration.chainId;\n } else if (chainId) {\n return chainId;\n }\n return this.config.chainId;\n }\n\n /**\n * Adds a new suggestedAsset to state. Parameters will be validated according to\n * asset type being watched. A `<suggestedNftMeta.id>: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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Object containing a Promise resolving to the suggestedAsset address if accepted.\n */\n async watchNft(\n asset: NftAsset,\n type: NFTStandardType,\n origin: string,\n networkClientId?: NetworkClientId,\n ) {\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 networkClientId,\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(address, tokenId, {\n nftMetadata: {\n name: name ?? null,\n description: description ?? null,\n image: image ?? null,\n standard: standard ?? null,\n },\n chainId,\n userAddress: selectedAddress,\n source: Source.Dapp,\n networkClientId,\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 tokenId - NFT token ID.\n * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving the NFT ownership.\n */\n async isNftOwner(\n ownerAddress: string,\n nftAddress: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<boolean> {\n // Checks the ownership for ERC-721.\n try {\n const owner = await this.getERC721OwnerOf(\n nftAddress,\n tokenId,\n networkClientId,\n );\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 tokenId,\n networkClientId,\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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @param source - Whether the NFT was detected, added manually or suggested by a dapp.\n */\n async addNftVerifyOwnership(\n address: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n source?: Source,\n ) {\n const { selectedAddress } = this.config;\n if (\n !(await this.isNftOwner(\n selectedAddress,\n address,\n tokenId,\n networkClientId,\n ))\n ) {\n throw new Error('This NFT is not owned by the user');\n }\n await this.addNft(address, tokenId, { networkClientId, source });\n }\n\n /**\n * Adds an NFT and respective NFT contract to the stored NFT and NFT contracts lists.\n *\n * @param tokenAddress - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @param options - an object of arguments\n * @param options.nftMetadata - NFT optional metadata.\n * @param options.chainId - The chain ID of the current network.\n * @param options.userAddress - The address of the current user.\n * @param options.source - Whether the NFT was detected, added manually or suggested by a dapp.\n * @param options.networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving to the current NFT list.\n */\n async addNft(\n tokenAddress: string,\n tokenId: string,\n {\n nftMetadata,\n chainId, // TODO remove and replace chainId arg with fetch chainId using getNetworkClientById(networkClientId).configuration.chainId once polling refactor is complete\n userAddress,\n source = Source.Custom,\n networkClientId,\n }: {\n nftMetadata?: NftMetadata;\n chainId?: Hex;\n userAddress?: string;\n source?: Source;\n networkClientId?: NetworkClientId;\n } = {},\n ) {\n tokenAddress = toChecksumHexAddress(tokenAddress);\n\n const currentChainId = this.getCorrectChainId({ chainId, networkClientId });\n const selectedAddress = userAddress ?? this.config.selectedAddress;\n\n const newNftContracts = await this.addNftContract({\n tokenAddress,\n chainId: currentChainId,\n userAddress: selectedAddress,\n networkClientId,\n source,\n });\n\n nftMetadata =\n nftMetadata ||\n (await this.getNftInformation(tokenAddress, tokenId, networkClientId));\n\n // If NFT contract was not added, do not add individual NFT\n const nftContract = newNftContracts.find(\n (contract) =>\n contract.address.toLowerCase() === tokenAddress.toLowerCase(),\n );\n\n // If NFT contract information, add individual NFT\n if (nftContract) {\n await this.addIndividualNft(\n tokenAddress,\n tokenId,\n nftMetadata,\n nftContract,\n currentChainId,\n selectedAddress,\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<Nft>,\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"]}
|
|
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 {\n NetworkClientId,\n NetworkController,\n NetworkState,\n} 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\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<NftConfig, NftState> {\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<NftMetadata> {\n // TODO Parameterize this by chainId for non-mainnet token detection\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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformationFromTokenURI(\n contractAddress: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<NftMetadata> {\n const { ipfsGateway, useIPFSSubdomains, isIpfsGatewayEnabled } =\n this.config;\n const result = await this.getNftURIAndStandard(\n contractAddress,\n tokenId,\n networkClientId,\n );\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\n const isDisplayNFTMediaToggleEnabled = this.config.openSeaEnabled;\n if (!hasIpfsTokenURI && !isDisplayNFTMediaToggleEnabled) {\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 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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving NFT uri and token standard.\n */\n private async getNftURIAndStandard(\n contractAddress: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<[string, string]> {\n // try ERC721 uri\n try {\n const uri = await this.getERC721TokenURI(\n contractAddress,\n tokenId,\n networkClientId,\n );\n return [uri, ERC721];\n } catch {\n // Ignore error\n }\n\n // try ERC1155 uri\n try {\n const tokenURI = await this.getERC1155TokenURI(\n contractAddress,\n tokenId,\n networkClientId,\n );\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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftInformation(\n contractAddress: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<NftMetadata> {\n let { chainId } = this.config;\n if (networkClientId) {\n chainId =\n this.getNetworkClientById(networkClientId).configuration.chainId;\n }\n\n const blockchainMetadata = await safelyExecute(async () => {\n return await this.getNftInformationFromTokenURI(\n contractAddress,\n tokenId,\n networkClientId,\n );\n });\n\n let openSeaMetadata;\n // currently we only need to enter this block if we are on mainnet\n if (this.config.openSeaEnabled && chainId === '0x1') {\n openSeaMetadata = await safelyExecute(async () => {\n return await this.getNftInformationFromApi(contractAddress, tokenId);\n });\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<ApiNftContract> {\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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving to the current NFT name and image.\n */\n private async getNftContractInformationFromContract(\n contractAddress: string,\n networkClientId?: NetworkClientId,\n ): Promise<\n Partial<ApiNftContract> &\n Pick<ApiNftContract, 'address'> &\n Pick<ApiNftContract, 'collection'>\n > {\n const name = await this.getERC721AssetName(\n contractAddress,\n networkClientId,\n );\n const symbol = await this.getERC721AssetSymbol(\n contractAddress,\n networkClientId,\n );\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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving to the NFT contract name, image and description.\n */\n private async getNftContractInformation(\n contractAddress: string,\n networkClientId?: NetworkClientId,\n ): Promise<\n Partial<ApiNftContract> &\n Pick<ApiNftContract, 'address'> &\n Pick<ApiNftContract, 'collection'>\n > {\n const blockchainContractData: Partial<ApiNftContract> &\n Pick<ApiNftContract, 'address'> &\n Pick<ApiNftContract, 'collection'> = await safelyExecute(async () => {\n return await this.getNftContractInformationFromContract(\n contractAddress,\n networkClientId,\n );\n });\n\n const { chainId } = this.config;\n const getCurrentChainId = this.getCorrectChainId({\n chainId,\n networkClientId,\n });\n\n let openSeaContractData: Partial<ApiNftContract> | undefined;\n if (this.config.openSeaEnabled && getCurrentChainId === '0x1') {\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 tokenAddress - 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 chainId - The chainId of the network where the NFT is being added.\n * @param userAddress - The address of the account where the NFT is being 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 tokenAddress: string,\n tokenId: string,\n nftMetadata: NftMetadata,\n nftContract: NftContract,\n chainId: Hex,\n userAddress: string,\n source: Source,\n ): Promise<Nft[]> {\n // TODO: Remove unused return\n const releaseLock = await this.mutex.acquire();\n try {\n tokenAddress = toChecksumHexAddress(tokenAddress);\n const { allNfts } = this.state;\n\n const nfts = allNfts[userAddress]?.[chainId] || [];\n\n const existingEntry: Nft | undefined = nfts.find(\n (nft) =>\n nft.address.toLowerCase() === tokenAddress.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() === tokenAddress.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: tokenAddress,\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,\n });\n\n if (this.onNftAdded) {\n this.onNftAdded({\n address: tokenAddress,\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 options - options.\n * @param options.tokenAddress - Hex address of the NFT contract.\n * @param options.chainId - The chainId of the network where the NFT is being added.\n * @param options.userAddress - The address of the account where the NFT is being added.\n * @param options.networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @param options.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 tokenAddress,\n chainId,\n userAddress,\n networkClientId,\n source,\n }: {\n tokenAddress: string;\n chainId?: Hex;\n userAddress?: string;\n networkClientId?: NetworkClientId;\n source?: Source;\n }): Promise<NftContract[]> {\n const releaseLock = await this.mutex.acquire();\n try {\n tokenAddress = toChecksumHexAddress(tokenAddress);\n const { allNftContracts } = this.state;\n const currentChainId = this.getCorrectChainId({\n chainId,\n networkClientId,\n });\n const selectedAddress = userAddress ?? this.config.selectedAddress;\n\n const nftContracts =\n allNftContracts[selectedAddress]?.[currentChainId] || [];\n\n const existingEntry = nftContracts.find(\n (nftContract) =>\n nftContract.address.toLowerCase() === tokenAddress.toLowerCase(),\n );\n if (existingEntry) {\n return nftContracts;\n }\n\n // this doesn't work currently for detection if the user switches networks while the detection is processing\n // will be fixed once detection uses networkClientIds\n const contractInformation = await this.getNftContractInformation(\n tokenAddress,\n networkClientId,\n );\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: tokenAddress },\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: currentChainId,\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 getNetworkClientById: NetworkController['getNetworkClientById'];\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.getNetworkClientById - Gets the network client for the given networkClientId.\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 getNetworkClientById,\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 getNetworkClientById: NetworkController['getNetworkClientById'];\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<BaseConfig>,\n state?: Partial<NftState>,\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.getNetworkClientById = getNetworkClientById;\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 userAddress: 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 userAddress,\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 // temporary method to get the correct chainId until we remove chainId from the config & the chainId arg from the detection logic\n // Just a helper method to prefer the networkClient chainId first then the chainId argument and then finally the config chainId\n private getCorrectChainId({\n chainId,\n networkClientId,\n }: {\n chainId?: Hex;\n networkClientId?: NetworkClientId;\n }) {\n if (networkClientId) {\n return this.getNetworkClientById(networkClientId).configuration.chainId;\n } else if (chainId) {\n return chainId;\n }\n return this.config.chainId;\n }\n\n /**\n * Adds a new suggestedAsset to state. Parameters will be validated according to\n * asset type being watched. A `<suggestedNftMeta.id>: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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Object containing a Promise resolving to the suggestedAsset address if accepted.\n */\n async watchNft(\n asset: NftAsset,\n type: NFTStandardType,\n origin: string,\n networkClientId?: NetworkClientId,\n ) {\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 networkClientId,\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(address, tokenId, {\n nftMetadata: {\n name: name ?? null,\n description: description ?? null,\n image: image ?? null,\n standard: standard ?? null,\n },\n chainId,\n userAddress: selectedAddress,\n source: Source.Dapp,\n networkClientId,\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 tokenId - NFT token ID.\n * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving the NFT ownership.\n */\n async isNftOwner(\n ownerAddress: string,\n nftAddress: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n ): Promise<boolean> {\n // Checks the ownership for ERC-721.\n try {\n const owner = await this.getERC721OwnerOf(\n nftAddress,\n tokenId,\n networkClientId,\n );\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 tokenId,\n networkClientId,\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 * @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @param source - Whether the NFT was detected, added manually or suggested by a dapp.\n */\n async addNftVerifyOwnership(\n address: string,\n tokenId: string,\n networkClientId?: NetworkClientId,\n source?: Source,\n ) {\n const { selectedAddress } = this.config;\n if (\n !(await this.isNftOwner(\n selectedAddress,\n address,\n tokenId,\n networkClientId,\n ))\n ) {\n throw new Error('This NFT is not owned by the user');\n }\n await this.addNft(address, tokenId, { networkClientId, source });\n }\n\n /**\n * Adds an NFT and respective NFT contract to the stored NFT and NFT contracts lists.\n *\n * @param tokenAddress - Hex address of the NFT contract.\n * @param tokenId - The NFT identifier.\n * @param options - an object of arguments\n * @param options.nftMetadata - NFT optional metadata.\n * @param options.chainId - The chain ID of the current network.\n * @param options.userAddress - The address of the current user.\n * @param options.source - Whether the NFT was detected, added manually or suggested by a dapp.\n * @param options.networkClientId - The networkClientId that can be used to identify the network client to use for this request.\n * @returns Promise resolving to the current NFT list.\n */\n async addNft(\n tokenAddress: string,\n tokenId: string,\n {\n nftMetadata,\n chainId, // TODO remove and replace chainId arg with fetch chainId using getNetworkClientById(networkClientId).configuration.chainId once polling refactor is complete\n userAddress,\n source = Source.Custom,\n networkClientId,\n }: {\n nftMetadata?: NftMetadata;\n chainId?: Hex;\n userAddress?: string;\n source?: Source;\n networkClientId?: NetworkClientId;\n } = {},\n ) {\n tokenAddress = toChecksumHexAddress(tokenAddress);\n\n const currentChainId = this.getCorrectChainId({ chainId, networkClientId });\n const selectedAddress = userAddress ?? this.config.selectedAddress;\n\n const newNftContracts = await this.addNftContract({\n tokenAddress,\n chainId: currentChainId,\n userAddress: selectedAddress,\n networkClientId,\n source,\n });\n\n nftMetadata =\n nftMetadata ||\n (await this.getNftInformation(tokenAddress, tokenId, networkClientId));\n\n // If NFT contract was not added, do not add individual NFT\n const nftContract = newNftContracts.find(\n (contract) =>\n contract.address.toLowerCase() === tokenAddress.toLowerCase(),\n );\n\n // If NFT contract information, add individual NFT\n if (nftContract) {\n await this.addIndividualNft(\n tokenAddress,\n tokenId,\n nftMetadata,\n nftContract,\n currentChainId,\n selectedAddress,\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<Nft>,\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"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RestrictedControllerMessenger } from '@metamask/base-controller';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
2
|
+
import type { NetworkClientId, NetworkControllerStateChangeEvent, NetworkState, NetworkControllerGetNetworkClientByIdAction } from '@metamask/network-controller';
|
|
3
|
+
import { PollingController } from '@metamask/polling-controller';
|
|
4
4
|
import type { Hex } from '@metamask/utils';
|
|
5
5
|
import type { Patch } from 'immer';
|
|
6
6
|
declare const name = "TokenListController";
|
|
@@ -34,11 +34,11 @@ export declare type GetTokenListState = {
|
|
|
34
34
|
type: `${typeof name}:getState`;
|
|
35
35
|
handler: () => TokenListState;
|
|
36
36
|
};
|
|
37
|
-
declare type TokenListMessenger = RestrictedControllerMessenger<typeof name, GetTokenListState, TokenListStateChange | NetworkControllerStateChangeEvent,
|
|
37
|
+
declare type TokenListMessenger = RestrictedControllerMessenger<typeof name, GetTokenListState | NetworkControllerGetNetworkClientByIdAction, TokenListStateChange | NetworkControllerStateChangeEvent, NetworkControllerGetNetworkClientByIdAction['type'], TokenListStateChange['type'] | NetworkControllerStateChangeEvent['type']>;
|
|
38
38
|
/**
|
|
39
39
|
* Controller that passively polls on a set interval for the list of tokens from metaswaps api
|
|
40
40
|
*/
|
|
41
|
-
export declare class TokenListController extends
|
|
41
|
+
export declare class TokenListController extends PollingController<typeof name, TokenListState, TokenListMessenger> {
|
|
42
42
|
#private;
|
|
43
43
|
private readonly mutex;
|
|
44
44
|
private intervalId?;
|
|
@@ -92,16 +92,18 @@ export declare class TokenListController extends BaseControllerV2<typeof name, T
|
|
|
92
92
|
private startPolling;
|
|
93
93
|
/**
|
|
94
94
|
* Fetching token list from the Token Service API.
|
|
95
|
+
*
|
|
96
|
+
* @private
|
|
97
|
+
* @param networkClientId - The ID of the network client triggering the fetch.
|
|
98
|
+
* @returns A promise that resolves when this operation completes.
|
|
95
99
|
*/
|
|
96
|
-
|
|
100
|
+
_executePoll(networkClientId: string): Promise<void>;
|
|
97
101
|
/**
|
|
98
|
-
*
|
|
99
|
-
* if yes data in cache will be returned
|
|
100
|
-
* otherwise null will be returned.
|
|
102
|
+
* Fetching token list from the Token Service API.
|
|
101
103
|
*
|
|
102
|
-
* @
|
|
104
|
+
* @param networkClientId - The ID of the network client triggering the fetch.
|
|
103
105
|
*/
|
|
104
|
-
|
|
106
|
+
fetchTokenList(networkClientId?: NetworkClientId): Promise<void>;
|
|
105
107
|
/**
|
|
106
108
|
* Clearing tokenList and tokensChainsCache explicitly.
|
|
107
109
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenListController.d.ts","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"TokenListController.d.ts","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,11 +13,11 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
13
13
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
14
14
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
15
15
|
};
|
|
16
|
-
var _TokenListController_instances, _TokenListController_onNetworkControllerStateChange;
|
|
16
|
+
var _TokenListController_instances, _TokenListController_onNetworkControllerStateChange, _TokenListController_fetchFromCache;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.TokenListController = void 0;
|
|
19
|
-
const base_controller_1 = require("@metamask/base-controller");
|
|
20
19
|
const controller_utils_1 = require("@metamask/controller-utils");
|
|
20
|
+
const polling_controller_1 = require("@metamask/polling-controller");
|
|
21
21
|
const async_mutex_1 = require("async-mutex");
|
|
22
22
|
const assetsUtil_1 = require("./assetsUtil");
|
|
23
23
|
const token_service_1 = require("./token-service");
|
|
@@ -37,7 +37,7 @@ const defaultState = {
|
|
|
37
37
|
/**
|
|
38
38
|
* Controller that passively polls on a set interval for the list of tokens from metaswaps api
|
|
39
39
|
*/
|
|
40
|
-
class TokenListController extends
|
|
40
|
+
class TokenListController extends polling_controller_1.PollingController {
|
|
41
41
|
/**
|
|
42
42
|
* Creates a TokenListController instance.
|
|
43
43
|
*
|
|
@@ -128,25 +128,46 @@ class TokenListController extends base_controller_1.BaseControllerV2 {
|
|
|
128
128
|
}
|
|
129
129
|
/**
|
|
130
130
|
* Fetching token list from the Token Service API.
|
|
131
|
+
*
|
|
132
|
+
* @private
|
|
133
|
+
* @param networkClientId - The ID of the network client triggering the fetch.
|
|
134
|
+
* @returns A promise that resolves when this operation completes.
|
|
135
|
+
*/
|
|
136
|
+
_executePoll(networkClientId) {
|
|
137
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
138
|
+
return this.fetchTokenList(networkClientId);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Fetching token list from the Token Service API.
|
|
143
|
+
*
|
|
144
|
+
* @param networkClientId - The ID of the network client triggering the fetch.
|
|
131
145
|
*/
|
|
132
|
-
fetchTokenList() {
|
|
133
|
-
var _a;
|
|
146
|
+
fetchTokenList(networkClientId) {
|
|
147
|
+
var _a, _b;
|
|
134
148
|
return __awaiter(this, void 0, void 0, function* () {
|
|
135
149
|
const releaseLock = yield this.mutex.acquire();
|
|
150
|
+
let networkClient;
|
|
151
|
+
if (networkClientId) {
|
|
152
|
+
networkClient = this.messagingSystem.call('NetworkController:getNetworkClientById', networkClientId);
|
|
153
|
+
}
|
|
154
|
+
const chainId = (_a = networkClient === null || networkClient === void 0 ? void 0 : networkClient.configuration.chainId) !== null && _a !== void 0 ? _a : this.chainId;
|
|
136
155
|
try {
|
|
137
156
|
const { tokensChainsCache } = this.state;
|
|
138
157
|
let tokenList = {};
|
|
139
|
-
const cachedTokens = yield (0, controller_utils_1.safelyExecute)(() => this.
|
|
158
|
+
const cachedTokens = yield (0, controller_utils_1.safelyExecute)(() => __classPrivateFieldGet(this, _TokenListController_instances, "m", _TokenListController_fetchFromCache).call(this, chainId));
|
|
140
159
|
if (cachedTokens) {
|
|
141
160
|
// Use non-expired cached tokens
|
|
142
161
|
tokenList = Object.assign({}, cachedTokens);
|
|
143
162
|
}
|
|
144
163
|
else {
|
|
145
164
|
// Fetch fresh token list
|
|
146
|
-
const tokensFromAPI = yield (0, controller_utils_1.safelyExecute)(() =>
|
|
165
|
+
const tokensFromAPI = yield (0, controller_utils_1.safelyExecute)(() => {
|
|
166
|
+
return (0, token_service_1.fetchTokenListByChainId)(chainId, this.abortController.signal);
|
|
167
|
+
});
|
|
147
168
|
if (!tokensFromAPI) {
|
|
148
169
|
// Fallback to expired cached tokens
|
|
149
|
-
tokenList = Object.assign({}, (((
|
|
170
|
+
tokenList = Object.assign({}, (((_b = tokensChainsCache[chainId]) === null || _b === void 0 ? void 0 : _b.data) || {}));
|
|
150
171
|
this.update(() => {
|
|
151
172
|
return Object.assign(Object.assign({}, this.state), { tokenList,
|
|
152
173
|
tokensChainsCache });
|
|
@@ -165,13 +186,13 @@ class TokenListController extends base_controller_1.BaseControllerV2 {
|
|
|
165
186
|
const uniqueTokenList = filteredTokenList.filter((token) => !duplicateSymbols.includes(token.symbol));
|
|
166
187
|
for (const token of uniqueTokenList) {
|
|
167
188
|
const formattedToken = Object.assign(Object.assign({}, token), { aggregators: (0, assetsUtil_1.formatAggregatorNames)(token.aggregators), iconUrl: (0, assetsUtil_1.formatIconUrlWithProxy)({
|
|
168
|
-
chainId
|
|
189
|
+
chainId,
|
|
169
190
|
tokenAddress: token.address,
|
|
170
191
|
}) });
|
|
171
192
|
tokenList[token.address] = formattedToken;
|
|
172
193
|
}
|
|
173
194
|
}
|
|
174
|
-
const updatedTokensChainsCache = Object.assign(Object.assign({}, tokensChainsCache), { [
|
|
195
|
+
const updatedTokensChainsCache = Object.assign(Object.assign({}, tokensChainsCache), { [chainId]: {
|
|
175
196
|
timestamp: Date.now(),
|
|
176
197
|
data: tokenList,
|
|
177
198
|
} });
|
|
@@ -184,25 +205,6 @@ class TokenListController extends base_controller_1.BaseControllerV2 {
|
|
|
184
205
|
}
|
|
185
206
|
});
|
|
186
207
|
}
|
|
187
|
-
/**
|
|
188
|
-
* Checks if the Cache timestamp is valid,
|
|
189
|
-
* if yes data in cache will be returned
|
|
190
|
-
* otherwise null will be returned.
|
|
191
|
-
*
|
|
192
|
-
* @returns The cached data, or `null` if the cache was expired.
|
|
193
|
-
*/
|
|
194
|
-
fetchFromCache() {
|
|
195
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
196
|
-
const { tokensChainsCache } = this.state;
|
|
197
|
-
const dataCache = tokensChainsCache[this.chainId];
|
|
198
|
-
const now = Date.now();
|
|
199
|
-
if ((dataCache === null || dataCache === void 0 ? void 0 : dataCache.data) &&
|
|
200
|
-
now - (dataCache === null || dataCache === void 0 ? void 0 : dataCache.timestamp) < this.cacheRefreshThreshold) {
|
|
201
|
-
return dataCache.data;
|
|
202
|
-
}
|
|
203
|
-
return null;
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
208
|
/**
|
|
207
209
|
* Clearing tokenList and tokensChainsCache explicitly.
|
|
208
210
|
*/
|
|
@@ -242,6 +244,17 @@ _TokenListController_instances = new WeakSet(), _TokenListController_onNetworkCo
|
|
|
242
244
|
}
|
|
243
245
|
}
|
|
244
246
|
});
|
|
247
|
+
}, _TokenListController_fetchFromCache = function _TokenListController_fetchFromCache(chainId) {
|
|
248
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
249
|
+
const { tokensChainsCache } = this.state;
|
|
250
|
+
const dataCache = tokensChainsCache[chainId];
|
|
251
|
+
const now = Date.now();
|
|
252
|
+
if ((dataCache === null || dataCache === void 0 ? void 0 : dataCache.data) &&
|
|
253
|
+
now - (dataCache === null || dataCache === void 0 ? void 0 : dataCache.timestamp) < this.cacheRefreshThreshold) {
|
|
254
|
+
return dataCache.data;
|
|
255
|
+
}
|
|
256
|
+
return null;
|
|
257
|
+
});
|
|
245
258
|
};
|
|
246
259
|
exports.default = TokenListController;
|
|
247
260
|
//# sourceMappingURL=TokenListController.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenListController.js","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { BaseControllerV2 } from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport type {\n NetworkControllerStateChangeEvent,\n NetworkState,\n} from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport type { Patch } from 'immer';\n\nimport {\n isTokenListSupportedForNetwork,\n formatAggregatorNames,\n formatIconUrlWithProxy,\n} from './assetsUtil';\nimport { fetchTokenList } from './token-service';\n\nconst DEFAULT_INTERVAL = 24 * 60 * 60 * 1000;\nconst DEFAULT_THRESHOLD = 24 * 60 * 60 * 1000;\n\nconst name = 'TokenListController';\n\nexport type TokenListToken = {\n name: string;\n symbol: string;\n decimals: number;\n address: string;\n occurrences: number;\n aggregators: string[];\n iconUrl: string;\n};\n\nexport type TokenListMap = Record<string, TokenListToken>;\n\ntype DataCache = {\n timestamp: number;\n data: TokenListMap;\n};\ntype TokensChainsCache = {\n [chainId: Hex]: DataCache;\n};\n\nexport type TokenListState = {\n tokenList: TokenListMap;\n tokensChainsCache: TokensChainsCache;\n preventPollingOnNetworkRestart: boolean;\n};\n\nexport type TokenListStateChange = {\n type: `${typeof name}:stateChange`;\n payload: [TokenListState, Patch[]];\n};\n\nexport type GetTokenListState = {\n type: `${typeof name}:getState`;\n handler: () => TokenListState;\n};\n\ntype TokenListMessenger = RestrictedControllerMessenger<\n typeof name,\n GetTokenListState,\n TokenListStateChange | NetworkControllerStateChangeEvent,\n never,\n TokenListStateChange['type'] | NetworkControllerStateChangeEvent['type']\n>;\n\nconst metadata = {\n tokenList: { persist: true, anonymous: true },\n tokensChainsCache: { persist: true, anonymous: true },\n preventPollingOnNetworkRestart: { persist: true, anonymous: true },\n};\n\nconst defaultState: TokenListState = {\n tokenList: {},\n tokensChainsCache: {},\n preventPollingOnNetworkRestart: false,\n};\n\n/**\n * Controller that passively polls on a set interval for the list of tokens from metaswaps api\n */\nexport class TokenListController extends BaseControllerV2<\n typeof name,\n TokenListState,\n TokenListMessenger\n> {\n private readonly mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay: number;\n\n private readonly cacheRefreshThreshold: number;\n\n private chainId: Hex;\n\n private abortController: AbortController;\n\n /**\n * Creates a TokenListController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onNetworkStateChange - A function for registering an event handler for network state changes.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.cacheRefreshThreshold - The token cache expiry time, in milliseconds.\n * @param options.messenger - A restricted controller messenger.\n * @param options.state - Initial state to set on this controller.\n * @param options.preventPollingOnNetworkRestart - Determines whether to prevent poilling on network restart in extension.\n */\n constructor({\n chainId,\n preventPollingOnNetworkRestart = false,\n onNetworkStateChange,\n interval = DEFAULT_INTERVAL,\n cacheRefreshThreshold = DEFAULT_THRESHOLD,\n messenger,\n state,\n }: {\n chainId: Hex;\n preventPollingOnNetworkRestart?: boolean;\n onNetworkStateChange?: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n interval?: number;\n cacheRefreshThreshold?: number;\n messenger: TokenListMessenger;\n state?: Partial<TokenListState>;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.intervalDelay = interval;\n this.cacheRefreshThreshold = cacheRefreshThreshold;\n this.chainId = chainId;\n this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);\n this.abortController = new AbortController();\n if (onNetworkStateChange) {\n onNetworkStateChange(async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n });\n } else {\n this.messagingSystem.subscribe(\n 'NetworkController:stateChange',\n async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n },\n );\n }\n }\n\n /**\n * Updates state and restarts polling on changes to the network controller\n * state.\n *\n * @param networkControllerState - The updated network controller state.\n */\n async #onNetworkControllerStateChange(networkControllerState: NetworkState) {\n if (this.chainId !== networkControllerState.providerConfig.chainId) {\n this.abortController.abort();\n this.abortController = new AbortController();\n this.chainId = networkControllerState.providerConfig.chainId;\n if (this.state.preventPollingOnNetworkRestart) {\n this.clearingTokenListData();\n } else {\n // Ensure tokenList is referencing data from correct network\n this.update(() => {\n return {\n ...this.state,\n tokenList: this.state.tokensChainsCache[this.chainId]?.data || {},\n };\n });\n await this.restart();\n }\n }\n }\n\n /**\n * Start polling for the token list.\n */\n async start() {\n if (!isTokenListSupportedForNetwork(this.chainId)) {\n return;\n }\n await this.startPolling();\n }\n\n /**\n * Restart polling for the token list.\n */\n async restart() {\n this.stopPolling();\n await this.startPolling();\n }\n\n /**\n * Stop polling for the token list.\n */\n stop() {\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 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<void> {\n await safelyExecute(() => this.fetchTokenList());\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this.fetchTokenList());\n }, this.intervalDelay);\n }\n\n /**\n * Fetching token list from the Token Service API.\n */\n async fetchTokenList(): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n try {\n const { tokensChainsCache } = this.state;\n let tokenList: TokenListMap = {};\n const cachedTokens: TokenListMap = await safelyExecute(() =>\n this.fetchFromCache(),\n );\n if (cachedTokens) {\n // Use non-expired cached tokens\n tokenList = { ...cachedTokens };\n } else {\n // Fetch fresh token list\n const tokensFromAPI: TokenListToken[] = await safelyExecute(() =>\n fetchTokenList(this.chainId, this.abortController.signal),\n );\n\n if (!tokensFromAPI) {\n // Fallback to expired cached tokens\n tokenList = { ...(tokensChainsCache[this.chainId]?.data || {}) };\n\n this.update(() => {\n return {\n ...this.state,\n tokenList,\n tokensChainsCache,\n };\n });\n return;\n }\n // Filtering out tokens with less than 3 occurrences and native tokens\n const filteredTokenList = tokensFromAPI.filter(\n (token) =>\n token.occurrences &&\n token.occurrences >= 3 &&\n token.address !== '0x0000000000000000000000000000000000000000',\n );\n // Removing the tokens with symbol conflicts\n const symbolsList = filteredTokenList.map((token) => token.symbol);\n const duplicateSymbols = [\n ...new Set(\n symbolsList.filter(\n (symbol, index) => symbolsList.indexOf(symbol) !== index,\n ),\n ),\n ];\n const uniqueTokenList = filteredTokenList.filter(\n (token) => !duplicateSymbols.includes(token.symbol),\n );\n for (const token of uniqueTokenList) {\n const formattedToken: TokenListToken = {\n ...token,\n aggregators: formatAggregatorNames(token.aggregators),\n iconUrl: formatIconUrlWithProxy({\n chainId: this.chainId,\n tokenAddress: token.address,\n }),\n };\n tokenList[token.address] = formattedToken;\n }\n }\n const updatedTokensChainsCache: TokensChainsCache = {\n ...tokensChainsCache,\n [this.chainId]: {\n timestamp: Date.now(),\n data: tokenList,\n },\n };\n this.update(() => {\n return {\n ...this.state,\n tokenList,\n tokensChainsCache: updatedTokensChainsCache,\n };\n });\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Checks if the Cache timestamp is valid,\n * if yes data in cache will be returned\n * otherwise null will be returned.\n *\n * @returns The cached data, or `null` if the cache was expired.\n */\n async fetchFromCache(): Promise<TokenListMap | null> {\n const { tokensChainsCache }: TokenListState = this.state;\n const dataCache = tokensChainsCache[this.chainId];\n const now = Date.now();\n if (\n dataCache?.data &&\n now - dataCache?.timestamp < this.cacheRefreshThreshold\n ) {\n return dataCache.data;\n }\n return null;\n }\n\n /**\n * Clearing tokenList and tokensChainsCache explicitly.\n */\n clearingTokenListData(): void {\n this.update(() => {\n return {\n ...this.state,\n tokenList: {},\n tokensChainsCache: {},\n };\n });\n }\n\n /**\n * Updates preventPollingOnNetworkRestart from extension.\n *\n * @param shouldPreventPolling - Determine whether to prevent polling on network change\n */\n updatePreventPollingOnNetworkRestart(shouldPreventPolling: boolean): void {\n this.update(() => {\n return {\n ...this.state,\n preventPollingOnNetworkRestart: shouldPreventPolling,\n };\n });\n }\n}\n\nexport default TokenListController;\n"]}
|
|
1
|
+
{"version":3,"file":"TokenListController.js","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport type {\n NetworkClientId,\n NetworkControllerStateChangeEvent,\n NetworkState,\n NetworkControllerGetNetworkClientByIdAction,\n} from '@metamask/network-controller';\nimport { PollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport type { Patch } from 'immer';\n\nimport {\n isTokenListSupportedForNetwork,\n formatAggregatorNames,\n formatIconUrlWithProxy,\n} from './assetsUtil';\nimport { fetchTokenListByChainId } from './token-service';\n\nconst DEFAULT_INTERVAL = 24 * 60 * 60 * 1000;\nconst DEFAULT_THRESHOLD = 24 * 60 * 60 * 1000;\n\nconst name = 'TokenListController';\n\nexport type TokenListToken = {\n name: string;\n symbol: string;\n decimals: number;\n address: string;\n occurrences: number;\n aggregators: string[];\n iconUrl: string;\n};\n\nexport type TokenListMap = Record<string, TokenListToken>;\n\ntype DataCache = {\n timestamp: number;\n data: TokenListMap;\n};\ntype TokensChainsCache = {\n [chainId: Hex]: DataCache;\n};\n\nexport type TokenListState = {\n tokenList: TokenListMap;\n tokensChainsCache: TokensChainsCache;\n preventPollingOnNetworkRestart: boolean;\n};\n\nexport type TokenListStateChange = {\n type: `${typeof name}:stateChange`;\n payload: [TokenListState, Patch[]];\n};\n\nexport type GetTokenListState = {\n type: `${typeof name}:getState`;\n handler: () => TokenListState;\n};\ntype TokenListMessenger = RestrictedControllerMessenger<\n typeof name,\n GetTokenListState | NetworkControllerGetNetworkClientByIdAction,\n TokenListStateChange | NetworkControllerStateChangeEvent,\n NetworkControllerGetNetworkClientByIdAction['type'],\n TokenListStateChange['type'] | NetworkControllerStateChangeEvent['type']\n>;\n\nconst metadata = {\n tokenList: { persist: true, anonymous: true },\n tokensChainsCache: { persist: true, anonymous: true },\n preventPollingOnNetworkRestart: { persist: true, anonymous: true },\n};\n\nconst defaultState: TokenListState = {\n tokenList: {},\n tokensChainsCache: {},\n preventPollingOnNetworkRestart: false,\n};\n\n/**\n * Controller that passively polls on a set interval for the list of tokens from metaswaps api\n */\nexport class TokenListController extends PollingController<\n typeof name,\n TokenListState,\n TokenListMessenger\n> {\n private readonly mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay: number;\n\n private readonly cacheRefreshThreshold: number;\n\n private chainId: Hex;\n\n private abortController: AbortController;\n\n /**\n * Creates a TokenListController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onNetworkStateChange - A function for registering an event handler for network state changes.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.cacheRefreshThreshold - The token cache expiry time, in milliseconds.\n * @param options.messenger - A restricted controller messenger.\n * @param options.state - Initial state to set on this controller.\n * @param options.preventPollingOnNetworkRestart - Determines whether to prevent poilling on network restart in extension.\n */\n constructor({\n chainId,\n preventPollingOnNetworkRestart = false,\n onNetworkStateChange,\n interval = DEFAULT_INTERVAL,\n cacheRefreshThreshold = DEFAULT_THRESHOLD,\n messenger,\n state,\n }: {\n chainId: Hex;\n preventPollingOnNetworkRestart?: boolean;\n onNetworkStateChange?: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n interval?: number;\n cacheRefreshThreshold?: number;\n messenger: TokenListMessenger;\n state?: Partial<TokenListState>;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.intervalDelay = interval;\n this.cacheRefreshThreshold = cacheRefreshThreshold;\n this.chainId = chainId;\n this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);\n this.abortController = new AbortController();\n if (onNetworkStateChange) {\n onNetworkStateChange(async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n });\n } else {\n this.messagingSystem.subscribe(\n 'NetworkController:stateChange',\n async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n },\n );\n }\n }\n\n /**\n * Updates state and restarts polling on changes to the network controller\n * state.\n *\n * @param networkControllerState - The updated network controller state.\n */\n async #onNetworkControllerStateChange(networkControllerState: NetworkState) {\n if (this.chainId !== networkControllerState.providerConfig.chainId) {\n this.abortController.abort();\n this.abortController = new AbortController();\n this.chainId = networkControllerState.providerConfig.chainId;\n if (this.state.preventPollingOnNetworkRestart) {\n this.clearingTokenListData();\n } else {\n // Ensure tokenList is referencing data from correct network\n this.update(() => {\n return {\n ...this.state,\n tokenList: this.state.tokensChainsCache[this.chainId]?.data || {},\n };\n });\n await this.restart();\n }\n }\n }\n\n /**\n * Start polling for the token list.\n */\n async start() {\n if (!isTokenListSupportedForNetwork(this.chainId)) {\n return;\n }\n await this.startPolling();\n }\n\n /**\n * Restart polling for the token list.\n */\n async restart() {\n this.stopPolling();\n await this.startPolling();\n }\n\n /**\n * Stop polling for the token list.\n */\n stop() {\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 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<void> {\n await safelyExecute(() => this.fetchTokenList());\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this.fetchTokenList());\n }, this.intervalDelay);\n }\n\n /**\n * Fetching token list from the Token Service API.\n *\n * @private\n * @param networkClientId - The ID of the network client triggering the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll(networkClientId: string): Promise<void> {\n return this.fetchTokenList(networkClientId);\n }\n\n /**\n * Fetching token list from the Token Service API.\n *\n * @param networkClientId - The ID of the network client triggering the fetch.\n */\n async fetchTokenList(networkClientId?: NetworkClientId): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n let networkClient;\n if (networkClientId) {\n networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n }\n const chainId = networkClient?.configuration.chainId ?? this.chainId;\n try {\n const { tokensChainsCache } = this.state;\n let tokenList: TokenListMap = {};\n const cachedTokens: TokenListMap = await safelyExecute(() =>\n this.#fetchFromCache(chainId),\n );\n if (cachedTokens) {\n // Use non-expired cached tokens\n tokenList = { ...cachedTokens };\n } else {\n // Fetch fresh token list\n const tokensFromAPI: TokenListToken[] = await safelyExecute(() => {\n return fetchTokenListByChainId(chainId, this.abortController.signal);\n });\n if (!tokensFromAPI) {\n // Fallback to expired cached tokens\n tokenList = { ...(tokensChainsCache[chainId]?.data || {}) };\n this.update(() => {\n return {\n ...this.state,\n tokenList,\n tokensChainsCache,\n };\n });\n return;\n }\n // Filtering out tokens with less than 3 occurrences and native tokens\n const filteredTokenList = tokensFromAPI.filter(\n (token) =>\n token.occurrences &&\n token.occurrences >= 3 &&\n token.address !== '0x0000000000000000000000000000000000000000',\n );\n // Removing the tokens with symbol conflicts\n const symbolsList = filteredTokenList.map((token) => token.symbol);\n const duplicateSymbols = [\n ...new Set(\n symbolsList.filter(\n (symbol, index) => symbolsList.indexOf(symbol) !== index,\n ),\n ),\n ];\n const uniqueTokenList = filteredTokenList.filter(\n (token) => !duplicateSymbols.includes(token.symbol),\n );\n for (const token of uniqueTokenList) {\n const formattedToken: TokenListToken = {\n ...token,\n aggregators: formatAggregatorNames(token.aggregators),\n iconUrl: formatIconUrlWithProxy({\n chainId,\n tokenAddress: token.address,\n }),\n };\n tokenList[token.address] = formattedToken;\n }\n }\n const updatedTokensChainsCache: TokensChainsCache = {\n ...tokensChainsCache,\n [chainId]: {\n timestamp: Date.now(),\n data: tokenList,\n },\n };\n this.update(() => {\n return {\n ...this.state,\n tokenList,\n tokensChainsCache: updatedTokensChainsCache,\n };\n });\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Checks if the Cache timestamp is valid,\n * if yes data in cache will be returned\n * otherwise null will be returned.\n * @param chainId - The chain ID of the network for which to fetch the cache.\n * @returns The cached data, or `null` if the cache was expired.\n */\n async #fetchFromCache(chainId: Hex): Promise<TokenListMap | null> {\n const { tokensChainsCache }: TokenListState = this.state;\n const dataCache = tokensChainsCache[chainId];\n const now = Date.now();\n if (\n dataCache?.data &&\n now - dataCache?.timestamp < this.cacheRefreshThreshold\n ) {\n return dataCache.data;\n }\n return null;\n }\n\n /**\n * Clearing tokenList and tokensChainsCache explicitly.\n */\n clearingTokenListData(): void {\n this.update(() => {\n return {\n ...this.state,\n tokenList: {},\n tokensChainsCache: {},\n };\n });\n }\n\n /**\n * Updates preventPollingOnNetworkRestart from extension.\n *\n * @param shouldPreventPolling - Determine whether to prevent polling on network change\n */\n updatePreventPollingOnNetworkRestart(shouldPreventPolling: boolean): void {\n this.update(() => {\n return {\n ...this.state,\n preventPollingOnNetworkRestart: shouldPreventPolling,\n };\n });\n }\n}\n\nexport default TokenListController;\n"]}
|
package/dist/assetsUtil.d.ts
CHANGED
|
@@ -47,7 +47,9 @@ export declare enum SupportedTokenDetectionNetworks {
|
|
|
47
47
|
bsc = "0x38",
|
|
48
48
|
polygon = "0x89",
|
|
49
49
|
avax = "0xa86a",
|
|
50
|
-
aurora = "0x4e454152"
|
|
50
|
+
aurora = "0x4e454152",
|
|
51
|
+
linea_goerli = "0xe704",
|
|
52
|
+
linea_mainnet = "0xe708"
|
|
51
53
|
}
|
|
52
54
|
/**
|
|
53
55
|
* Check if token detection is enabled for certain networks.
|
package/dist/assetsUtil.d.ts.map
CHANGED
|
@@ -1 +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;
|
|
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;IACrB,YAAY,WAAW;IACvB,aAAa,WAAW;CACzB;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"}
|
package/dist/assetsUtil.js
CHANGED
|
@@ -121,6 +121,8 @@ var SupportedTokenDetectionNetworks;
|
|
|
121
121
|
SupportedTokenDetectionNetworks["polygon"] = "0x89";
|
|
122
122
|
SupportedTokenDetectionNetworks["avax"] = "0xa86a";
|
|
123
123
|
SupportedTokenDetectionNetworks["aurora"] = "0x4e454152";
|
|
124
|
+
SupportedTokenDetectionNetworks["linea_goerli"] = "0xe704";
|
|
125
|
+
SupportedTokenDetectionNetworks["linea_mainnet"] = "0xe708";
|
|
124
126
|
})(SupportedTokenDetectionNetworks = exports.SupportedTokenDetectionNetworks || (exports.SupportedTokenDetectionNetworks = {}));
|
|
125
127
|
/**
|
|
126
128
|
* Check if token detection is enabled for certain networks.
|
package/dist/assetsUtil.js.map
CHANGED
|
@@ -1 +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<string, string> = {\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<Hex>(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"]}
|
|
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<string, string> = {\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}\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<Hex>(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"]}
|
package/dist/token-service.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare const TOKEN_METADATA_NO_SUPPORT_ERROR = "TokenService Error: Netw
|
|
|
11
11
|
* @param options.timeout - The fetch timeout.
|
|
12
12
|
* @returns The token list, or `undefined` if the request was cancelled.
|
|
13
13
|
*/
|
|
14
|
-
export declare function
|
|
14
|
+
export declare function fetchTokenListByChainId(chainId: Hex, abortSignal: AbortSignal, { timeout }?: {
|
|
15
15
|
timeout?: number | undefined;
|
|
16
16
|
}): Promise<unknown>;
|
|
17
17
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-service.d.ts","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAI3C,eAAO,MAAM,mBAAmB,8CAA8C,CAAC;AAC/E,eAAO,MAAM,+BAA+B,oEACuB,CAAC;AA+BpE;;;;;;;;;GASG;AACH,wBAAsB,
|
|
1
|
+
{"version":3,"file":"token-service.d.ts","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAI3C,eAAO,MAAM,mBAAmB,8CAA8C,CAAC;AAC/E,eAAO,MAAM,+BAA+B,oEACuB,CAAC;AA+BpE;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,GAAG,EACZ,WAAW,EAAE,WAAW,EACxB,EAAE,OAAwB,EAAE;;CAAK,GAChC,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,WAAW,EACxB,EAAE,OAAwB,EAAE;;CAAK,GAChC,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAUxB"}
|
package/dist/token-service.js
CHANGED
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.fetchTokenMetadata = exports.
|
|
12
|
+
exports.fetchTokenMetadata = exports.fetchTokenListByChainId = exports.TOKEN_METADATA_NO_SUPPORT_ERROR = exports.TOKEN_END_POINT_API = void 0;
|
|
13
13
|
const controller_utils_1 = require("@metamask/controller-utils");
|
|
14
14
|
const assetsUtil_1 = require("./assetsUtil");
|
|
15
15
|
exports.TOKEN_END_POINT_API = 'https://token-api.metaswap.codefi.network';
|
|
@@ -47,7 +47,7 @@ const defaultTimeout = tenSecondsInMilliseconds;
|
|
|
47
47
|
* @param options.timeout - The fetch timeout.
|
|
48
48
|
* @returns The token list, or `undefined` if the request was cancelled.
|
|
49
49
|
*/
|
|
50
|
-
function
|
|
50
|
+
function fetchTokenListByChainId(chainId, abortSignal, { timeout = defaultTimeout } = {}) {
|
|
51
51
|
return __awaiter(this, void 0, void 0, function* () {
|
|
52
52
|
const tokenURL = getTokensURL(chainId);
|
|
53
53
|
const response = yield queryApi(tokenURL, abortSignal, timeout);
|
|
@@ -57,7 +57,7 @@ function fetchTokenList(chainId, abortSignal, { timeout = defaultTimeout } = {})
|
|
|
57
57
|
return undefined;
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
|
-
exports.
|
|
60
|
+
exports.fetchTokenListByChainId = fetchTokenListByChainId;
|
|
61
61
|
/**
|
|
62
62
|
* Fetch metadata for the token address provided for a given network. This request is cancellable
|
|
63
63
|
* using the abort signal passed in.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-service.js","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,iEAA+E;AAG/E,6CAA8D;AAEjD,QAAA,mBAAmB,GAAG,2CAA2C,CAAC;AAClE,QAAA,+BAA+B,GAC1C,iEAAiE,CAAC;AAEpE;;;;;GAKG;AACH,SAAS,YAAY,CAAC,OAAY;IAChC,OAAO,GAAG,2BAAmB,WAAW,IAAA,sCAAmB,EAAC,OAAO,CAAC,EAAE,CAAC;AACzE,CAAC;AAED;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAC,OAAY,EAAE,YAAoB;IAC7D,OAAO,GAAG,2BAAmB,UAAU,IAAA,sCAAmB,EACxD,OAAO,CACR,YAAY,YAAY,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,wBAAwB,GAAG,KAAM,CAAC;AAExC,qCAAqC;AACrC,yGAAyG;AACzG,MAAM,cAAc,GAAG,wBAAwB,CAAC;AAEhD;;;;;;;;;GASG;AACH,SAAsB,
|
|
1
|
+
{"version":3,"file":"token-service.js","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { convertHexToDecimal, timeoutFetch } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\n\nimport { isTokenListSupportedForNetwork } from './assetsUtil';\n\nexport const TOKEN_END_POINT_API = 'https://token-api.metaswap.codefi.network';\nexport const TOKEN_METADATA_NO_SUPPORT_ERROR =\n 'TokenService Error: Network does not support fetchTokenMetadata';\n\n/**\n * Get the tokens URL for a specific network.\n *\n * @param chainId - The chain ID of the network the tokens requested are on.\n * @returns The tokens URL.\n */\nfunction getTokensURL(chainId: Hex) {\n return `${TOKEN_END_POINT_API}/tokens/${convertHexToDecimal(chainId)}`;\n}\n\n/**\n * Get the token metadata URL for the given network and token.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The token address.\n * @returns The token metadata URL.\n */\nfunction getTokenMetadataURL(chainId: Hex, tokenAddress: string) {\n return `${TOKEN_END_POINT_API}/token/${convertHexToDecimal(\n chainId,\n )}?address=${tokenAddress}`;\n}\n\nconst tenSecondsInMilliseconds = 10_000;\n\n// Token list averages 1.6 MB in size\n// timeoutFetch by default has a 500ms timeout, which will almost always timeout given the response size.\nconst defaultTimeout = tenSecondsInMilliseconds;\n\n/**\n * Fetch the list of token metadata for a given network. This request is cancellable using the\n * abort signal passed in.\n *\n * @param chainId - The chain ID of the network the requested tokens are on.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token list, or `undefined` if the request was cancelled.\n */\nexport async function fetchTokenListByChainId(\n chainId: Hex,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<unknown> {\n const tokenURL = getTokensURL(chainId);\n const response = await queryApi(tokenURL, abortSignal, timeout);\n if (response) {\n return parseJsonResponse(response);\n }\n return undefined;\n}\n\n/**\n * Fetch metadata for the token address provided for a given network. This request is cancellable\n * using the abort signal passed in.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The address of the token to fetch metadata for.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token metadata, or `undefined` if the request was either aborted or failed.\n */\nexport async function fetchTokenMetadata<T>(\n chainId: Hex,\n tokenAddress: string,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<T | undefined> {\n if (!isTokenListSupportedForNetwork(chainId)) {\n throw new Error(TOKEN_METADATA_NO_SUPPORT_ERROR);\n }\n const tokenMetadataURL = getTokenMetadataURL(chainId, tokenAddress);\n const response = await queryApi(tokenMetadataURL, abortSignal, timeout);\n if (response) {\n return parseJsonResponse(response) as Promise<T>;\n }\n return undefined;\n}\n\n/**\n * Perform fetch request against the api.\n *\n * @param apiURL - The URL of the API to fetch.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param timeout - The fetch timeout.\n * @returns Promise resolving request response.\n */\nasync function queryApi(\n apiURL: string,\n abortSignal: AbortSignal,\n timeout: number,\n): Promise<Response | undefined> {\n const fetchOptions: RequestInit = {\n referrer: apiURL,\n referrerPolicy: 'no-referrer-when-downgrade',\n method: 'GET',\n mode: 'cors',\n signal: abortSignal,\n cache: 'default',\n };\n fetchOptions.headers = new window.Headers();\n fetchOptions.headers.set('Content-Type', 'application/json');\n try {\n return await timeoutFetch(apiURL, fetchOptions, timeout);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n console.log('Request is aborted');\n }\n }\n return undefined;\n}\n\n/**\n * Parse an API response and return the response JSON data.\n *\n * @param apiResponse - The API response to parse.\n * @returns The response JSON data.\n * @throws Will throw if the response includes an error.\n */\nasync function parseJsonResponse(apiResponse: Response): Promise<unknown> {\n const responseObj = await apiResponse.json();\n // api may return errors as json without setting an error http status code\n if (responseObj?.error) {\n throw new Error(`TokenService Error: ${responseObj.error}`);\n }\n return responseObj;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask/assets-controllers",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "16.0.0",
|
|
4
4
|
"description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|
|
@@ -34,15 +34,16 @@
|
|
|
34
34
|
"@ethersproject/contracts": "^5.7.0",
|
|
35
35
|
"@ethersproject/providers": "^5.7.0",
|
|
36
36
|
"@metamask/abi-utils": "^2.0.2",
|
|
37
|
-
"@metamask/approval-controller": "^4.0.
|
|
37
|
+
"@metamask/approval-controller": "^4.0.1",
|
|
38
38
|
"@metamask/base-controller": "^3.2.3",
|
|
39
39
|
"@metamask/contract-metadata": "^2.3.1",
|
|
40
40
|
"@metamask/controller-utils": "^5.0.2",
|
|
41
41
|
"@metamask/eth-query": "^3.0.1",
|
|
42
42
|
"@metamask/metamask-eth-abis": "3.0.0",
|
|
43
|
-
"@metamask/network-controller": "^
|
|
44
|
-
"@metamask/
|
|
45
|
-
"@metamask/
|
|
43
|
+
"@metamask/network-controller": "^15.0.0",
|
|
44
|
+
"@metamask/polling-controller": "^0.2.0",
|
|
45
|
+
"@metamask/preferences-controller": "^4.4.3",
|
|
46
|
+
"@metamask/rpc-errors": "^6.1.0",
|
|
46
47
|
"@metamask/utils": "^8.1.0",
|
|
47
48
|
"@types/uuid": "^8.3.0",
|
|
48
49
|
"async-mutex": "^0.2.6",
|
|
@@ -68,9 +69,9 @@
|
|
|
68
69
|
"typescript": "~4.8.4"
|
|
69
70
|
},
|
|
70
71
|
"peerDependencies": {
|
|
71
|
-
"@metamask/approval-controller": "^4.0.
|
|
72
|
-
"@metamask/network-controller": "^
|
|
73
|
-
"@metamask/preferences-controller": "^4.4.
|
|
72
|
+
"@metamask/approval-controller": "^4.0.1",
|
|
73
|
+
"@metamask/network-controller": "^15.0.0",
|
|
74
|
+
"@metamask/preferences-controller": "^4.4.3"
|
|
74
75
|
},
|
|
75
76
|
"engines": {
|
|
76
77
|
"node": ">=16.0.0"
|