{"version":3,"file":"TokensController.mjs","sourceRoot":"","sources":["../src/TokensController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport type {\n  AccountsControllerGetAccountAction,\n  AccountsControllerGetSelectedAccountAction,\n  AccountsControllerListAccountsAction,\n  AccountsControllerSelectedEvmAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type { ApprovalControllerAddRequestAction } from '@metamask/approval-controller';\nimport type {\n  ControllerGetStateAction,\n  ControllerStateChangeEvent,\n  StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport contractsMap from '@metamask/contract-metadata';\nimport {\n  toChecksumHexAddress,\n  ERC721_INTERFACE_ID,\n  ORIGIN_METAMASK,\n  ApprovalType,\n  ERC20,\n  ERC721,\n  ERC1155,\n  isValidHexAddress,\n  safelyExecute,\n} from '@metamask/controller-utils';\nimport type { KeyringControllerAccountRemovedEvent } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport { abiERC721 } from '@metamask/metamask-eth-abis';\nimport type {\n  NetworkClientId,\n  NetworkControllerGetNetworkClientByIdAction,\n  NetworkControllerNetworkDidChangeEvent,\n  NetworkControllerStateChangeEvent,\n  NetworkState,\n  Provider,\n} from '@metamask/network-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { isStrictHexString } from '@metamask/utils';\nimport type { Hex, Json } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport type { Patch } from 'immer';\nimport { cloneDeep } from 'lodash';\nimport { v1 as random } from 'uuid';\n\nimport { formatAggregatorNames, formatIconUrlWithProxy } from './assetsUtil';\nimport { ERC20Standard } from './Standards/ERC20Standard';\nimport { ERC1155Standard } from './Standards/NftStandards/ERC1155/ERC1155Standard';\nimport {\n  fetchTokenMetadata,\n  TOKEN_METADATA_NO_SUPPORT_ERROR,\n  TokenRwaData,\n} from './token-service';\nimport type {\n  TokenListStateChange,\n  TokenListToken,\n} from './TokenListController';\nimport type { Token } from './TokenRatesController';\nimport type { TokensControllerMethodActions } from './TokensController-method-action-types';\n\n/**\n * @type SuggestedAssetMeta\n *\n * Suggested asset by EIP747 meta data\n *\n * @property id - Generated UUID associated with this suggested asset\n * @property time - Timestamp associated with this this suggested asset\n * @property type - Type type this suggested asset\n * @property asset - Asset suggested object\n * @property interactingAddress - Account address that requested watch asset\n */\ntype SuggestedAssetMeta = {\n  id: string;\n  time: number;\n  type: string;\n  asset: Token;\n  interactingAddress: string;\n  origin?: string;\n  pageMeta?: Record<string, Json>;\n};\n\ntype WatchAssetRequestMetadata = {\n  origin?: string;\n  pageMeta?: Record<string, Json>;\n};\n\nconst getNonEmptyString = (\n  ...candidates: (string | undefined)[]\n): string | undefined => {\n  return candidates.find(\n    (candidate) => typeof candidate === 'string' && candidate.trim() !== '',\n  );\n};\n\n/**\n * @type TokensControllerState\n *\n * Assets controller state\n *\n * @property allTokens - Object containing tokens by network and account\n * @property allIgnoredTokens - Object containing hidden/ignored tokens by network and account\n * @property allDetectedTokens - Object containing tokens detected with non-zero balances\n */\nexport type TokensControllerState = {\n  allTokens: { [chainId: Hex]: { [key: string]: Token[] } };\n  allIgnoredTokens: { [chainId: Hex]: { [key: string]: string[] } };\n  allDetectedTokens: { [chainId: Hex]: { [key: string]: Token[] } };\n};\n\nconst metadata: StateMetadata<TokensControllerState> = {\n  allTokens: {\n    includeInStateLogs: false,\n    persist: true,\n    includeInDebugSnapshot: false,\n    usedInUi: true,\n  },\n  allIgnoredTokens: {\n    includeInStateLogs: false,\n    persist: true,\n    includeInDebugSnapshot: false,\n    usedInUi: true,\n  },\n  allDetectedTokens: {\n    includeInStateLogs: false,\n    persist: true,\n    includeInDebugSnapshot: false,\n    usedInUi: true,\n  },\n};\n\nconst controllerName = 'TokensController';\n\nexport type TokensControllerGetStateAction = ControllerGetStateAction<\n  typeof controllerName,\n  TokensControllerState\n>;\n\nexport type TokensControllerActions =\n  | TokensControllerGetStateAction\n  | TokensControllerMethodActions;\n\n/**\n * The external actions available to the {@link TokensController}.\n */\nexport type AllowedActions =\n  | ApprovalControllerAddRequestAction\n  | NetworkControllerGetNetworkClientByIdAction\n  | AccountsControllerGetAccountAction\n  | AccountsControllerGetSelectedAccountAction\n  | AccountsControllerListAccountsAction;\n\nexport type TokensControllerStateChangeEvent = ControllerStateChangeEvent<\n  typeof controllerName,\n  TokensControllerState\n>;\n\nexport type TokensControllerEvents = TokensControllerStateChangeEvent;\n\nexport type AllowedEvents =\n  | NetworkControllerStateChangeEvent\n  | NetworkControllerNetworkDidChangeEvent\n  | TokenListStateChange\n  | AccountsControllerSelectedEvmAccountChangeEvent\n  | KeyringControllerAccountRemovedEvent;\n\n/**\n * The messenger of the {@link TokensController}.\n */\nexport type TokensControllerMessenger = Messenger<\n  typeof controllerName,\n  TokensControllerActions | AllowedActions,\n  TokensControllerEvents | AllowedEvents\n>;\n\nexport const getDefaultTokensState = (): TokensControllerState => {\n  return {\n    allTokens: {},\n    allIgnoredTokens: {},\n    allDetectedTokens: {},\n  };\n};\n\nconst MESSENGER_EXPOSED_METHODS = [\n  'addDetectedTokens',\n  'addTokens',\n  'addToken',\n  'ignoreTokens',\n  'updateTokenType',\n  'watchAsset',\n  'clearIgnoredTokens',\n  'resetState',\n] as const;\n\n/**\n * Controller that stores assets and exposes convenience methods\n */\nexport class TokensController extends BaseController<\n  typeof controllerName,\n  TokensControllerState,\n  TokensControllerMessenger\n> {\n  readonly #mutex = new Mutex();\n\n  #selectedAccountId: string;\n\n  readonly #provider: Provider;\n\n  readonly #abortController: AbortController;\n\n  /**\n   * Tokens controller options\n   *\n   * @param options - Constructor options.\n   * @param options.chainId - The chain ID of the current network.\n   * @param options.provider - Network provider.\n   * @param options.state - Initial state to set on this controller.\n   * @param options.messenger - The messenger.\n   */\n  constructor({\n    provider,\n    state,\n    messenger,\n  }: {\n    chainId: Hex;\n    provider: Provider;\n    state?: Partial<TokensControllerState>;\n    messenger: TokensControllerMessenger;\n  }) {\n    super({\n      name: controllerName,\n      metadata,\n      messenger,\n      state: {\n        ...getDefaultTokensState(),\n        ...state,\n      },\n    });\n\n    this.#provider = provider;\n\n    this.#selectedAccountId = this.#getSelectedAccount().id;\n\n    this.#abortController = new AbortController();\n\n    messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);\n\n    this.messenger.subscribe(\n      'AccountsController:selectedEvmAccountChange',\n      this.#onSelectedAccountChange.bind(this),\n    );\n\n    this.messenger.subscribe(\n      'NetworkController:stateChange',\n      this.#onNetworkStateChange.bind(this),\n    );\n\n    this.messenger.subscribe(\n      'KeyringController:accountRemoved',\n      (accountAddress: string) => this.#handleOnAccountRemoved(accountAddress),\n    );\n\n    this.messenger.subscribe(\n      'TokenListController:stateChange',\n      ({ tokensChainsCache }) => {\n        const { allTokens } = this.state;\n        const selectedAddress = this.#getSelectedAddress();\n\n        // Deep clone the `allTokens` object to ensure mutability\n        const updatedAllTokens = cloneDeep(allTokens);\n\n        for (const [chainId, chainCache] of Object.entries(tokensChainsCache)) {\n          const chainData = chainCache?.data ?? {};\n\n          if (updatedAllTokens[chainId as Hex]) {\n            if (updatedAllTokens[chainId as Hex][selectedAddress]) {\n              const tokens = updatedAllTokens[chainId as Hex][selectedAddress];\n\n              for (const [, token] of Object.entries(tokens)) {\n                const cachedToken = chainData[token.address.toLowerCase()];\n                if (cachedToken && cachedToken.name && !token.name) {\n                  token.name = cachedToken.name; // Update the token name\n                }\n                if (cachedToken?.rwaData) {\n                  token.rwaData = cachedToken.rwaData; // Update the token RWA data\n                }\n              }\n            }\n          }\n        }\n\n        // Update the state with the modified tokens\n        this.update(() => {\n          return {\n            ...this.state,\n            allTokens: updatedAllTokens,\n          };\n        });\n      },\n    );\n  }\n\n  #handleOnAccountRemoved(accountAddress: string) {\n    const isEthAddress =\n      isStrictHexString(accountAddress.toLowerCase()) &&\n      isValidHexAddress(accountAddress);\n\n    if (!isEthAddress) {\n      return;\n    }\n\n    const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state;\n    const newAllTokens = cloneDeep(allTokens);\n    const newAllDetectedTokens = cloneDeep(allDetectedTokens);\n    const newAllIgnoredTokens = cloneDeep(allIgnoredTokens);\n\n    for (const chainId of Object.keys(newAllTokens)) {\n      if (newAllTokens[chainId as Hex][accountAddress]) {\n        delete newAllTokens[chainId as Hex][accountAddress];\n      }\n    }\n\n    for (const chainId of Object.keys(newAllDetectedTokens)) {\n      if (newAllDetectedTokens[chainId as Hex][accountAddress]) {\n        delete newAllDetectedTokens[chainId as Hex][accountAddress];\n      }\n    }\n\n    for (const chainId of Object.keys(newAllIgnoredTokens)) {\n      if (newAllIgnoredTokens[chainId as Hex][accountAddress]) {\n        delete newAllIgnoredTokens[chainId as Hex][accountAddress];\n      }\n    }\n\n    this.update((state) => {\n      state.allTokens = newAllTokens;\n      state.allIgnoredTokens = newAllIgnoredTokens;\n      state.allDetectedTokens = newAllDetectedTokens;\n    });\n  }\n\n  /**\n   * Handles the event when the network state changes.\n   *\n   * @param _ - The network state.\n   * @param patches - An array of patch operations performed on the network state.\n   */\n  #onNetworkStateChange(_: NetworkState, patches: Patch[]) {\n    // Remove state for deleted networks\n    for (const patch of patches) {\n      if (\n        patch.op === 'remove' &&\n        patch.path[0] === 'networkConfigurationsByChainId'\n      ) {\n        const removedChainId = patch.path[1] as Hex;\n\n        this.update((state) => {\n          delete state.allTokens[removedChainId];\n          delete state.allIgnoredTokens[removedChainId];\n          delete state.allDetectedTokens[removedChainId];\n        });\n      }\n    }\n  }\n\n  /**\n   * Handles the selected account change in the accounts controller.\n   *\n   * @param selectedAccount - The new selected account\n   */\n  #onSelectedAccountChange(selectedAccount: InternalAccount) {\n    this.#selectedAccountId = selectedAccount.id;\n  }\n\n  /**\n   * Fetch metadata for a token.\n   *\n   * @param tokenAddress - The address of the token.\n   * @param chainId - The chain ID of the network on which the token is detected.\n   * @returns The token metadata.\n   */\n  async #fetchTokenMetadata(\n    tokenAddress: string,\n    chainId: Hex,\n  ): Promise<TokenListToken | undefined> {\n    try {\n      const token = await fetchTokenMetadata<TokenListToken>(\n        chainId,\n        tokenAddress,\n        this.#abortController.signal,\n      );\n      return token;\n    } catch (error) {\n      if (\n        error instanceof Error &&\n        error.message.includes(TOKEN_METADATA_NO_SUPPORT_ERROR)\n      ) {\n        return undefined;\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * Adds a token to the stored token list.\n   *\n   * @param options - The method argument object.\n   * @param options.address - Hex address of the token contract.\n   * @param options.symbol - Symbol of the token.\n   * @param options.decimals - Number of decimals the token uses.\n   * @param options.name - Name of the token.\n   * @param options.image - Image of the token.\n   * @param options.interactingAddress - The address of the account to add a token to.\n   * @param options.networkClientId - Network Client ID.\n   * @param options.rwaData - Optional RWA data for the token.\n   * @returns Current token list.\n   */\n  async addToken({\n    address,\n    symbol,\n    decimals,\n    name,\n    image,\n    interactingAddress,\n    networkClientId,\n    rwaData,\n  }: {\n    address: string;\n    symbol: string;\n    decimals: number;\n    name?: string;\n    image?: string;\n    interactingAddress?: string;\n    networkClientId: NetworkClientId;\n    rwaData?: TokenRwaData;\n  }): Promise<Token[]> {\n    const releaseLock = await this.#mutex.acquire();\n    const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state;\n\n    const chainIdToUse = this.messenger.call(\n      'NetworkController:getNetworkClientById',\n      networkClientId,\n    ).configuration.chainId;\n\n    const accountAddress =\n      this.#getAddressOrSelectedAddress(interactingAddress);\n\n    try {\n      address = toChecksumHexAddress(address);\n      const tokens = allTokens[chainIdToUse]?.[accountAddress] ?? [];\n      const ignoredTokens =\n        allIgnoredTokens[chainIdToUse]?.[accountAddress] ?? [];\n      const detectedTokens =\n        allDetectedTokens[chainIdToUse]?.[accountAddress] ?? [];\n      const newTokens: Token[] = [...tokens];\n      const [isERC721, tokenMetadata] = await Promise.all([\n        this.#detectIsERC721(address, networkClientId),\n        // TODO parameterize the token metadata fetch by networkClientId\n        this.#fetchTokenMetadata(address, chainIdToUse),\n      ]);\n      const newEntry: Token = {\n        address,\n        symbol,\n        decimals,\n        image:\n          image && image.trim() !== ''\n            ? image\n            : formatIconUrlWithProxy({\n                chainId: chainIdToUse,\n                tokenAddress: address,\n              }),\n        isERC721,\n        aggregators: formatAggregatorNames(tokenMetadata?.aggregators ?? []),\n        name,\n        ...(rwaData !== undefined && { rwaData }),\n      };\n      const previousIndex = newTokens.findIndex(\n        (token) => token.address.toLowerCase() === address.toLowerCase(),\n      );\n      if (previousIndex !== -1) {\n        newTokens[previousIndex] = newEntry;\n      } else {\n        newTokens.push(newEntry);\n      }\n\n      const newIgnoredTokens = ignoredTokens.filter(\n        (tokenAddress) => tokenAddress.toLowerCase() !== address.toLowerCase(),\n      );\n      const newDetectedTokens = detectedTokens.filter(\n        (token) => token.address.toLowerCase() !== address.toLowerCase(),\n      );\n\n      const { newAllTokens, newAllIgnoredTokens, newAllDetectedTokens } =\n        this.#getNewAllTokensState({\n          newTokens,\n          newIgnoredTokens,\n          newDetectedTokens,\n          interactingAddress: accountAddress,\n          interactingChainId: chainIdToUse,\n        });\n\n      const newState: Partial<TokensControllerState> = {\n        allTokens: newAllTokens,\n        allIgnoredTokens: newAllIgnoredTokens,\n        allDetectedTokens: newAllDetectedTokens,\n      };\n\n      this.update((state) => {\n        Object.assign(state, newState);\n      });\n      return newTokens;\n    } finally {\n      releaseLock();\n    }\n  }\n\n  /**\n   * Add a batch of tokens.\n   *\n   * @param tokensToImport - Array of tokens to import.\n   * @param networkClientId - Optional network client ID used to determine interacting chain ID.\n   */\n  async addTokens(tokensToImport: Token[], networkClientId: NetworkClientId) {\n    const releaseLock = await this.#mutex.acquire();\n    const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state;\n    const importedTokensMap: { [key: string]: true } = {};\n\n    const interactingChainId = this.messenger.call(\n      'NetworkController:getNetworkClientById',\n      networkClientId,\n    ).configuration.chainId;\n\n    // Used later to dedupe imported tokens\n    const newTokensMap = [\n      ...(allTokens[interactingChainId]?.[this.#getSelectedAccount().address] ??\n        []),\n      ...tokensToImport,\n    ].reduce<{ [address: string]: Token }>((output, token) => {\n      output[toChecksumHexAddress(token.address)] = token;\n      return output;\n    }, {});\n    try {\n      tokensToImport.forEach((tokenToAdd) => {\n        const { address, symbol, decimals, image, aggregators, name, rwaData } =\n          tokenToAdd;\n        const checksumAddress = toChecksumHexAddress(address);\n        const formattedToken: Token = {\n          address: checksumAddress,\n          symbol,\n          decimals,\n          image,\n          aggregators,\n          name,\n          ...(rwaData && { rwaData }),\n        };\n        newTokensMap[checksumAddress] = formattedToken;\n        importedTokensMap[address.toLowerCase()] = true;\n        return formattedToken;\n      });\n      const newTokens = Object.values(newTokensMap);\n\n      const newIgnoredTokens = allIgnoredTokens[interactingChainId]?.[\n        this.#getSelectedAddress()\n      ]?.filter(\n        (tokenAddress) => !newTokensMap[toChecksumHexAddress(tokenAddress)],\n      );\n\n      const detectedTokensForGivenChain = interactingChainId\n        ? allDetectedTokens?.[interactingChainId]?.[this.#getSelectedAddress()]\n        : [];\n\n      const newDetectedTokens = detectedTokensForGivenChain?.filter(\n        (t) => !importedTokensMap[t.address.toLowerCase()],\n      );\n\n      const { newAllTokens, newAllDetectedTokens, newAllIgnoredTokens } =\n        this.#getNewAllTokensState({\n          newTokens,\n          newDetectedTokens,\n          newIgnoredTokens,\n          interactingChainId,\n        });\n\n      this.update((state) => {\n        state.allTokens = newAllTokens;\n        state.allDetectedTokens = newAllDetectedTokens;\n        state.allIgnoredTokens = newAllIgnoredTokens;\n      });\n    } finally {\n      releaseLock();\n    }\n  }\n\n  /**\n   * Ignore a batch of tokens.\n   *\n   * @param tokenAddressesToIgnore - Array of token addresses to ignore.\n   * @param networkClientId - Optional network client ID used to determine interacting chain ID.\n   */\n  ignoreTokens(\n    tokenAddressesToIgnore: string[],\n    networkClientId: NetworkClientId,\n  ) {\n    const interactingChainId = this.messenger.call(\n      'NetworkController:getNetworkClientById',\n      networkClientId,\n    ).configuration.chainId;\n\n    const { allTokens, allDetectedTokens, allIgnoredTokens } = this.state;\n    const ignoredTokensMap: { [key: string]: true } = {};\n    const ignoredTokens =\n      allIgnoredTokens[interactingChainId]?.[this.#getSelectedAddress()] ?? [];\n    let newIgnoredTokens: string[] = [...ignoredTokens];\n\n    const tokens =\n      allTokens[interactingChainId]?.[this.#getSelectedAddress()] ?? [];\n\n    const detectedTokens =\n      allDetectedTokens[interactingChainId]?.[this.#getSelectedAddress()] ?? [];\n\n    const checksummedTokenAddresses = tokenAddressesToIgnore.map((address) => {\n      const checksumAddress = toChecksumHexAddress(address);\n      ignoredTokensMap[address.toLowerCase()] = true;\n      return checksumAddress;\n    });\n    newIgnoredTokens = [...ignoredTokens, ...checksummedTokenAddresses];\n    const newDetectedTokens = detectedTokens.filter(\n      (token) => !ignoredTokensMap[token.address.toLowerCase()],\n    );\n    const newTokens = tokens.filter(\n      (token) => !ignoredTokensMap[token.address.toLowerCase()],\n    );\n\n    const { newAllIgnoredTokens, newAllDetectedTokens, newAllTokens } =\n      this.#getNewAllTokensState({\n        newIgnoredTokens,\n        newDetectedTokens,\n        newTokens,\n        interactingChainId,\n      });\n\n    this.update((state) => {\n      state.allIgnoredTokens = newAllIgnoredTokens;\n      state.allDetectedTokens = newAllDetectedTokens;\n      state.allTokens = newAllTokens;\n    });\n  }\n\n  /**\n   * Adds a batch of detected tokens to the stored token list.\n   *\n   * @param incomingDetectedTokens - Array of detected tokens to be added or updated.\n   * @param detectionDetails - An object containing the chain ID and address of the currently selected network on which the incomingDetectedTokens were detected.\n   * @param detectionDetails.selectedAddress - the account address on which the incomingDetectedTokens were detected.\n   * @param detectionDetails.chainId - the chainId on which the incomingDetectedTokens were detected.\n   */\n  async addDetectedTokens(\n    incomingDetectedTokens: Token[],\n    detectionDetails: { selectedAddress?: string; chainId: Hex },\n  ) {\n    const releaseLock = await this.#mutex.acquire();\n\n    const { chainId } = detectionDetails;\n    // Previously selectedAddress could be an empty string. This is to preserve the behaviour\n    const accountAddress =\n      detectionDetails?.selectedAddress ?? this.#getSelectedAddress();\n\n    const { allTokens, allDetectedTokens, allIgnoredTokens } = this.state;\n    let newTokens = [...(allTokens?.[chainId]?.[accountAddress] ?? [])];\n    let newDetectedTokens = [\n      ...(allDetectedTokens?.[chainId]?.[accountAddress] ?? []),\n    ];\n\n    try {\n      incomingDetectedTokens.forEach((tokenToAdd) => {\n        const {\n          address,\n          symbol,\n          decimals,\n          image,\n          aggregators,\n          isERC721,\n          name,\n          rwaData,\n        } = tokenToAdd;\n        const checksumAddress = toChecksumHexAddress(address);\n        const newEntry: Token = {\n          address: checksumAddress,\n          symbol,\n          decimals,\n          image,\n          isERC721,\n          aggregators,\n          name,\n          ...(rwaData && { rwaData }),\n        };\n\n        const previousImportedIndex = newTokens.findIndex(\n          (token) =>\n            token.address.toLowerCase() === checksumAddress.toLowerCase(),\n        );\n\n        if (previousImportedIndex !== -1) {\n          // Update existing data of imported token\n          newTokens[previousImportedIndex] = newEntry;\n        } else {\n          const ignoredTokenIndex =\n            allIgnoredTokens?.[chainId]?.[accountAddress]?.indexOf(address) ??\n            -1;\n\n          if (ignoredTokenIndex === -1) {\n            // Add detected token\n            const previousDetectedIndex = newDetectedTokens.findIndex(\n              (token) =>\n                token.address.toLowerCase() === checksumAddress.toLowerCase(),\n            );\n            if (previousDetectedIndex !== -1) {\n              newDetectedTokens[previousDetectedIndex] = newEntry;\n            } else {\n              newDetectedTokens.push(newEntry);\n            }\n          }\n        }\n      });\n\n      const { newAllTokens, newAllDetectedTokens } = this.#getNewAllTokensState(\n        {\n          newTokens,\n          newDetectedTokens,\n          interactingAddress: accountAddress,\n          interactingChainId: chainId,\n        },\n      );\n\n      // We may be detecting tokens on a different chain/account pair than are currently configured.\n      // Re-point `tokens` and `detectedTokens` to keep them referencing the current chain/account.\n      const selectedAddress = this.#getSelectedAddress();\n\n      newTokens = newAllTokens?.[chainId]?.[selectedAddress] ?? [];\n      newDetectedTokens =\n        newAllDetectedTokens?.[chainId]?.[selectedAddress] ?? [];\n\n      this.update((state) => {\n        state.allTokens = newAllTokens;\n        state.allDetectedTokens = newAllDetectedTokens;\n      });\n    } finally {\n      releaseLock();\n    }\n  }\n\n  /**\n   * Adds isERC721 field to token object. This is called when a user attempts to add tokens that\n   * were previously added which do not yet had isERC721 field.\n   *\n   * @param tokenAddress - The contract address of the token requiring the isERC721 field added.\n   * @param networkClientId - The network client ID of the network on which the token is detected.\n   * @returns The new token object with the added isERC721 field.\n   */\n  async updateTokenType(\n    tokenAddress: string,\n    networkClientId: NetworkClientId,\n  ): Promise<Token> {\n    const chainIdToUse = this.messenger.call(\n      'NetworkController:getNetworkClientById',\n      networkClientId,\n    ).configuration.chainId;\n\n    const isERC721 = await this.#detectIsERC721(tokenAddress, networkClientId);\n    const accountAddress = this.#getSelectedAddress();\n    const tokens = [...this.state.allTokens[chainIdToUse][accountAddress]];\n    const tokenIndex = tokens.findIndex((token) => {\n      return token.address.toLowerCase() === tokenAddress.toLowerCase();\n    });\n    const updatedToken = { ...tokens[tokenIndex], isERC721 };\n    tokens[tokenIndex] = updatedToken;\n    this.update((state) => {\n      state.allTokens[chainIdToUse][accountAddress] = tokens;\n    });\n    return updatedToken;\n  }\n\n  /**\n   * Detects whether or not a token is ERC-721 compatible.\n   *\n   * @param tokenAddress - The token contract address.\n   * @param networkClientId - Optional network client ID to fetch contract info with.\n   * @returns A boolean indicating whether the token address passed in supports the EIP-721\n   * interface.\n   */\n  async #detectIsERC721(\n    tokenAddress: string,\n    networkClientId?: NetworkClientId,\n  ) {\n    const checksumAddress = toChecksumHexAddress(tokenAddress);\n    // if this token is already in our contract metadata map we don't need\n    // to check against the contract\n    if (contractsMap[checksumAddress]?.erc721 === true) {\n      return Promise.resolve(true);\n    } else if (contractsMap[checksumAddress]?.erc20 === true) {\n      return Promise.resolve(false);\n    }\n\n    const tokenContract = this.#createEthersContract(\n      tokenAddress,\n      abiERC721,\n      networkClientId,\n    );\n    try {\n      return await tokenContract.supportsInterface(ERC721_INTERFACE_ID);\n    } catch (error) {\n      // currently we see a variety of errors across different networks when\n      // token contracts are not ERC721 compatible. We need to figure out a better\n      // way of differentiating token interface types but for now if we get an error\n      // we have to assume the token is not ERC721 compatible.\n      return false;\n    }\n  }\n\n  #getProvider(networkClientId?: NetworkClientId): Web3Provider {\n    return new Web3Provider(\n      networkClientId\n        ? this.messenger.call(\n            'NetworkController:getNetworkClientById',\n            networkClientId,\n          ).provider\n        : this.#provider,\n    );\n  }\n\n  #createEthersContract(\n    tokenAddress: string,\n    abi: string,\n    networkClientId?: NetworkClientId,\n  ): Contract {\n    const web3provider = this.#getProvider(networkClientId);\n    const tokenContract = new Contract(tokenAddress, abi, web3provider);\n    return tokenContract;\n  }\n\n  #generateRandomId(): string {\n    return random();\n  }\n\n  /**\n   * Adds a new suggestedAsset to the list of watched assets.\n   * Parameters will be validated according to the asset type being watched.\n   *\n   * @param options - The method options.\n   * @param options.asset - The asset to be watched. For now only ERC20 tokens are accepted.\n   * @param options.type - The asset type.\n   * @param options.interactingAddress - The address of the account that is requesting to watch the asset.\n   * @param options.networkClientId - Network Client ID.\n   * @param options.origin - The origin to set on the approval request.\n   * @param options.pageMeta - The metadata for the page initiating the request.\n   * @param options.requestMetadata - Metadata for the request, including pageMeta and origin.\n   * @returns A promise that resolves if the asset was watched successfully, and rejects otherwise.\n   */\n  async watchAsset({\n    asset,\n    type,\n    interactingAddress,\n    networkClientId,\n    origin,\n    pageMeta,\n    requestMetadata,\n  }: {\n    asset: Token;\n    type: string;\n    interactingAddress?: string;\n    networkClientId: NetworkClientId;\n    origin?: string;\n    pageMeta?: Record<string, Json>;\n    requestMetadata?: WatchAssetRequestMetadata;\n  }): Promise<void> {\n    if (type !== ERC20) {\n      throw new Error(`Asset of type ${type} not supported`);\n    }\n\n    if (!asset.address) {\n      throw rpcErrors.invalidParams('Address must be specified');\n    }\n\n    if (!isValidHexAddress(asset.address)) {\n      throw rpcErrors.invalidParams(`Invalid address \"${asset.address}\"`);\n    }\n\n    const selectedAddress =\n      this.#getAddressOrSelectedAddress(interactingAddress);\n\n    // Validate contract\n\n    if (await this.#detectIsERC721(asset.address, networkClientId)) {\n      throw rpcErrors.invalidParams(\n        `Contract ${asset.address} must match type ${type}, but was detected as ${ERC721}`,\n      );\n    }\n\n    const provider = this.#getProvider(networkClientId);\n    const isErc1155 = await safelyExecute(() =>\n      new ERC1155Standard(provider).contractSupportsBase1155Interface(\n        asset.address,\n      ),\n    );\n    if (isErc1155) {\n      throw rpcErrors.invalidParams(\n        `Contract ${asset.address} must match type ${type}, but was detected as ${ERC1155}`,\n      );\n    }\n\n    const erc20 = new ERC20Standard(provider);\n    const [contractName, contractSymbol, contractDecimals] = await Promise.all([\n      safelyExecute(() => erc20.getTokenName(asset.address)),\n      safelyExecute(() => erc20.getTokenSymbol(asset.address)),\n      safelyExecute(async () => erc20.getTokenDecimals(asset.address)),\n    ]);\n\n    asset.name = contractName;\n\n    // Validate symbol\n\n    if (!asset.symbol && !contractSymbol) {\n      throw rpcErrors.invalidParams(\n        'A symbol is required, but was not found in either the request or contract',\n      );\n    }\n\n    if (\n      contractSymbol !== undefined &&\n      asset.symbol !== undefined &&\n      asset.symbol.toUpperCase() !== contractSymbol.toUpperCase()\n    ) {\n      throw rpcErrors.invalidParams(\n        `The symbol in the request (${asset.symbol}) does not match the symbol in the contract (${contractSymbol})`,\n      );\n    }\n\n    asset.symbol = contractSymbol ?? asset.symbol;\n    if (typeof asset.symbol !== 'string') {\n      throw rpcErrors.invalidParams(`Invalid symbol: not a string`);\n    }\n\n    if (asset.symbol.length > 11) {\n      throw rpcErrors.invalidParams(\n        `Invalid symbol \"${asset.symbol}\": longer than 11 characters`,\n      );\n    }\n\n    // Validate decimals\n\n    if (asset.decimals === undefined && contractDecimals === undefined) {\n      throw rpcErrors.invalidParams(\n        'Decimals are required, but were not found in either the request or contract',\n      );\n    }\n\n    if (\n      contractDecimals !== undefined &&\n      asset.decimals !== undefined &&\n      String(asset.decimals) !== contractDecimals\n    ) {\n      throw rpcErrors.invalidParams(\n        `The decimals in the request (${asset.decimals}) do not match the decimals in the contract (${contractDecimals})`,\n      );\n    }\n\n    const decimalsStr = contractDecimals ?? asset.decimals;\n    const decimalsNum = parseInt(decimalsStr as unknown as string, 10);\n    if (!Number.isInteger(decimalsNum) || decimalsNum > 36 || decimalsNum < 0) {\n      throw rpcErrors.invalidParams(\n        `Invalid decimals \"${decimalsStr}\": must be an integer 0 <= 36`,\n      );\n    }\n    asset.decimals = decimalsNum;\n\n    const suggestedAssetMeta: SuggestedAssetMeta = {\n      asset,\n      id: this.#generateRandomId(),\n      time: Date.now(),\n      type,\n      interactingAddress: selectedAddress,\n      origin: getNonEmptyString(requestMetadata?.origin, origin),\n      pageMeta: requestMetadata?.pageMeta ?? pageMeta,\n    };\n\n    await this.#requestApproval(suggestedAssetMeta);\n\n    const { address, symbol, decimals, name, image, rwaData } = asset;\n    await this.addToken({\n      address,\n      symbol,\n      decimals,\n      name,\n      image,\n      interactingAddress: suggestedAssetMeta.interactingAddress,\n      networkClientId,\n      rwaData,\n    });\n  }\n\n  /**\n   * Takes a new tokens and ignoredTokens array for the current network/account combination\n   * and returns new allTokens and allIgnoredTokens state to update to.\n   *\n   * @param params - Object that holds token params.\n   * @param params.newTokens - The new tokens to set for the current network and selected account.\n   * @param params.newIgnoredTokens - The new ignored tokens to set for the current network and selected account.\n   * @param params.newDetectedTokens - The new detected tokens to set for the current network and selected account.\n   * @param params.interactingAddress - The account address to use to store the tokens.\n   * @param params.interactingChainId - The chainId to use to store the tokens.\n   * @returns The updated `allTokens` and `allIgnoredTokens` state.\n   */\n  #getNewAllTokensState(params: {\n    newTokens?: Token[];\n    newIgnoredTokens?: string[];\n    newDetectedTokens?: Token[];\n    interactingAddress?: string;\n    interactingChainId: Hex;\n  }) {\n    const {\n      newTokens,\n      newIgnoredTokens,\n      newDetectedTokens,\n      interactingAddress,\n      interactingChainId,\n    } = params;\n    const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state;\n\n    const userAddressToAddTokens =\n      this.#getAddressOrSelectedAddress(interactingAddress);\n\n    let newAllTokens = allTokens;\n    if (\n      newTokens?.length ||\n      (newTokens &&\n        allTokens &&\n        allTokens[interactingChainId] &&\n        allTokens[interactingChainId][userAddressToAddTokens])\n    ) {\n      const networkTokens = allTokens[interactingChainId];\n      const newNetworkTokens = {\n        ...networkTokens,\n        ...{ [userAddressToAddTokens]: newTokens },\n      };\n      newAllTokens = {\n        ...allTokens,\n        ...{ [interactingChainId]: newNetworkTokens },\n      };\n    }\n\n    let newAllIgnoredTokens = allIgnoredTokens;\n    if (\n      newIgnoredTokens?.length ||\n      (newIgnoredTokens &&\n        allIgnoredTokens &&\n        allIgnoredTokens[interactingChainId] &&\n        allIgnoredTokens[interactingChainId][userAddressToAddTokens])\n    ) {\n      const networkIgnoredTokens = allIgnoredTokens[interactingChainId];\n      const newIgnoredNetworkTokens = {\n        ...networkIgnoredTokens,\n        ...{ [userAddressToAddTokens]: newIgnoredTokens },\n      };\n      newAllIgnoredTokens = {\n        ...allIgnoredTokens,\n        ...{ [interactingChainId]: newIgnoredNetworkTokens },\n      };\n    }\n\n    let newAllDetectedTokens = allDetectedTokens;\n    if (\n      newDetectedTokens?.length ||\n      (newDetectedTokens &&\n        allDetectedTokens &&\n        allDetectedTokens[interactingChainId] &&\n        allDetectedTokens[interactingChainId][userAddressToAddTokens])\n    ) {\n      const networkDetectedTokens = allDetectedTokens[interactingChainId];\n      const newDetectedNetworkTokens = {\n        ...networkDetectedTokens,\n        ...{ [userAddressToAddTokens]: newDetectedTokens },\n      };\n      newAllDetectedTokens = {\n        ...allDetectedTokens,\n        ...{ [interactingChainId]: newDetectedNetworkTokens },\n      };\n    }\n    return { newAllTokens, newAllIgnoredTokens, newAllDetectedTokens };\n  }\n\n  #getAddressOrSelectedAddress(address: string | undefined): string {\n    if (address) {\n      return address;\n    }\n\n    return this.#getSelectedAddress();\n  }\n\n  /**\n   * Removes all tokens from the ignored list.\n   */\n  clearIgnoredTokens() {\n    this.update((state) => {\n      state.allIgnoredTokens = {};\n    });\n  }\n\n  async #requestApproval(suggestedAssetMeta: SuggestedAssetMeta) {\n    const requestData: Record<string, Json> = {\n      id: suggestedAssetMeta.id,\n      interactingAddress: suggestedAssetMeta.interactingAddress,\n      asset: {\n        address: suggestedAssetMeta.asset.address,\n        decimals: suggestedAssetMeta.asset.decimals,\n        symbol: suggestedAssetMeta.asset.symbol,\n        image:\n          suggestedAssetMeta.asset.image &&\n          suggestedAssetMeta.asset.image.trim() !== ''\n            ? suggestedAssetMeta.asset.image\n            : null,\n      },\n    };\n    if (suggestedAssetMeta.pageMeta) {\n      requestData.metadata = {\n        pageMeta: suggestedAssetMeta.pageMeta,\n      };\n    }\n\n    return this.messenger.call(\n      'ApprovalController:addRequest',\n      {\n        id: suggestedAssetMeta.id,\n        origin: getNonEmptyString(suggestedAssetMeta.origin) ?? ORIGIN_METAMASK,\n        type: ApprovalType.WatchAsset,\n        requestData,\n      },\n      true,\n    );\n  }\n\n  #getSelectedAccount() {\n    return this.messenger.call('AccountsController:getSelectedAccount');\n  }\n\n  #getSelectedAddress() {\n    // If the address is not defined (or empty), we fallback to the currently selected account's address\n    const account = this.messenger.call(\n      'AccountsController:getAccount',\n      this.#selectedAccountId,\n    );\n    return account?.address ?? '';\n  }\n\n  /**\n   * Reset the controller state to the default state.\n   */\n  resetState() {\n    this.update(() => {\n      return getDefaultTokensState();\n    });\n  }\n}\n\nexport default TokensController;\n"]}