@metamask/assets-controllers 1.0.1 → 3.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 CHANGED
@@ -6,6 +6,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [3.0.0]
10
+ ### Changed
11
+ - **BREAKING:** A new private property, controlled by the `start` and `stop` methods, is added to the CurrencyRateController: `enabled`. When this is false, no network requests will be made from the controller. Previously, setNativeCurrency or setCurrentCurrency would trigger a network request. That is now prevented if `enabled` is false. ([#1002](https://github.com/MetaMask/controllers/pull/1002))
12
+
13
+ ### Fixed
14
+ - The TokenRatesController no longer overwrites the `disabled` config property passed to the constructor, allowing the controller to be instantiated with `config.disabled` set to either true or false. ([#1002](https://github.com/MetaMask/controllers/pull/1002))
15
+ - This package will now warn if a required package is not present ([#1003](https://github.com/MetaMask/controllers/pull/1003))
16
+
17
+ ## [2.0.0]
18
+ ### Changed
19
+ - **BREAKING:** Update `onNetworkStateChange`, a constructor option for several controllers, to take an object with a `providerConfig` property instead of `provider` ([#995](https://github.com/MetaMask/controllers/pull/995))
20
+ - This affects:
21
+ - AssetsContractController
22
+ - NftController
23
+ - NftDetectionController
24
+ - TokenDetectionController
25
+ - TokenListController
26
+ - TokenRatesController
27
+ - TokenController
28
+ - **BREAKING:** [TokenDetectionController] Update `getNetworkState` constructor option to take an object with `providerConfig` property rather than `providerConfig` ([#995](https://github.com/MetaMask/controllers/pull/995))
29
+ - Relax dependencies on `@metamask/base-controller`, `@metamask/controller-utils`, `@metamask/network-controller`, and `@metamask/preferences-controller` (use `^` instead of `~`) ([#998](https://github.com/MetaMask/controllers/pull/998))
30
+
9
31
  ## [1.0.1]
10
32
  ### Fixed
11
33
  - Fix race condition where some token detections can get mistakenly added to the wrong account ([#956](https://github.com/MetaMask/controllers/pull/956))
@@ -22,6 +44,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
22
44
  ### Changed
23
45
  - Use Ethers for AssetsContractController ([#845](https://github.com/MetaMask/controllers/pull/845))
24
46
 
25
- [Unreleased]: https://github.com/MetaMask/controllers/compare/@metamask/assets-controllers@1.0.1...HEAD
47
+ [Unreleased]: https://github.com/MetaMask/controllers/compare/@metamask/assets-controllers@3.0.0...HEAD
48
+ [3.0.0]: https://github.com/MetaMask/controllers/compare/@metamask/assets-controllers@2.0.0...@metamask/assets-controllers@3.0.0
49
+ [2.0.0]: https://github.com/MetaMask/controllers/compare/@metamask/assets-controllers@1.0.1...@metamask/assets-controllers@2.0.0
26
50
  [1.0.1]: https://github.com/MetaMask/controllers/compare/@metamask/assets-controllers@1.0.0...@metamask/assets-controllers@1.0.1
27
51
  [1.0.0]: https://github.com/MetaMask/controllers/releases/tag/@metamask/assets-controllers@1.0.0
@@ -64,9 +64,9 @@ class AssetsContractController extends base_controller_1.BaseController {
64
64
  this.configure({ ipfsGateway });
65
65
  });
66
66
  onNetworkStateChange((networkState) => {
67
- if (this.config.chainId !== networkState.provider.chainId) {
67
+ if (this.config.chainId !== networkState.providerConfig.chainId) {
68
68
  this.configure({
69
- chainId: networkState.provider.chainId,
69
+ chainId: networkState.providerConfig.chainId,
70
70
  });
71
71
  }
72
72
  });
@@ -1 +1 @@
1
- {"version":3,"file":"AssetsContractController.js","sourceRoot":"","sources":["../src/AssetsContractController.ts"],"names":[],"mappings":"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","sourcesContent":["import { BN } from 'ethereumjs-util';\nimport abiSingleCallBalancesContract from 'single-call-balance-checker-abi';\nimport { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport {\n BaseController,\n BaseConfig,\n BaseState,\n} from '@metamask/base-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport { IPFS_DEFAULT_GATEWAY_URL } from '@metamask/controller-utils';\nimport { NetworkState } from '@metamask/network-controller';\nimport { SupportedTokenDetectionNetworks } from './assetsUtil';\nimport { ERC721Standard } from './Standards/NftStandards/ERC721/ERC721Standard';\nimport { ERC1155Standard } from './Standards/NftStandards/ERC1155/ERC1155Standard';\nimport { ERC20Standard } from './Standards/ERC20Standard';\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<string, string> = {\n [SupportedTokenDetectionNetworks.mainnet]:\n '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39',\n [SupportedTokenDetectionNetworks.bsc]:\n '0x2352c63A83f9Fd126af8676146721Fa00924d7e4',\n [SupportedTokenDetectionNetworks.polygon]:\n '0x2352c63A83f9Fd126af8676146721Fa00924d7e4',\n [SupportedTokenDetectionNetworks.avax]:\n '0xD023D153a0DFa485130ECFdE2FAA7e612EF94818',\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: string;\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?: Web3Provider;\n\n private erc721Standard?: ERC721Standard;\n\n private erc1155Standard?: ERC1155Standard;\n\n private erc20Standard?: ERC20Standard;\n\n /**\n * Name of this controller used during composition\n */\n override name = 'AssetsContractController';\n\n /**\n * Creates a AssetsContractController instance.\n *\n * @param options - The controller options.\n * @param options.onPreferencesStateChange - Allows subscribing to preference controller state changes.\n * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.\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 onPreferencesStateChange,\n onNetworkStateChange,\n }: {\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\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: SupportedTokenDetectionNetworks.mainnet,\n };\n this.initialize();\n\n onPreferencesStateChange(({ ipfsGateway }) => {\n this.configure({ ipfsGateway });\n });\n\n onNetworkStateChange((networkState) => {\n if (this.config.chainId !== networkState.provider.chainId) {\n this.configure({\n chainId: networkState.provider.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 = new Web3Provider(provider);\n this.erc721Standard = new ERC721Standard(this._provider);\n this.erc1155Standard = new ERC1155Standard(this._provider);\n this.erc20Standard = new ERC20Standard(this._provider);\n }\n\n get provider() {\n throw new Error('Property only used for setting');\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 * @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 ): Promise<BN> {\n if (!this.erc20Standard) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @returns Promise resolving to the 'decimals'.\n */\n async getERC20TokenDecimals(address: string): Promise<string> {\n if (this.erc20Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return await this.erc20Standard.getTokenDecimals(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 * @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 ): Promise<string> {\n if (this.erc721Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @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 ): 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 if (\n this.erc721Standard === undefined ||\n this.erc1155Standard === undefined ||\n this.erc20Standard === undefined\n ) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n\n const { ipfsGateway } = this.config;\n\n // ERC721\n try {\n return {\n ...(await this.erc721Standard.getDetails(\n tokenAddress,\n ipfsGateway,\n tokenId,\n )),\n };\n } catch {\n // Ignore\n }\n\n // ERC1155\n try {\n return {\n ...(await this.erc1155Standard.getDetails(\n tokenAddress,\n ipfsGateway,\n tokenId,\n )),\n };\n } catch {\n // Ignore\n }\n\n // ERC20\n try {\n return {\n ...(await this.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 * @returns Promise resolving to the 'tokenURI'.\n */\n async getERC721TokenURI(address: string, tokenId: string): Promise<string> {\n if (this.erc721Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @returns Promise resolving to the 'name'.\n */\n async getERC721AssetName(address: string): Promise<string> {\n if (this.erc721Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @returns Promise resolving to the 'symbol'.\n */\n async getERC721AssetSymbol(address: string): Promise<string> {\n if (this.erc721Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @returns Promise resolving to the owner address.\n */\n async getERC721OwnerOf(address: string, tokenId: string): Promise<string> {\n if (this.erc721Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @returns Promise resolving to the 'tokenURI'.\n */\n async getERC1155TokenURI(address: string, tokenId: string): Promise<string> {\n if (this.erc1155Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @returns Promise resolving to the 'balanceOf'.\n */\n async getERC1155BalanceOf(\n userAddress: string,\n nftAddress: string,\n nftId: string,\n ): Promise<BN> {\n if (this.erc1155Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return await this.erc1155Standard.getBalanceOf(\n nftAddress,\n userAddress,\n nftId,\n );\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 * @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 ): Promise<void> {\n if (this.erc1155Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return await this.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 * @returns The list of non-zero token balances.\n */\n async getBalancesInSingleCall(\n selectedAddress: string,\n tokensToDetect: string[],\n ) {\n if (!(this.config.chainId in SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID)) {\n // Only fetch balance if contract address exists\n return {};\n }\n const contractAddress =\n SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID[this.config.chainId];\n\n const contract = new Contract(\n contractAddress,\n abiSingleCallBalancesContract,\n this._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":"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","sourcesContent":["import { BN } from 'ethereumjs-util';\nimport abiSingleCallBalancesContract from 'single-call-balance-checker-abi';\nimport { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport {\n BaseController,\n BaseConfig,\n BaseState,\n} from '@metamask/base-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport { IPFS_DEFAULT_GATEWAY_URL } from '@metamask/controller-utils';\nimport { NetworkState } from '@metamask/network-controller';\nimport { SupportedTokenDetectionNetworks } from './assetsUtil';\nimport { ERC721Standard } from './Standards/NftStandards/ERC721/ERC721Standard';\nimport { ERC1155Standard } from './Standards/NftStandards/ERC1155/ERC1155Standard';\nimport { ERC20Standard } from './Standards/ERC20Standard';\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<string, string> = {\n [SupportedTokenDetectionNetworks.mainnet]:\n '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39',\n [SupportedTokenDetectionNetworks.bsc]:\n '0x2352c63A83f9Fd126af8676146721Fa00924d7e4',\n [SupportedTokenDetectionNetworks.polygon]:\n '0x2352c63A83f9Fd126af8676146721Fa00924d7e4',\n [SupportedTokenDetectionNetworks.avax]:\n '0xD023D153a0DFa485130ECFdE2FAA7e612EF94818',\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: string;\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?: Web3Provider;\n\n private erc721Standard?: ERC721Standard;\n\n private erc1155Standard?: ERC1155Standard;\n\n private erc20Standard?: ERC20Standard;\n\n /**\n * Name of this controller used during composition\n */\n override name = 'AssetsContractController';\n\n /**\n * Creates a AssetsContractController instance.\n *\n * @param options - The controller options.\n * @param options.onPreferencesStateChange - Allows subscribing to preference controller state changes.\n * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.\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 onPreferencesStateChange,\n onNetworkStateChange,\n }: {\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\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: SupportedTokenDetectionNetworks.mainnet,\n };\n this.initialize();\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 = new Web3Provider(provider);\n this.erc721Standard = new ERC721Standard(this._provider);\n this.erc1155Standard = new ERC1155Standard(this._provider);\n this.erc20Standard = new ERC20Standard(this._provider);\n }\n\n get provider() {\n throw new Error('Property only used for setting');\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 * @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 ): Promise<BN> {\n if (!this.erc20Standard) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @returns Promise resolving to the 'decimals'.\n */\n async getERC20TokenDecimals(address: string): Promise<string> {\n if (this.erc20Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return await this.erc20Standard.getTokenDecimals(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 * @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 ): Promise<string> {\n if (this.erc721Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @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 ): 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 if (\n this.erc721Standard === undefined ||\n this.erc1155Standard === undefined ||\n this.erc20Standard === undefined\n ) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n\n const { ipfsGateway } = this.config;\n\n // ERC721\n try {\n return {\n ...(await this.erc721Standard.getDetails(\n tokenAddress,\n ipfsGateway,\n tokenId,\n )),\n };\n } catch {\n // Ignore\n }\n\n // ERC1155\n try {\n return {\n ...(await this.erc1155Standard.getDetails(\n tokenAddress,\n ipfsGateway,\n tokenId,\n )),\n };\n } catch {\n // Ignore\n }\n\n // ERC20\n try {\n return {\n ...(await this.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 * @returns Promise resolving to the 'tokenURI'.\n */\n async getERC721TokenURI(address: string, tokenId: string): Promise<string> {\n if (this.erc721Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @returns Promise resolving to the 'name'.\n */\n async getERC721AssetName(address: string): Promise<string> {\n if (this.erc721Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @returns Promise resolving to the 'symbol'.\n */\n async getERC721AssetSymbol(address: string): Promise<string> {\n if (this.erc721Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @returns Promise resolving to the owner address.\n */\n async getERC721OwnerOf(address: string, tokenId: string): Promise<string> {\n if (this.erc721Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @returns Promise resolving to the 'tokenURI'.\n */\n async getERC1155TokenURI(address: string, tokenId: string): Promise<string> {\n if (this.erc1155Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return this.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 * @returns Promise resolving to the 'balanceOf'.\n */\n async getERC1155BalanceOf(\n userAddress: string,\n nftAddress: string,\n nftId: string,\n ): Promise<BN> {\n if (this.erc1155Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return await this.erc1155Standard.getBalanceOf(\n nftAddress,\n userAddress,\n nftId,\n );\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 * @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 ): Promise<void> {\n if (this.erc1155Standard === undefined) {\n throw new Error(MISSING_PROVIDER_ERROR);\n }\n return await this.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 * @returns The list of non-zero token balances.\n */\n async getBalancesInSingleCall(\n selectedAddress: string,\n tokensToDetect: string[],\n ) {\n if (!(this.config.chainId in SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID)) {\n // Only fetch balance if contract address exists\n return {};\n }\n const contractAddress =\n SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID[this.config.chainId];\n\n const contract = new Contract(\n contractAddress,\n abiSingleCallBalancesContract,\n this._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"]}
@@ -35,6 +35,7 @@ declare type CurrencyRateMessenger = RestrictedControllerMessenger<typeof name,
35
35
  * asset to the user's preferred currency.
36
36
  */
37
37
  export declare class CurrencyRateController extends BaseControllerV2<typeof name, CurrencyRateState, CurrencyRateMessenger> {
38
+ #private;
38
39
  private mutex;
39
40
  private intervalId?;
40
41
  private intervalDelay;
@@ -8,6 +8,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
12
+ if (kind === "m") throw new TypeError("Private method is not writable");
13
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
14
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
15
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
16
+ };
17
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
18
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
19
+ 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");
20
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
21
+ };
22
+ var _CurrencyRateController_enabled;
11
23
  Object.defineProperty(exports, "__esModule", { value: true });
12
24
  exports.CurrencyRateController = void 0;
13
25
  const async_mutex_1 = require("async-mutex");
@@ -56,15 +68,21 @@ class CurrencyRateController extends base_controller_1.BaseControllerV2 {
56
68
  state: Object.assign(Object.assign({}, defaultState), state),
57
69
  });
58
70
  this.mutex = new async_mutex_1.Mutex();
71
+ /**
72
+ * A boolean that controls whether or not network requests can be made by the controller
73
+ */
74
+ _CurrencyRateController_enabled.set(this, void 0);
59
75
  this.includeUsdRate = includeUsdRate;
60
76
  this.intervalDelay = interval;
61
77
  this.fetchExchangeRate = fetchExchangeRate;
78
+ __classPrivateFieldSet(this, _CurrencyRateController_enabled, false, "f");
62
79
  }
63
80
  /**
64
81
  * Start polling for the currency rate.
65
82
  */
66
83
  start() {
67
84
  return __awaiter(this, void 0, void 0, function* () {
85
+ __classPrivateFieldSet(this, _CurrencyRateController_enabled, true, "f");
68
86
  yield this.startPolling();
69
87
  });
70
88
  }
@@ -72,6 +90,7 @@ class CurrencyRateController extends base_controller_1.BaseControllerV2 {
72
90
  * Stop polling for the currency rate.
73
91
  */
74
92
  stop() {
93
+ __classPrivateFieldSet(this, _CurrencyRateController_enabled, false, "f");
75
94
  this.stopPolling();
76
95
  }
77
96
  /**
@@ -121,9 +140,9 @@ class CurrencyRateController extends base_controller_1.BaseControllerV2 {
121
140
  return __awaiter(this, void 0, void 0, function* () {
122
141
  this.stopPolling();
123
142
  // TODO: Expose polling currency rate update errors
124
- yield (0, controller_utils_1.safelyExecute)(() => this.updateExchangeRate());
143
+ yield (0, controller_utils_1.safelyExecute)(() => __awaiter(this, void 0, void 0, function* () { return yield this.updateExchangeRate(); }));
125
144
  this.intervalId = setInterval(() => __awaiter(this, void 0, void 0, function* () {
126
- yield (0, controller_utils_1.safelyExecute)(() => this.updateExchangeRate());
145
+ yield (0, controller_utils_1.safelyExecute)(() => __awaiter(this, void 0, void 0, function* () { return yield this.updateExchangeRate(); }));
127
146
  }), this.intervalDelay);
128
147
  });
129
148
  }
@@ -134,6 +153,10 @@ class CurrencyRateController extends base_controller_1.BaseControllerV2 {
134
153
  */
135
154
  updateExchangeRate() {
136
155
  return __awaiter(this, void 0, void 0, function* () {
156
+ if (!__classPrivateFieldGet(this, _CurrencyRateController_enabled, "f")) {
157
+ console.info('[CurrencyRateController] Not updating exchange rate since network requests have been disabled');
158
+ return this.state;
159
+ }
137
160
  const releaseLock = yield this.mutex.acquire();
138
161
  const { currentCurrency: stateCurrentCurrency, nativeCurrency: stateNativeCurrency, pendingCurrentCurrency, pendingNativeCurrency, } = this.state;
139
162
  let conversionDate = null;
@@ -153,7 +176,9 @@ class CurrencyRateController extends base_controller_1.BaseControllerV2 {
153
176
  // a null conversionRate either way.
154
177
  currentCurrency !== '' &&
155
178
  nativeCurrency !== '') {
156
- ({ conversionRate, usdConversionRate } = yield this.fetchExchangeRate(currentCurrency, nativeCurrencyForExchangeRate, this.includeUsdRate));
179
+ const fetchExchangeRateResponse = yield this.fetchExchangeRate(currentCurrency, nativeCurrencyForExchangeRate, this.includeUsdRate);
180
+ conversionRate = fetchExchangeRateResponse.conversionRate;
181
+ usdConversionRate = fetchExchangeRateResponse.usdConversionRate;
157
182
  conversionDate = Date.now() / 1000;
158
183
  }
159
184
  }
@@ -189,5 +214,6 @@ class CurrencyRateController extends base_controller_1.BaseControllerV2 {
189
214
  }
190
215
  }
191
216
  exports.CurrencyRateController = CurrencyRateController;
217
+ _CurrencyRateController_enabled = new WeakMap();
192
218
  exports.default = CurrencyRateController;
193
219
  //# sourceMappingURL=CurrencyRateController.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CurrencyRateController.js","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Mutex } from 'async-mutex';\nimport type { Patch } from 'immer';\nimport {\n BaseControllerV2,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport {\n TESTNET_TICKER_SYMBOLS,\n FALL_BACK_VS_CURRENCY,\n safelyExecute,\n} from '@metamask/controller-utils';\nimport { fetchExchangeRate as defaultFetchExchangeRate } from './crypto-compare';\n\n/**\n * @type CurrencyRateState\n * @property conversionDate - Timestamp of conversion rate expressed in ms since UNIX epoch\n * @property conversionRate - Conversion rate from current base asset to the current currency\n * @property currentCurrency - Currently-active ISO 4217 currency code\n * @property nativeCurrency - Symbol for the base asset used for conversion\n * @property pendingCurrentCurrency - The currency being switched to\n * @property pendingNativeCurrency - The base asset currency being switched to\n * @property usdConversionRate - Conversion rate from usd to the current currency\n */\nexport type CurrencyRateState = {\n conversionDate: number | null;\n conversionRate: number | null;\n currentCurrency: string;\n nativeCurrency: string;\n pendingCurrentCurrency: string | null;\n pendingNativeCurrency: string | null;\n usdConversionRate: number | null;\n};\n\nconst name = 'CurrencyRateController';\n\nexport type CurrencyRateStateChange = {\n type: `${typeof name}:stateChange`;\n payload: [CurrencyRateState, Patch[]];\n};\n\nexport type GetCurrencyRateState = {\n type: `${typeof name}:getState`;\n handler: () => CurrencyRateState;\n};\n\ntype CurrencyRateMessenger = RestrictedControllerMessenger<\n typeof name,\n GetCurrencyRateState,\n CurrencyRateStateChange,\n never,\n never\n>;\n\nconst metadata = {\n conversionDate: { persist: true, anonymous: true },\n conversionRate: { persist: true, anonymous: true },\n currentCurrency: { persist: true, anonymous: true },\n nativeCurrency: { persist: true, anonymous: true },\n pendingCurrentCurrency: { persist: false, anonymous: true },\n pendingNativeCurrency: { persist: false, anonymous: true },\n usdConversionRate: { persist: true, anonymous: true },\n};\n\nconst defaultState = {\n conversionDate: 0,\n conversionRate: 0,\n currentCurrency: 'usd',\n nativeCurrency: 'ETH',\n pendingCurrentCurrency: null,\n pendingNativeCurrency: null,\n usdConversionRate: null,\n};\n\n/**\n * Controller that passively polls on a set interval for an exchange rate from the current network\n * asset to the user's preferred currency.\n */\nexport class CurrencyRateController extends BaseControllerV2<\n typeof name,\n CurrencyRateState,\n CurrencyRateMessenger\n> {\n private mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private intervalDelay;\n\n private fetchExchangeRate;\n\n private includeUsdRate;\n\n /**\n * Creates a CurrencyRateController instance.\n *\n * @param options - Constructor options.\n * @param options.includeUsdRate - Keep track of the USD rate in addition to the current currency rate.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.messenger - A reference to the messaging system.\n * @param options.state - Initial state to set on this controller.\n * @param options.fetchExchangeRate - Fetches the exchange rate from an external API. This option is primarily meant for use in unit tests.\n */\n constructor({\n includeUsdRate = false,\n interval = 180000,\n messenger,\n state,\n fetchExchangeRate = defaultFetchExchangeRate,\n }: {\n includeUsdRate?: boolean;\n interval?: number;\n messenger: CurrencyRateMessenger;\n state?: Partial<CurrencyRateState>;\n fetchExchangeRate?: typeof defaultFetchExchangeRate;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.includeUsdRate = includeUsdRate;\n this.intervalDelay = interval;\n this.fetchExchangeRate = fetchExchangeRate;\n }\n\n /**\n * Start polling for the currency rate.\n */\n async start() {\n await this.startPolling();\n }\n\n /**\n * Stop polling for the currency rate.\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 /**\n * Sets a currency to track.\n *\n * @param currentCurrency - ISO 4217 currency code.\n */\n async setCurrentCurrency(currentCurrency: string) {\n this.update((state) => {\n state.pendingCurrentCurrency = currentCurrency;\n });\n await this.updateExchangeRate();\n }\n\n /**\n * Sets a new native currency.\n *\n * @param symbol - Symbol for the base asset.\n */\n async setNativeCurrency(symbol: string) {\n this.update((state) => {\n state.pendingNativeCurrency = symbol;\n });\n await this.updateExchangeRate();\n }\n\n private stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n }\n\n /**\n * Starts a new polling interval.\n */\n private async startPolling(): Promise<void> {\n this.stopPolling();\n // TODO: Expose polling currency rate update errors\n await safelyExecute(() => this.updateExchangeRate());\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this.updateExchangeRate());\n }, this.intervalDelay);\n }\n\n /**\n * Updates exchange rate for the current currency.\n *\n * @returns The controller state.\n */\n async updateExchangeRate(): Promise<CurrencyRateState | void> {\n const releaseLock = await this.mutex.acquire();\n const {\n currentCurrency: stateCurrentCurrency,\n nativeCurrency: stateNativeCurrency,\n pendingCurrentCurrency,\n pendingNativeCurrency,\n } = this.state;\n\n let conversionDate: number | null = null;\n let conversionRate: number | null = null;\n let usdConversionRate: number | null = null;\n const currentCurrency = pendingCurrentCurrency ?? stateCurrentCurrency;\n const nativeCurrency = pendingNativeCurrency ?? stateNativeCurrency;\n\n // For preloaded testnets (Rinkeby, Ropsten, Goerli, Kovan) we want to fetch exchange rate for real ETH.\n const nativeCurrencyForExchangeRate = Object.values(\n TESTNET_TICKER_SYMBOLS,\n ).includes(nativeCurrency)\n ? FALL_BACK_VS_CURRENCY // ETH\n : nativeCurrency;\n\n try {\n if (\n currentCurrency &&\n nativeCurrency &&\n // if either currency is an empty string we can skip the comparison\n // because it will result in an error from the api and ultimately\n // a null conversionRate either way.\n currentCurrency !== '' &&\n nativeCurrency !== ''\n ) {\n ({ conversionRate, usdConversionRate } = await this.fetchExchangeRate(\n currentCurrency,\n nativeCurrencyForExchangeRate,\n this.includeUsdRate,\n ));\n conversionDate = Date.now() / 1000;\n }\n } catch (error) {\n if (\n !(\n error instanceof Error &&\n error.message.includes('market does not exist for this coin pair')\n )\n ) {\n throw error;\n }\n } finally {\n try {\n this.update(() => {\n return {\n conversionDate,\n conversionRate,\n // we currently allow and handle an empty string as a valid nativeCurrency\n // in cases where a user has not entered a native ticker symbol for a custom network\n // currentCurrency is not from user input but this protects us from unexpected changes.\n nativeCurrency,\n currentCurrency,\n pendingCurrentCurrency: null,\n pendingNativeCurrency: null,\n usdConversionRate,\n };\n });\n } finally {\n releaseLock();\n }\n }\n return this.state;\n }\n}\n\nexport default CurrencyRateController;\n"]}
1
+ {"version":3,"file":"CurrencyRateController.js","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Mutex } from 'async-mutex';\nimport type { Patch } from 'immer';\nimport {\n BaseControllerV2,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport {\n TESTNET_TICKER_SYMBOLS,\n FALL_BACK_VS_CURRENCY,\n safelyExecute,\n} from '@metamask/controller-utils';\nimport { fetchExchangeRate as defaultFetchExchangeRate } from './crypto-compare';\n\n/**\n * @type CurrencyRateState\n * @property conversionDate - Timestamp of conversion rate expressed in ms since UNIX epoch\n * @property conversionRate - Conversion rate from current base asset to the current currency\n * @property currentCurrency - Currently-active ISO 4217 currency code\n * @property nativeCurrency - Symbol for the base asset used for conversion\n * @property pendingCurrentCurrency - The currency being switched to\n * @property pendingNativeCurrency - The base asset currency being switched to\n * @property usdConversionRate - Conversion rate from usd to the current currency\n */\nexport type CurrencyRateState = {\n conversionDate: number | null;\n conversionRate: number | null;\n currentCurrency: string;\n nativeCurrency: string;\n pendingCurrentCurrency: string | null;\n pendingNativeCurrency: string | null;\n usdConversionRate: number | null;\n};\n\nconst name = 'CurrencyRateController';\n\nexport type CurrencyRateStateChange = {\n type: `${typeof name}:stateChange`;\n payload: [CurrencyRateState, Patch[]];\n};\n\nexport type GetCurrencyRateState = {\n type: `${typeof name}:getState`;\n handler: () => CurrencyRateState;\n};\n\ntype CurrencyRateMessenger = RestrictedControllerMessenger<\n typeof name,\n GetCurrencyRateState,\n CurrencyRateStateChange,\n never,\n never\n>;\n\nconst metadata = {\n conversionDate: { persist: true, anonymous: true },\n conversionRate: { persist: true, anonymous: true },\n currentCurrency: { persist: true, anonymous: true },\n nativeCurrency: { persist: true, anonymous: true },\n pendingCurrentCurrency: { persist: false, anonymous: true },\n pendingNativeCurrency: { persist: false, anonymous: true },\n usdConversionRate: { persist: true, anonymous: true },\n};\n\nconst defaultState = {\n conversionDate: 0,\n conversionRate: 0,\n currentCurrency: 'usd',\n nativeCurrency: 'ETH',\n pendingCurrentCurrency: null,\n pendingNativeCurrency: null,\n usdConversionRate: null,\n};\n\n/**\n * Controller that passively polls on a set interval for an exchange rate from the current network\n * asset to the user's preferred currency.\n */\nexport class CurrencyRateController extends BaseControllerV2<\n typeof name,\n CurrencyRateState,\n CurrencyRateMessenger\n> {\n private mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private intervalDelay;\n\n private fetchExchangeRate;\n\n private includeUsdRate;\n\n /**\n * A boolean that controls whether or not network requests can be made by the controller\n */\n #enabled;\n\n /**\n * Creates a CurrencyRateController instance.\n *\n * @param options - Constructor options.\n * @param options.includeUsdRate - Keep track of the USD rate in addition to the current currency rate.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.messenger - A reference to the messaging system.\n * @param options.state - Initial state to set on this controller.\n * @param options.fetchExchangeRate - Fetches the exchange rate from an external API. This option is primarily meant for use in unit tests.\n */\n constructor({\n includeUsdRate = false,\n interval = 180000,\n messenger,\n state,\n fetchExchangeRate = defaultFetchExchangeRate,\n }: {\n includeUsdRate?: boolean;\n interval?: number;\n messenger: CurrencyRateMessenger;\n state?: Partial<CurrencyRateState>;\n fetchExchangeRate?: typeof defaultFetchExchangeRate;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.includeUsdRate = includeUsdRate;\n this.intervalDelay = interval;\n this.fetchExchangeRate = fetchExchangeRate;\n this.#enabled = false;\n }\n\n /**\n * Start polling for the currency rate.\n */\n async start() {\n this.#enabled = true;\n\n await this.startPolling();\n }\n\n /**\n * Stop polling for the currency rate.\n */\n stop() {\n this.#enabled = false;\n\n this.stopPolling();\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n /**\n * Sets a currency to track.\n *\n * @param currentCurrency - ISO 4217 currency code.\n */\n async setCurrentCurrency(currentCurrency: string) {\n this.update((state) => {\n state.pendingCurrentCurrency = currentCurrency;\n });\n await this.updateExchangeRate();\n }\n\n /**\n * Sets a new native currency.\n *\n * @param symbol - Symbol for the base asset.\n */\n async setNativeCurrency(symbol: string) {\n this.update((state) => {\n state.pendingNativeCurrency = symbol;\n });\n await this.updateExchangeRate();\n }\n\n private stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n }\n\n /**\n * Starts a new polling interval.\n */\n private async startPolling(): Promise<void> {\n this.stopPolling();\n // TODO: Expose polling currency rate update errors\n\n await safelyExecute(async () => await this.updateExchangeRate());\n\n this.intervalId = setInterval(async () => {\n await safelyExecute(async () => await this.updateExchangeRate());\n }, this.intervalDelay);\n }\n\n /**\n * Updates exchange rate for the current currency.\n *\n * @returns The controller state.\n */\n async updateExchangeRate(): Promise<CurrencyRateState | void> {\n if (!this.#enabled) {\n console.info(\n '[CurrencyRateController] Not updating exchange rate since network requests have been disabled',\n );\n return this.state;\n }\n const releaseLock = await this.mutex.acquire();\n const {\n currentCurrency: stateCurrentCurrency,\n nativeCurrency: stateNativeCurrency,\n pendingCurrentCurrency,\n pendingNativeCurrency,\n } = this.state;\n\n let conversionDate: number | null = null;\n let conversionRate: number | null = null;\n let usdConversionRate: number | null = null;\n const currentCurrency = pendingCurrentCurrency ?? stateCurrentCurrency;\n const nativeCurrency = pendingNativeCurrency ?? stateNativeCurrency;\n\n // For preloaded testnets (Rinkeby, Ropsten, Goerli, Kovan) we want to fetch exchange rate for real ETH.\n const nativeCurrencyForExchangeRate = Object.values(\n TESTNET_TICKER_SYMBOLS,\n ).includes(nativeCurrency)\n ? FALL_BACK_VS_CURRENCY // ETH\n : nativeCurrency;\n\n try {\n if (\n currentCurrency &&\n nativeCurrency &&\n // if either currency is an empty string we can skip the comparison\n // because it will result in an error from the api and ultimately\n // a null conversionRate either way.\n currentCurrency !== '' &&\n nativeCurrency !== ''\n ) {\n const fetchExchangeRateResponse = await this.fetchExchangeRate(\n currentCurrency,\n nativeCurrencyForExchangeRate,\n this.includeUsdRate,\n );\n\n conversionRate = fetchExchangeRateResponse.conversionRate;\n usdConversionRate = fetchExchangeRateResponse.usdConversionRate;\n conversionDate = Date.now() / 1000;\n }\n } catch (error) {\n if (\n !(\n error instanceof Error &&\n error.message.includes('market does not exist for this coin pair')\n )\n ) {\n throw error;\n }\n } finally {\n try {\n this.update(() => {\n return {\n conversionDate,\n conversionRate,\n // we currently allow and handle an empty string as a valid nativeCurrency\n // in cases where a user has not entered a native ticker symbol for a custom network\n // currentCurrency is not from user input but this protects us from unexpected changes.\n nativeCurrency,\n currentCurrency,\n pendingCurrentCurrency: null,\n pendingNativeCurrency: null,\n usdConversionRate,\n };\n });\n } finally {\n releaseLock();\n }\n }\n return this.state;\n }\n}\n\nexport default CurrencyRateController;\n"]}
@@ -74,8 +74,8 @@ class NftController extends base_controller_1.BaseController {
74
74
  onPreferencesStateChange(({ selectedAddress, ipfsGateway, openSeaEnabled }) => {
75
75
  this.configure({ selectedAddress, ipfsGateway, openSeaEnabled });
76
76
  });
77
- onNetworkStateChange(({ provider }) => {
78
- const { chainId } = provider;
77
+ onNetworkStateChange(({ providerConfig }) => {
78
+ const { chainId } = providerConfig;
79
79
  this.configure({ chainId });
80
80
  });
81
81
  }