@metamask/assets-controllers 15.0.0 → 17.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 +22 -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 +1 -1
- package/dist/NftController.d.ts.map +1 -1
- package/dist/NftController.js +12 -1
- package/dist/NftController.js.map +1 -1
- package/dist/NftDetectionController.d.ts +16 -5
- package/dist/NftDetectionController.d.ts.map +1 -1
- package/dist/NftDetectionController.js +26 -5
- package/dist/NftDetectionController.js.map +1 -1
- package/dist/TokenBalancesController.js +4 -4
- package/dist/TokenBalancesController.js.map +1 -1
- package/dist/TokenDetectionController.d.ts +19 -5
- package/dist/TokenDetectionController.d.ts.map +1 -1
- package/dist/TokenDetectionController.js +27 -7
- package/dist/TokenDetectionController.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 +10 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NftDetectionController.js","sourceRoot":"","sources":["../src/NftDetectionController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BaseConfig, BaseState } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport {\n OPENSEA_PROXY_URL,\n fetchWithErrorHandling,\n toChecksumHexAddress,\n ChainId,\n} from '@metamask/controller-utils';\nimport type { NetworkState } from '@metamask/network-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport { Source } from './constants';\nimport type { NftController, NftState, NftMetadata } from './NftController';\n\nconst DEFAULT_INTERVAL = 180000;\n\n/**\n * @type ApiNft\n *\n * NFT object coming from OpenSea api\n * @property token_id - The NFT identifier\n * @property num_sales - Number of sales\n * @property background_color - The background color to be displayed with the item\n * @property image_url - URI of an image associated with this NFT\n * @property image_preview_url - URI of a smaller image associated with this NFT\n * @property image_thumbnail_url - URI of a thumbnail image associated with this NFT\n * @property image_original_url - URI of the original image associated with this NFT\n * @property animation_url - URI of a animation associated with this NFT\n * @property animation_original_url - URI of the original animation associated with this NFT\n * @property name - The NFT name\n * @property description - The NFT description\n * @property external_link - External link containing additional information\n * @property assetContract - The NFT contract information object\n * @property creator - The NFT owner information object\n * @property lastSale - When this item was last sold\n */\nexport interface ApiNft {\n token_id: string;\n num_sales: number | null;\n background_color: string | null;\n image_url: string | null;\n image_preview_url: string | null;\n image_thumbnail_url: string | null;\n image_original_url: string | null;\n animation_url: string | null;\n animation_original_url: string | null;\n name: string | null;\n description: string | null;\n external_link: string | null;\n asset_contract: ApiNftContract;\n creator: ApiNftCreator;\n last_sale: ApiNftLastSale | null;\n}\n\n/**\n * @type ApiNftContract\n *\n * NFT contract object coming from OpenSea api\n * @property address - Address of the NFT contract\n * @property asset_contract_type - The NFT type, it could be `semi-fungible` or `non-fungible`\n * @property created_date - Creation date\n * @property collection - Object containing the contract name and URI of an image associated\n * @property schema_name - The schema followed by the contract, it could be `ERC721` or `ERC1155`\n * @property symbol - The NFT contract symbol\n * @property total_supply - Total supply of NFTs\n * @property description - The NFT contract description\n * @property external_link - External link containing additional information\n */\nexport interface ApiNftContract {\n address: string;\n asset_contract_type: string | null;\n created_date: string | null;\n schema_name: string | null;\n symbol: string | null;\n total_supply: string | null;\n description: string | null;\n external_link: string | null;\n collection: {\n name: string | null;\n image_url?: string | null;\n };\n}\n\n/**\n * @type ApiNftLastSale\n *\n * NFT sale object coming from OpenSea api\n * @property event_timestamp - Object containing a `username`\n * @property total_price - URI of NFT image associated with this owner\n * @property transaction - Object containing transaction_hash and block_hash\n */\nexport interface ApiNftLastSale {\n event_timestamp: string;\n total_price: string;\n transaction: { transaction_hash: string; block_hash: string };\n}\n\n/**\n * @type ApiNftCreator\n *\n * NFT creator object coming from OpenSea api\n * @property user - Object containing a `username`\n * @property profile_img_url - URI of NFT image associated with this owner\n * @property address - The owner address\n */\nexport interface ApiNftCreator {\n user: { username: string };\n profile_img_url: string;\n address: string;\n}\n\n/**\n * @type NftDetectionConfig\n *\n * NftDetection configuration\n * @property interval - Polling interval used to fetch new token rates\n * @property chainId - Current chain ID\n * @property selectedAddress - Vault selected address\n */\nexport interface NftDetectionConfig extends BaseConfig {\n interval: number;\n chainId: Hex;\n selectedAddress: string;\n}\n\n/**\n * Controller that passively polls on a set interval for NFT auto detection\n */\nexport class NftDetectionController extends BaseController<\n NftDetectionConfig,\n BaseState\n> {\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private getOwnerNftApi({\n address,\n offset,\n }: {\n address: string;\n offset: number;\n }) {\n return `${OPENSEA_PROXY_URL}/assets?owner=${address}&offset=${offset}&limit=50`;\n }\n\n private async getOwnerNfts(address: string) {\n let nftApiResponse: { assets: ApiNft[] };\n let nfts: ApiNft[] = [];\n let offset = 0;\n let pagingFinish = false;\n /* istanbul ignore if */\n do {\n nftApiResponse = await fetchWithErrorHandling({\n url: this.getOwnerNftApi({ address, offset }),\n timeout: 15000,\n });\n\n if (!nftApiResponse) {\n return nfts;\n }\n\n nftApiResponse?.assets?.length !== 0\n ? (nfts = [...nfts, ...nftApiResponse.assets])\n : (pagingFinish = true);\n offset += 50;\n } while (!pagingFinish);\n\n return nfts;\n }\n\n /**\n * Name of this controller used during composition\n */\n override name = 'NftDetectionController';\n\n private readonly getOpenSeaApiKey: () => string | undefined;\n\n private readonly addNft: NftController['addNft'];\n\n private readonly getNftState: () => NftState;\n\n /**\n * Creates an NftDetectionController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onNftsStateChange - Allows subscribing to assets controller state changes.\n * @param options.onPreferencesStateChange - Allows subscribing to preferences controller state changes.\n * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.\n * @param options.getOpenSeaApiKey - Gets the OpenSea API key, if one is set.\n * @param options.addNft - Add an NFT.\n * @param options.getNftState - Gets the current state of the Assets controller.\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 getOpenSeaApiKey,\n addNft,\n getNftState,\n }: {\n chainId: Hex;\n onNftsStateChange: (listener: (nftsState: NftState) => void) => void;\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n getOpenSeaApiKey: () => string | undefined;\n addNft: NftController['addNft'];\n getNftState: () => NftState;\n },\n config?: Partial<NftDetectionConfig>,\n state?: Partial<BaseState>,\n ) {\n super(config, state);\n this.defaultConfig = {\n interval: DEFAULT_INTERVAL,\n chainId: initialChainId,\n selectedAddress: '',\n disabled: true,\n };\n this.initialize();\n this.getNftState = getNftState;\n onPreferencesStateChange(({ selectedAddress, useNftDetection }) => {\n const { selectedAddress: previouslySelectedAddress, disabled } =\n this.config;\n\n if (\n selectedAddress !== previouslySelectedAddress ||\n !useNftDetection !== disabled\n ) {\n this.configure({ selectedAddress, disabled: !useNftDetection });\n }\n\n if (useNftDetection !== undefined) {\n if (useNftDetection) {\n this.start();\n } else {\n this.stop();\n }\n }\n });\n\n onNetworkStateChange(({ providerConfig }) => {\n this.configure({\n chainId: providerConfig.chainId,\n });\n });\n this.getOpenSeaApiKey = getOpenSeaApiKey;\n this.addNft = addNft;\n }\n\n /**\n * Start polling for the currency rate.\n */\n async start() {\n if (!this.isMainnet() || this.disabled) {\n return;\n }\n\n await this.startPolling();\n }\n\n /**\n * Stop polling for the currency rate.\n */\n stop() {\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 * @param interval - An interval on which to poll.\n */\n private async startPolling(interval?: number): Promise<void> {\n interval && this.configure({ interval }, false, false);\n this.stopPolling();\n await this.detectNfts();\n this.intervalId = setInterval(async () => {\n await this.detectNfts();\n }, this.config.interval);\n }\n\n /**\n * Checks whether network is mainnet or not.\n *\n * @returns Whether current network is mainnet.\n */\n isMainnet = (): boolean => this.config.chainId === ChainId.mainnet;\n\n /**\n * Triggers asset ERC721 token auto detection on mainnet. Any newly detected NFTs are\n * added.\n */\n async detectNfts() {\n /* istanbul ignore if */\n if (!this.isMainnet() || this.disabled) {\n return;\n }\n const { selectedAddress, chainId } = this.config;\n\n /* istanbul ignore else */\n if (!selectedAddress) {\n return;\n }\n\n const apiNfts = await this.getOwnerNfts(selectedAddress);\n const addNftPromises = apiNfts.map(async (nft: ApiNft) => {\n const {\n token_id,\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 asset_contract: { address, schema_name },\n last_sale,\n } = nft;\n\n let ignored;\n /* istanbul ignore else */\n const { ignoredNfts } = this.getNftState();\n if (ignoredNfts.length) {\n ignored = ignoredNfts.find((c) => {\n /* istanbul ignore next */\n return (\n c.address === toChecksumHexAddress(address) &&\n c.tokenId === token_id\n );\n });\n }\n\n /* istanbul ignore else */\n if (!ignored) {\n /* istanbul ignore next */\n const nftMetadata: NftMetadata = Object.assign(\n {},\n { name },\n creator && { creator },\n description && { description },\n image_url && { image: image_url },\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 schema_name && { standard: schema_name },\n external_link && { externalLink: external_link },\n last_sale && { lastSale: last_sale },\n );\n\n await this.addNft(address, token_id, {\n nftMetadata,\n userAddress: selectedAddress,\n chainId,\n source: Source.Detected,\n });\n }\n });\n await Promise.all(addNftPromises);\n }\n}\n\nexport default NftDetectionController;\n"]}
|
|
1
|
+
{"version":3,"file":"NftDetectionController.js","sourceRoot":"","sources":["../src/NftDetectionController.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,iEAKoC;AAOpC,qEAAmE;AAInE,2CAAqC;AAGrC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AA+GhC;;GAEG;AACH,MAAa,sBAAuB,SAAQ,wCAG3C;IAmDC;;;;;;;;;;;;;;OAcG;IACH,YACE,EACE,OAAO,EAAE,cAAc,EACvB,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,EACpB,gBAAgB,EAChB,MAAM,EACN,WAAW,GAcZ,EACD,MAAoC,EACpC,KAA0B;QAE1B,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAtDvB;;WAEG;QACM,SAAI,GAAG,wBAAwB,CAAC;QAwIzC;;;;WAIG;QACH,cAAS,GAAG,GAAY,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,KAAK,0BAAO,CAAC,OAAO,CAAC;QAEnE,+BAA0B,GAAG,CAAC,aAA4B,EAAW,EAAE;YACrE,OAAO,aAAa,CAAC,aAAa,CAAC,OAAO,KAAK,0BAAO,CAAC,OAAO,CAAC;QACjE,CAAC,CAAC;QA7FA,IAAI,CAAC,aAAa,GAAG;YACnB,QAAQ,EAAE,gBAAgB;YAC1B,OAAO,EAAE,cAAc;YACvB,eAAe,EAAE,EAAE;YACnB,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,oBAAoB,GAAG,oBAAoB,CAAC;QACjD,wBAAwB,CAAC,CAAC,EAAE,eAAe,EAAE,eAAe,EAAE,EAAE,EAAE;YAChE,MAAM,EAAE,eAAe,EAAE,yBAAyB,EAAE,QAAQ,EAAE,GAC5D,IAAI,CAAC,MAAM,CAAC;YAEd,IACE,eAAe,KAAK,yBAAyB;gBAC7C,CAAC,eAAe,KAAK,QAAQ,EAC7B;gBACA,IAAI,CAAC,SAAS,CAAC,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;aACjE;YAED,IAAI,eAAe,KAAK,SAAS,EAAE;gBACjC,IAAI,eAAe,EAAE;oBACnB,IAAI,CAAC,KAAK,EAAE,CAAC;iBACd;qBAAM;oBACL,IAAI,CAAC,IAAI,EAAE,CAAC;iBACb;aACF;QACH,CAAC,CAAC,CAAC;QAEH,oBAAoB,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE;YAC1C,IAAI,CAAC,SAAS,CAAC;gBACb,OAAO,EAAE,cAAc,CAAC,OAAO;aAChC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IA/HO,cAAc,CAAC,EACrB,OAAO,EACP,MAAM,GAIP;QACC,OAAO,GAAG,oCAAiB,iBAAiB,OAAO,WAAW,MAAM,WAAW,CAAC;IAClF,CAAC;IAEa,YAAY,CAAC,OAAe;;;YACxC,IAAI,cAAoC,CAAC;YACzC,IAAI,IAAI,GAAa,EAAE,CAAC;YACxB,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,IAAI,YAAY,GAAG,KAAK,CAAC;YACzB,wBAAwB;YACxB,GAAG;gBACD,cAAc,GAAG,MAAM,IAAA,yCAAsB,EAAC;oBAC5C,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;oBAC7C,OAAO,EAAE,KAAK;iBACf,CAAC,CAAC;gBAEH,IAAI,CAAC,cAAc,EAAE;oBACnB,OAAO,IAAI,CAAC;iBACb;gBAED,CAAA,MAAA,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,MAAM,0CAAE,MAAM,MAAK,CAAC;oBAClC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;oBAC9C,CAAC,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;gBAC1B,MAAM,IAAI,EAAE,CAAC;aACd,QAAQ,CAAC,YAAY,EAAE;YAExB,OAAO,IAAI,CAAC;;KACb;IAgGK,YAAY,CAChB,eAAuB,EACvB,OAA4B;;YAE5B,MAAM,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1D,CAAC;KAAA;IAED;;OAEG;IACG,KAAK;;YACT,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACtC,OAAO;aACR;YAED,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;KAAA;IAED;;OAEG;IACH,IAAI;QACF,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAEO,WAAW;QACjB,IAAI,IAAI,CAAC,UAAU,EAAE;YACnB,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;SAChC;IACH,CAAC;IAED;;;;OAIG;IACW,YAAY,CAAC,QAAiB;;YAC1C,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YACvD,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YACxB,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,GAAS,EAAE;gBACvC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1B,CAAC,CAAA,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;KAAA;IAaO,iBAAiB,CAAC,eAAiC;QACzD,IAAI,eAAe,EAAE;YACnB,OAAO,IAAI,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC;SACzE;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;IAC7B,CAAC;IAED;;;;;;OAMG;IACG,UAAU,CAAC,eAAiC,EAAE,cAAuB;;YACzE,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;YAExD,MAAM,eAAe,GAAG,cAAc,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;YAEtE,wBAAwB;YACxB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACtC,OAAO;aACR;YACD,0BAA0B;YAC1B,IAAI,CAAC,eAAe,EAAE;gBACpB,OAAO;aACR;YAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;YACzD,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,CAAO,GAAW,EAAE,EAAE;gBACvD,MAAM,EACJ,QAAQ,EACR,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,IAAI,EACJ,WAAW,EACX,aAAa,EACb,OAAO,EACP,cAAc,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EACxC,SAAS,GACV,GAAG,GAAG,CAAC;gBAER,IAAI,OAAO,CAAC;gBACZ,0BAA0B;gBAC1B,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC3C,IAAI,WAAW,CAAC,MAAM,EAAE;oBACtB,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;wBAC/B,0BAA0B;wBAC1B,OAAO,CACL,CAAC,CAAC,OAAO,KAAK,IAAA,uCAAoB,EAAC,OAAO,CAAC;4BAC3C,CAAC,CAAC,OAAO,KAAK,QAAQ,CACvB,CAAC;oBACJ,CAAC,CAAC,CAAC;iBACJ;gBAED,0BAA0B;gBAC1B,IAAI,CAAC,OAAO,EAAE;oBACZ,0BAA0B;oBAC1B,MAAM,WAAW,GAAgB,MAAM,CAAC,MAAM,CAC5C,EAAE,EACF,EAAE,IAAI,EAAE,EACR,OAAO,IAAI,EAAE,OAAO,EAAE,EACtB,WAAW,IAAI,EAAE,WAAW,EAAE,EAC9B,SAAS,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,EACjC,SAAS,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,EACzC,gBAAgB,IAAI,EAAE,eAAe,EAAE,gBAAgB,EAAE,EACzD,iBAAiB,IAAI,EAAE,YAAY,EAAE,iBAAiB,EAAE,EACxD,mBAAmB,IAAI,EAAE,cAAc,EAAE,mBAAmB,EAAE,EAC9D,kBAAkB,IAAI,EAAE,aAAa,EAAE,kBAAkB,EAAE,EAC3D,aAAa,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,EAC7C,sBAAsB,IAAI;wBACxB,iBAAiB,EAAE,sBAAsB;qBAC1C,EACD,WAAW,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,EACxC,aAAa,IAAI,EAAE,YAAY,EAAE,aAAa,EAAE,EAChD,SAAS,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CACrC,CAAC;oBAEF,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE;wBACnC,WAAW;wBACX,WAAW,EAAE,eAAe;wBAC5B,OAAO;wBACP,MAAM,EAAE,kBAAM,CAAC,QAAQ;qBACxB,CAAC,CAAC;iBACJ;YACH,CAAC,CAAA,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACpC,CAAC;KAAA;CACF;AA7RD,wDA6RC;AAED,kBAAe,sBAAsB,CAAC","sourcesContent":["import type { BaseConfig, BaseState } from '@metamask/base-controller';\nimport {\n OPENSEA_PROXY_URL,\n fetchWithErrorHandling,\n toChecksumHexAddress,\n ChainId,\n} from '@metamask/controller-utils';\nimport type {\n NetworkClientId,\n NetworkController,\n NetworkState,\n NetworkClient,\n} from '@metamask/network-controller';\nimport { PollingControllerV1 } from '@metamask/polling-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport { Source } from './constants';\nimport type { NftController, NftState, NftMetadata } from './NftController';\n\nconst DEFAULT_INTERVAL = 180000;\n\n/**\n * @type ApiNft\n *\n * NFT object coming from OpenSea api\n * @property token_id - The NFT identifier\n * @property num_sales - Number of sales\n * @property background_color - The background color to be displayed with the item\n * @property image_url - URI of an image associated with this NFT\n * @property image_preview_url - URI of a smaller image associated with this NFT\n * @property image_thumbnail_url - URI of a thumbnail image associated with this NFT\n * @property image_original_url - URI of the original image associated with this NFT\n * @property animation_url - URI of a animation associated with this NFT\n * @property animation_original_url - URI of the original animation associated with this NFT\n * @property name - The NFT name\n * @property description - The NFT description\n * @property external_link - External link containing additional information\n * @property assetContract - The NFT contract information object\n * @property creator - The NFT owner information object\n * @property lastSale - When this item was last sold\n */\nexport interface ApiNft {\n token_id: string;\n num_sales: number | null;\n background_color: string | null;\n image_url: string | null;\n image_preview_url: string | null;\n image_thumbnail_url: string | null;\n image_original_url: string | null;\n animation_url: string | null;\n animation_original_url: string | null;\n name: string | null;\n description: string | null;\n external_link: string | null;\n asset_contract: ApiNftContract;\n creator: ApiNftCreator;\n last_sale: ApiNftLastSale | null;\n}\n\n/**\n * @type ApiNftContract\n *\n * NFT contract object coming from OpenSea api\n * @property address - Address of the NFT contract\n * @property asset_contract_type - The NFT type, it could be `semi-fungible` or `non-fungible`\n * @property created_date - Creation date\n * @property collection - Object containing the contract name and URI of an image associated\n * @property schema_name - The schema followed by the contract, it could be `ERC721` or `ERC1155`\n * @property symbol - The NFT contract symbol\n * @property total_supply - Total supply of NFTs\n * @property description - The NFT contract description\n * @property external_link - External link containing additional information\n */\nexport interface ApiNftContract {\n address: string;\n asset_contract_type: string | null;\n created_date: string | null;\n schema_name: string | null;\n symbol: string | null;\n total_supply: string | null;\n description: string | null;\n external_link: string | null;\n collection: {\n name: string | null;\n image_url?: string | null;\n };\n}\n\n/**\n * @type ApiNftLastSale\n *\n * NFT sale object coming from OpenSea api\n * @property event_timestamp - Object containing a `username`\n * @property total_price - URI of NFT image associated with this owner\n * @property transaction - Object containing transaction_hash and block_hash\n */\nexport interface ApiNftLastSale {\n event_timestamp: string;\n total_price: string;\n transaction: { transaction_hash: string; block_hash: string };\n}\n\n/**\n * @type ApiNftCreator\n *\n * NFT creator object coming from OpenSea api\n * @property user - Object containing a `username`\n * @property profile_img_url - URI of NFT image associated with this owner\n * @property address - The owner address\n */\nexport interface ApiNftCreator {\n user: { username: string };\n profile_img_url: string;\n address: string;\n}\n\n/**\n * @type NftDetectionConfig\n *\n * NftDetection configuration\n * @property interval - Polling interval used to fetch new token rates\n * @property chainId - Current chain ID\n * @property selectedAddress - Vault selected address\n */\nexport interface NftDetectionConfig extends BaseConfig {\n interval: number;\n chainId: Hex;\n selectedAddress: string;\n}\n\n/**\n * Controller that passively polls on a set interval for NFT auto detection\n */\nexport class NftDetectionController extends PollingControllerV1<\n NftDetectionConfig,\n BaseState\n> {\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private getOwnerNftApi({\n address,\n offset,\n }: {\n address: string;\n offset: number;\n }) {\n return `${OPENSEA_PROXY_URL}/assets?owner=${address}&offset=${offset}&limit=50`;\n }\n\n private async getOwnerNfts(address: string) {\n let nftApiResponse: { assets: ApiNft[] };\n let nfts: ApiNft[] = [];\n let offset = 0;\n let pagingFinish = false;\n /* istanbul ignore if */\n do {\n nftApiResponse = await fetchWithErrorHandling({\n url: this.getOwnerNftApi({ address, offset }),\n timeout: 15000,\n });\n\n if (!nftApiResponse) {\n return nfts;\n }\n\n nftApiResponse?.assets?.length !== 0\n ? (nfts = [...nfts, ...nftApiResponse.assets])\n : (pagingFinish = true);\n offset += 50;\n } while (!pagingFinish);\n\n return nfts;\n }\n\n /**\n * Name of this controller used during composition\n */\n override name = 'NftDetectionController';\n\n private readonly getOpenSeaApiKey: () => string | undefined;\n\n private readonly addNft: NftController['addNft'];\n\n private readonly getNftState: () => NftState;\n\n private readonly getNetworkClientById: NetworkController['getNetworkClientById'];\n\n /**\n * Creates an NftDetectionController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onNftsStateChange - Allows subscribing to assets controller state changes.\n * @param options.onPreferencesStateChange - Allows subscribing to preferences controller state changes.\n * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.\n * @param options.getOpenSeaApiKey - Gets the OpenSea API key, if one is set.\n * @param options.addNft - Add an NFT.\n * @param options.getNftState - Gets the current state of the Assets controller.\n * @param options.getNetworkClientById - Gets the network client by 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 getNetworkClientById,\n onPreferencesStateChange,\n onNetworkStateChange,\n getOpenSeaApiKey,\n addNft,\n getNftState,\n }: {\n chainId: Hex;\n getNetworkClientById: NetworkController['getNetworkClientById'];\n onNftsStateChange: (listener: (nftsState: NftState) => void) => void;\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n getOpenSeaApiKey: () => string | undefined;\n addNft: NftController['addNft'];\n getNftState: () => NftState;\n },\n config?: Partial<NftDetectionConfig>,\n state?: Partial<BaseState>,\n ) {\n super(config, state);\n this.defaultConfig = {\n interval: DEFAULT_INTERVAL,\n chainId: initialChainId,\n selectedAddress: '',\n disabled: true,\n };\n this.initialize();\n this.getNftState = getNftState;\n this.getNetworkClientById = getNetworkClientById;\n onPreferencesStateChange(({ selectedAddress, useNftDetection }) => {\n const { selectedAddress: previouslySelectedAddress, disabled } =\n this.config;\n\n if (\n selectedAddress !== previouslySelectedAddress ||\n !useNftDetection !== disabled\n ) {\n this.configure({ selectedAddress, disabled: !useNftDetection });\n }\n\n if (useNftDetection !== undefined) {\n if (useNftDetection) {\n this.start();\n } else {\n this.stop();\n }\n }\n });\n\n onNetworkStateChange(({ providerConfig }) => {\n this.configure({\n chainId: providerConfig.chainId,\n });\n });\n this.getOpenSeaApiKey = getOpenSeaApiKey;\n this.addNft = addNft;\n this.setIntervalLength(this.config.interval);\n }\n\n async _executePoll(\n networkClientId: string,\n options: { address: string },\n ): Promise<void> {\n await this.detectNfts(networkClientId, options.address);\n }\n\n /**\n * Start polling for the currency rate.\n */\n async start() {\n if (!this.isMainnet() || this.disabled) {\n return;\n }\n\n await this.startPolling();\n }\n\n /**\n * Stop polling for the currency rate.\n */\n stop() {\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 * @param interval - An interval on which to poll.\n */\n private async startPolling(interval?: number): Promise<void> {\n interval && this.configure({ interval }, false, false);\n this.stopPolling();\n await this.detectNfts();\n this.intervalId = setInterval(async () => {\n await this.detectNfts();\n }, this.config.interval);\n }\n\n /**\n * Checks whether network is mainnet or not.\n *\n * @returns Whether current network is mainnet.\n */\n isMainnet = (): boolean => this.config.chainId === ChainId.mainnet;\n\n isMainnetByNetworkClientId = (networkClient: NetworkClient): boolean => {\n return networkClient.configuration.chainId === ChainId.mainnet;\n };\n\n private getCorrectChainId(networkClientId?: NetworkClientId) {\n if (networkClientId) {\n return this.getNetworkClientById(networkClientId).configuration.chainId;\n }\n return this.config.chainId;\n }\n\n /**\n * Triggers asset ERC721 token auto detection on mainnet. Any newly detected NFTs are\n * added.\n *\n * @param networkClientId - The network client ID to detect NFTs on.\n * @param accountAddress - The address to detect NFTs for.\n */\n async detectNfts(networkClientId?: NetworkClientId, accountAddress?: string) {\n const chainId = this.getCorrectChainId(networkClientId);\n\n const selectedAddress = accountAddress || this.config.selectedAddress;\n\n /* istanbul ignore if */\n if (!this.isMainnet() || this.disabled) {\n return;\n }\n /* istanbul ignore else */\n if (!selectedAddress) {\n return;\n }\n\n const apiNfts = await this.getOwnerNfts(selectedAddress);\n const addNftPromises = apiNfts.map(async (nft: ApiNft) => {\n const {\n token_id,\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 asset_contract: { address, schema_name },\n last_sale,\n } = nft;\n\n let ignored;\n /* istanbul ignore else */\n const { ignoredNfts } = this.getNftState();\n if (ignoredNfts.length) {\n ignored = ignoredNfts.find((c) => {\n /* istanbul ignore next */\n return (\n c.address === toChecksumHexAddress(address) &&\n c.tokenId === token_id\n );\n });\n }\n\n /* istanbul ignore else */\n if (!ignored) {\n /* istanbul ignore next */\n const nftMetadata: NftMetadata = Object.assign(\n {},\n { name },\n creator && { creator },\n description && { description },\n image_url && { image: image_url },\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 schema_name && { standard: schema_name },\n external_link && { externalLink: external_link },\n last_sale && { lastSale: last_sale },\n );\n\n await this.addNft(address, token_id, {\n nftMetadata,\n userAddress: selectedAddress,\n chainId,\n source: Source.Detected,\n });\n }\n });\n await Promise.all(addNftPromises);\n }\n}\n\nexport default NftDetectionController;\n"]}
|
|
@@ -74,15 +74,15 @@ class TokenBalancesController extends base_controller_1.BaseController {
|
|
|
74
74
|
}
|
|
75
75
|
const { tokens } = this.config;
|
|
76
76
|
const newContractBalances = {};
|
|
77
|
-
for (const
|
|
78
|
-
const { address } =
|
|
77
|
+
for (const token of tokens) {
|
|
78
|
+
const { address } = token;
|
|
79
79
|
try {
|
|
80
80
|
newContractBalances[address] = yield this.getERC20BalanceOf(address, this.getSelectedAddress());
|
|
81
|
-
|
|
81
|
+
token.balanceError = null;
|
|
82
82
|
}
|
|
83
83
|
catch (error) {
|
|
84
84
|
newContractBalances[address] = new ethereumjs_util_1.BN(0);
|
|
85
|
-
|
|
85
|
+
token.balanceError = error;
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
this.update({ contractBalances: newContractBalances });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenBalancesController.js","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,+DAA2D;AAC3D,iEAA2D;AAE3D,qDAAqC;AAO5B,mFAPA,oBAAE,OAOA;AAwBX;;;GAGG;AACH,MAAa,uBAAwB,SAAQ,gCAG5C;IAYC;;;;;;;;;OASG;IACH,YACE,EACE,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,GAOlB,EACD,MAAqC,EACrC,KAAmC;QAEnC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAlCvB;;WAEG;QACM,SAAI,GAAG,yBAAyB,CAAC;QAgCxC,IAAI,CAAC,aAAa,GAAG;YACnB,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,EAAE;SACX,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,EAAE,gBAAgB,EAAE,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,EAAE,EAAE;YACjD,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;YAC3D,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;QAC7C,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED;;;;OAIG;IACG,IAAI,CAAC,QAAiB;;YAC1B,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YACvD,IAAI,CAAC,MAAM,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzC,MAAM,IAAA,gCAAa,EAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;YACjD,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAClC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;KAAA;IAED;;OAEG;IACG,cAAc;;YAClB,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACjB,OAAO;aACR;YACD,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;YAC/B,MAAM,mBAAmB,GAA8B,EAAE,CAAC;YAC1D,KAAK,MAAM,
|
|
1
|
+
{"version":3,"file":"TokenBalancesController.js","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,+DAA2D;AAC3D,iEAA2D;AAE3D,qDAAqC;AAO5B,mFAPA,oBAAE,OAOA;AAwBX;;;GAGG;AACH,MAAa,uBAAwB,SAAQ,gCAG5C;IAYC;;;;;;;;;OASG;IACH,YACE,EACE,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,GAOlB,EACD,MAAqC,EACrC,KAAmC;QAEnC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAlCvB;;WAEG;QACM,SAAI,GAAG,yBAAyB,CAAC;QAgCxC,IAAI,CAAC,aAAa,GAAG;YACnB,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,EAAE;SACX,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,EAAE,gBAAgB,EAAE,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,EAAE,EAAE;YACjD,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;YAC3D,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;QAC7C,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED;;;;OAIG;IACG,IAAI,CAAC,QAAiB;;YAC1B,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YACvD,IAAI,CAAC,MAAM,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzC,MAAM,IAAA,gCAAa,EAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;YACjD,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAClC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;KAAA;IAED;;OAEG;IACG,cAAc;;YAClB,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACjB,OAAO;aACR;YACD,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;YAC/B,MAAM,mBAAmB,GAA8B,EAAE,CAAC;YAC1D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;gBAC1B,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;gBAC1B,IAAI;oBACF,mBAAmB,CAAC,OAAO,CAAC,GAAG,MAAM,IAAI,CAAC,iBAAiB,CACzD,OAAO,EACP,IAAI,CAAC,kBAAkB,EAAE,CAC1B,CAAC;oBACF,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;iBAC3B;gBAAC,OAAO,KAAK,EAAE;oBACd,mBAAmB,CAAC,OAAO,CAAC,GAAG,IAAI,oBAAE,CAAC,CAAC,CAAC,CAAC;oBACzC,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC;iBAC5B;aACF;YACD,IAAI,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACzD,CAAC;KAAA;CACF;AA9FD,0DA8FC;AAED,kBAAe,uBAAuB,CAAC","sourcesContent":["import type { BaseConfig, BaseState } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport { BN } from 'ethereumjs-util';\n\nimport type { AssetsContractController } from './AssetsContractController';\nimport type { Token } from './TokenRatesController';\nimport type { TokensState } from './TokensController';\n\n// TODO: Remove this export in the next major release\nexport { BN };\n\n/**\n * @type TokenBalancesConfig\n *\n * Token balances controller configuration\n * @property interval - Polling interval used to fetch new token balances\n * @property tokens - List of tokens to track balances for\n */\nexport interface TokenBalancesConfig extends BaseConfig {\n interval: number;\n tokens: Token[];\n}\n\n/**\n * @type TokenBalancesState\n *\n * Token balances controller state\n * @property contractBalances - Hash of token contract addresses to balances\n */\nexport interface TokenBalancesState extends BaseState {\n contractBalances: { [address: string]: BN };\n}\n\n/**\n * Controller that passively polls on a set interval token balances\n * for tokens stored in the TokensController\n */\nexport class TokenBalancesController extends BaseController<\n TokenBalancesConfig,\n TokenBalancesState\n> {\n private handle?: ReturnType<typeof setTimeout>;\n\n /**\n * Name of this controller used during composition\n */\n override name = 'TokenBalancesController';\n\n private readonly getSelectedAddress: () => PreferencesState['selectedAddress'];\n\n private readonly getERC20BalanceOf: AssetsContractController['getERC20BalanceOf'];\n\n /**\n * Creates a TokenBalancesController instance.\n *\n * @param options - The controller options.\n * @param options.onTokensStateChange - Allows subscribing to assets controller state changes.\n * @param options.getSelectedAddress - Gets the current selected address.\n * @param options.getERC20BalanceOf - Gets the balance of the given account at the given contract address.\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 onTokensStateChange,\n getSelectedAddress,\n getERC20BalanceOf,\n }: {\n onTokensStateChange: (\n listener: (tokenState: TokensState) => void,\n ) => void;\n getSelectedAddress: () => PreferencesState['selectedAddress'];\n getERC20BalanceOf: AssetsContractController['getERC20BalanceOf'];\n },\n config?: Partial<TokenBalancesConfig>,\n state?: Partial<TokenBalancesState>,\n ) {\n super(config, state);\n this.defaultConfig = {\n interval: 180000,\n tokens: [],\n };\n this.defaultState = { contractBalances: {} };\n this.initialize();\n onTokensStateChange(({ tokens, detectedTokens }) => {\n this.configure({ tokens: [...tokens, ...detectedTokens] });\n this.updateBalances();\n });\n this.getSelectedAddress = getSelectedAddress;\n this.getERC20BalanceOf = getERC20BalanceOf;\n this.poll();\n }\n\n /**\n * Starts a new polling interval.\n *\n * @param interval - Polling interval used to fetch new token balances.\n */\n async poll(interval?: number): Promise<void> {\n interval && this.configure({ interval }, false, false);\n this.handle && clearTimeout(this.handle);\n await safelyExecute(() => this.updateBalances());\n this.handle = setTimeout(() => {\n this.poll(this.config.interval);\n }, this.config.interval);\n }\n\n /**\n * Updates balances for all tokens.\n */\n async updateBalances() {\n if (this.disabled) {\n return;\n }\n const { tokens } = this.config;\n const newContractBalances: { [address: string]: BN } = {};\n for (const token of tokens) {\n const { address } = token;\n try {\n newContractBalances[address] = await this.getERC20BalanceOf(\n address,\n this.getSelectedAddress(),\n );\n token.balanceError = null;\n } catch (error) {\n newContractBalances[address] = new BN(0);\n token.balanceError = error;\n }\n }\n this.update({ contractBalances: newContractBalances });\n }\n}\n\nexport default TokenBalancesController;\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BaseConfig, BaseState } from '@metamask/base-controller';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
2
|
+
import type { NetworkClientId, NetworkController, NetworkState } from '@metamask/network-controller';
|
|
3
|
+
import { PollingControllerV1 } from '@metamask/polling-controller';
|
|
4
4
|
import type { PreferencesState } from '@metamask/preferences-controller';
|
|
5
5
|
import type { Hex } from '@metamask/utils';
|
|
6
6
|
import type { AssetsContractController } from './AssetsContractController';
|
|
@@ -26,7 +26,7 @@ export interface TokenDetectionConfig extends BaseConfig {
|
|
|
26
26
|
/**
|
|
27
27
|
* Controller that passively polls on a set interval for Tokens auto detection
|
|
28
28
|
*/
|
|
29
|
-
export declare class TokenDetectionController extends
|
|
29
|
+
export declare class TokenDetectionController extends PollingControllerV1<TokenDetectionConfig, BaseState> {
|
|
30
30
|
private intervalId?;
|
|
31
31
|
/**
|
|
32
32
|
* Name of this controller used during composition
|
|
@@ -36,6 +36,7 @@ export declare class TokenDetectionController extends BaseController<TokenDetect
|
|
|
36
36
|
private readonly addDetectedTokens;
|
|
37
37
|
private readonly getTokensState;
|
|
38
38
|
private readonly getTokenListState;
|
|
39
|
+
private readonly getNetworkClientById;
|
|
39
40
|
/**
|
|
40
41
|
* Creates a TokenDetectionController instance.
|
|
41
42
|
*
|
|
@@ -49,10 +50,11 @@ export declare class TokenDetectionController extends BaseController<TokenDetect
|
|
|
49
50
|
* @param options.getTokensState - Gets the current state of the Tokens controller.
|
|
50
51
|
* @param options.getNetworkState - Gets the state of the network controller.
|
|
51
52
|
* @param options.getPreferencesState - Gets the state of the preferences controller.
|
|
53
|
+
* @param options.getNetworkClientById - Gets the network client by ID.
|
|
52
54
|
* @param config - Initial options used to configure this controller.
|
|
53
55
|
* @param state - Initial state to set on this controller.
|
|
54
56
|
*/
|
|
55
|
-
constructor({ onPreferencesStateChange, onNetworkStateChange, onTokenListStateChange, getBalancesInSingleCall, addDetectedTokens, getTokenListState, getTokensState, getNetworkState, getPreferencesState, }: {
|
|
57
|
+
constructor({ onPreferencesStateChange, onNetworkStateChange, onTokenListStateChange, getBalancesInSingleCall, addDetectedTokens, getTokenListState, getTokensState, getNetworkState, getPreferencesState, getNetworkClientById, }: {
|
|
56
58
|
onPreferencesStateChange: (listener: (preferencesState: PreferencesState) => void) => void;
|
|
57
59
|
onNetworkStateChange: (listener: (networkState: NetworkState) => void) => void;
|
|
58
60
|
onTokenListStateChange: (listener: (tokenListState: TokenListState) => void) => void;
|
|
@@ -62,6 +64,7 @@ export declare class TokenDetectionController extends BaseController<TokenDetect
|
|
|
62
64
|
getTokensState: () => TokensState;
|
|
63
65
|
getNetworkState: () => NetworkState;
|
|
64
66
|
getPreferencesState: () => PreferencesState;
|
|
67
|
+
getNetworkClientById: NetworkController['getNetworkClientById'];
|
|
65
68
|
}, config?: Partial<TokenDetectionConfig>, state?: Partial<BaseState>);
|
|
66
69
|
/**
|
|
67
70
|
* Start polling for detected tokens.
|
|
@@ -78,10 +81,21 @@ export declare class TokenDetectionController extends BaseController<TokenDetect
|
|
|
78
81
|
* @param interval - An interval on which to poll.
|
|
79
82
|
*/
|
|
80
83
|
private startPolling;
|
|
84
|
+
private getCorrectChainId;
|
|
85
|
+
_executePoll(networkClientId: string, options: {
|
|
86
|
+
address: string;
|
|
87
|
+
}): Promise<void>;
|
|
81
88
|
/**
|
|
82
89
|
* Triggers asset ERC20 token auto detection for each contract address in contract metadata on mainnet.
|
|
90
|
+
*
|
|
91
|
+
* @param options - Options to detect tokens.
|
|
92
|
+
* @param options.networkClientId - The ID of the network client to use.
|
|
93
|
+
* @param options.accountAddress - The account address to use.
|
|
83
94
|
*/
|
|
84
|
-
detectTokens(
|
|
95
|
+
detectTokens(options?: {
|
|
96
|
+
networkClientId?: NetworkClientId;
|
|
97
|
+
accountAddress?: string;
|
|
98
|
+
}): Promise<void>;
|
|
85
99
|
}
|
|
86
100
|
export default TokenDetectionController;
|
|
87
101
|
//# sourceMappingURL=TokenDetectionController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenDetectionController.d.ts","sourceRoot":"","sources":["../src/TokenDetectionController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"TokenDetectionController.d.ts","sourceRoot":"","sources":["../src/TokenDetectionController.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,14 +10,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.TokenDetectionController = void 0;
|
|
13
|
-
const base_controller_1 = require("@metamask/base-controller");
|
|
14
13
|
const controller_utils_1 = require("@metamask/controller-utils");
|
|
14
|
+
const polling_controller_1 = require("@metamask/polling-controller");
|
|
15
15
|
const assetsUtil_1 = require("./assetsUtil");
|
|
16
16
|
const DEFAULT_INTERVAL = 180000;
|
|
17
17
|
/**
|
|
18
18
|
* Controller that passively polls on a set interval for Tokens auto detection
|
|
19
19
|
*/
|
|
20
|
-
class TokenDetectionController extends
|
|
20
|
+
class TokenDetectionController extends polling_controller_1.PollingControllerV1 {
|
|
21
21
|
/**
|
|
22
22
|
* Creates a TokenDetectionController instance.
|
|
23
23
|
*
|
|
@@ -31,10 +31,11 @@ class TokenDetectionController extends base_controller_1.BaseController {
|
|
|
31
31
|
* @param options.getTokensState - Gets the current state of the Tokens controller.
|
|
32
32
|
* @param options.getNetworkState - Gets the state of the network controller.
|
|
33
33
|
* @param options.getPreferencesState - Gets the state of the preferences controller.
|
|
34
|
+
* @param options.getNetworkClientById - Gets the network client by ID.
|
|
34
35
|
* @param config - Initial options used to configure this controller.
|
|
35
36
|
* @param state - Initial state to set on this controller.
|
|
36
37
|
*/
|
|
37
|
-
constructor({ onPreferencesStateChange, onNetworkStateChange, onTokenListStateChange, getBalancesInSingleCall, addDetectedTokens, getTokenListState, getTokensState, getNetworkState, getPreferencesState, }, config, state) {
|
|
38
|
+
constructor({ onPreferencesStateChange, onNetworkStateChange, onTokenListStateChange, getBalancesInSingleCall, addDetectedTokens, getTokenListState, getTokensState, getNetworkState, getPreferencesState, getNetworkClientById, }, config, state) {
|
|
38
39
|
const { providerConfig: { chainId: defaultChainId }, } = getNetworkState();
|
|
39
40
|
const { useTokenDetection: defaultUseTokenDetection } = getPreferencesState();
|
|
40
41
|
super(config, state);
|
|
@@ -48,6 +49,7 @@ class TokenDetectionController extends base_controller_1.BaseController {
|
|
|
48
49
|
this.getTokenListState = getTokenListState;
|
|
49
50
|
this.addDetectedTokens = addDetectedTokens;
|
|
50
51
|
this.getBalancesInSingleCall = getBalancesInSingleCall;
|
|
52
|
+
this.getNetworkClientById = getNetworkClientById;
|
|
51
53
|
onTokenListStateChange(({ tokenList }) => {
|
|
52
54
|
const hasTokens = Object.keys(tokenList).length;
|
|
53
55
|
if (hasTokens) {
|
|
@@ -116,11 +118,28 @@ class TokenDetectionController extends base_controller_1.BaseController {
|
|
|
116
118
|
}), this.config.interval);
|
|
117
119
|
});
|
|
118
120
|
}
|
|
121
|
+
getCorrectChainId(networkClientId) {
|
|
122
|
+
if (networkClientId) {
|
|
123
|
+
return this.getNetworkClientById(networkClientId).configuration.chainId;
|
|
124
|
+
}
|
|
125
|
+
return this.config.chainId;
|
|
126
|
+
}
|
|
127
|
+
_executePoll(networkClientId, options) {
|
|
128
|
+
return this.detectTokens({
|
|
129
|
+
networkClientId,
|
|
130
|
+
accountAddress: options.address,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
119
133
|
/**
|
|
120
134
|
* Triggers asset ERC20 token auto detection for each contract address in contract metadata on mainnet.
|
|
135
|
+
*
|
|
136
|
+
* @param options - Options to detect tokens.
|
|
137
|
+
* @param options.networkClientId - The ID of the network client to use.
|
|
138
|
+
* @param options.accountAddress - The account address to use.
|
|
121
139
|
*/
|
|
122
|
-
detectTokens() {
|
|
140
|
+
detectTokens(options) {
|
|
123
141
|
return __awaiter(this, void 0, void 0, function* () {
|
|
142
|
+
const { networkClientId, accountAddress } = options || {};
|
|
124
143
|
const { disabled, isDetectionEnabledForNetwork, isDetectionEnabledFromPreferences, } = this.config;
|
|
125
144
|
if (disabled ||
|
|
126
145
|
!isDetectionEnabledForNetwork ||
|
|
@@ -128,12 +147,13 @@ class TokenDetectionController extends base_controller_1.BaseController {
|
|
|
128
147
|
return;
|
|
129
148
|
}
|
|
130
149
|
const { tokens } = this.getTokensState();
|
|
131
|
-
const
|
|
150
|
+
const selectedAddress = accountAddress || this.config.selectedAddress;
|
|
151
|
+
const chainId = this.getCorrectChainId(networkClientId);
|
|
132
152
|
const tokensAddresses = tokens.map(
|
|
133
153
|
/* istanbul ignore next*/ (token) => token.address.toLowerCase());
|
|
134
154
|
const { tokenList } = this.getTokenListState();
|
|
135
155
|
const tokensToDetect = [];
|
|
136
|
-
for (const address
|
|
156
|
+
for (const address of Object.keys(tokenList)) {
|
|
137
157
|
if (!tokensAddresses.includes(address)) {
|
|
138
158
|
tokensToDetect.push(address);
|
|
139
159
|
}
|
|
@@ -152,7 +172,7 @@ class TokenDetectionController extends base_controller_1.BaseController {
|
|
|
152
172
|
yield (0, controller_utils_1.safelyExecute)(() => __awaiter(this, void 0, void 0, function* () {
|
|
153
173
|
const balances = yield this.getBalancesInSingleCall(selectedAddress, tokensSlice);
|
|
154
174
|
const tokensToAdd = [];
|
|
155
|
-
for (const tokenAddress
|
|
175
|
+
for (const tokenAddress of Object.keys(balances)) {
|
|
156
176
|
let ignored;
|
|
157
177
|
/* istanbul ignore else */
|
|
158
178
|
const { ignoredTokens } = this.getTokensState();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenDetectionController.js","sourceRoot":"","sources":["../src/TokenDetectionController.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,+DAA2D;AAC3D,iEAGoC;AAMpC,6CAAmE;AAKnE,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAoBhC;;GAEG;AACH,MAAa,wBAAyB,SAAQ,gCAG7C;IAgBC;;;;;;;;;;;;;;;OAeG;IACH,YACE,EACE,wBAAwB,EACxB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,mBAAmB,GAiBpB,EACD,MAAsC,EACtC,KAA0B;QAE1B,MAAM,EACJ,cAAc,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,GAC5C,GAAG,eAAe,EAAE,CAAC;QACtB,MAAM,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,GACnD,mBAAmB,EAAE,CAAC;QAExB,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAlEvB;;WAEG;QACM,SAAI,GAAG,0BAA0B,CAAC;QAgEzC,IAAI,CAAC,aAAa,mBAChB,QAAQ,EAAE,gBAAgB,EAC1B,eAAe,EAAE,EAAE,EACnB,QAAQ,EAAE,IAAI,EACd,OAAO,EAAE,cAAc,EACvB,iCAAiC,EAAE,wBAAwB,EAC3D,4BAA4B,EAC1B,IAAA,gDAAmC,EAAC,cAAc,CAAC,IAClD,MAAM,CACV,CAAC;QAEF,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,IAAI,CAAC,uBAAuB,GAAG,uBAAuB,CAAC;QAEvD,sBAAsB,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE;YACvC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;YAEhD,IAAI,SAAS,EAAE;gBACb,IAAI,CAAC,YAAY,EAAE,CAAC;aACrB;QACH,CAAC,CAAC,CAAC;QAEH,wBAAwB,CAAC,CAAC,EAAE,eAAe,EAAE,iBAAiB,EAAE,EAAE,EAAE;YAClE,MAAM,EACJ,eAAe,EAAE,sBAAsB,EACvC,iCAAiC,GAClC,GAAG,IAAI,CAAC,MAAM,CAAC;YAChB,MAAM,wBAAwB,GAC5B,eAAe,KAAK,sBAAsB,CAAC;YAC7C,MAAM,iCAAiC,GACrC,iCAAiC,KAAK,iBAAiB,CAAC;YAE1D,IAAI,CAAC,SAAS,CAAC;gBACb,iCAAiC,EAAE,iBAAiB;gBACpD,eAAe;aAChB,CAAC,CAAC;YAEH,IACE,iBAAiB;gBACjB,CAAC,wBAAwB,IAAI,iCAAiC,CAAC,EAC/D;gBACA,IAAI,CAAC,YAAY,EAAE,CAAC;aACrB;QACH,CAAC,CAAC,CAAC;QAEH,oBAAoB,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE;YACvD,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;YAChD,MAAM,4BAA4B,GAChC,IAAA,gDAAmC,EAAC,OAAO,CAAC,CAAC;YAC/C,MAAM,gBAAgB,GAAG,cAAc,KAAK,OAAO,CAAC;YAEpD,IAAI,CAAC,SAAS,CAAC;gBACb,OAAO;gBACP,4BAA4B;aAC7B,CAAC,CAAC;YAEH,IAAI,4BAA4B,IAAI,gBAAgB,EAAE;gBACpD,IAAI,CAAC,YAAY,EAAE,CAAC;aACrB;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACG,KAAK;;YACT,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YACpC,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;KAAA;IAED;;OAEG;IACH,IAAI;QACF,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAEO,WAAW;QACjB,IAAI,IAAI,CAAC,UAAU,EAAE;YACnB,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;SAChC;IACH,CAAC;IAED;;;;OAIG;IACW,YAAY,CAAC,QAAiB;;YAC1C,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YACvD,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YAC1B,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,GAAS,EAAE;gBACvC,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YAC5B,CAAC,CAAA,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;KAAA;IAED;;OAEG;IACG,YAAY;;YAChB,MAAM,EACJ,QAAQ,EACR,4BAA4B,EAC5B,iCAAiC,GAClC,GAAG,IAAI,CAAC,MAAM,CAAC;YAChB,IACE,QAAQ;gBACR,CAAC,4BAA4B;gBAC7B,CAAC,iCAAiC,EAClC;gBACA,OAAO;aACR;YACD,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;YAEjD,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG;YAChC,yBAAyB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CACjE,CAAC;YACF,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC/C,MAAM,cAAc,GAAa,EAAE,CAAC;YACpC,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE;gBAC/B,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;oBACtC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;iBAC9B;aACF;YACD,MAAM,qBAAqB,GAAG,EAAE,CAAC;YACjC,qBAAqB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YACzD,qBAAqB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,KAAK,CAC7C,IAAI,EACJ,cAAc,CAAC,MAAM,GAAG,CAAC,CAC1B,CAAC;YAEF,0BAA0B;YAC1B,IAAI,CAAC,eAAe,EAAE;gBACpB,OAAO;aACR;YAED,KAAK,MAAM,WAAW,IAAI,qBAAqB,EAAE;gBAC/C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE;oBAC5B,MAAM;iBACP;gBAED,MAAM,IAAA,gCAAa,EAAC,GAAS,EAAE;oBAC7B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,uBAAuB,CACjD,eAAe,EACf,WAAW,CACZ,CAAC;oBACF,MAAM,WAAW,GAAY,EAAE,CAAC;oBAChC,KAAK,MAAM,YAAY,IAAI,QAAQ,EAAE;wBACnC,IAAI,OAAO,CAAC;wBACZ,0BAA0B;wBAC1B,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;wBAChD,IAAI,aAAa,CAAC,MAAM,EAAE;4BACxB,OAAO,GAAG,aAAa,CAAC,IAAI,CAC1B,CAAC,mBAAmB,EAAE,EAAE,CACtB,mBAAmB,KAAK,IAAA,uCAAoB,EAAC,YAAY,CAAC,CAC7D,CAAC;yBACH;wBACD,MAAM,uBAAuB,GAC3B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CACzB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,YAAY,CAAC,WAAW,EAAE,CACtD,IAAI,EAAE,CAAC;wBAEV,IAAI,OAAO,KAAK,SAAS,EAAE;4BACzB,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,GACpD,SAAS,CAAC,uBAAuB,CAAC,CAAC;4BACrC,WAAW,CAAC,IAAI,CAAC;gCACf,OAAO,EAAE,YAAY;gCACrB,QAAQ;gCACR,MAAM;gCACN,WAAW;gCACX,KAAK,EAAE,OAAO;gCACd,QAAQ,EAAE,KAAK;gCACf,IAAI;6BACL,CAAC,CAAC;yBACJ;qBACF;oBAED,IAAI,WAAW,CAAC,MAAM,EAAE;wBACtB,MAAM,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE;4BACxC,eAAe;4BACf,OAAO;yBACR,CAAC,CAAC;qBACJ;gBACH,CAAC,CAAA,CAAC,CAAC;aACJ;QACH,CAAC;KAAA;CACF;AAzQD,4DAyQC;AAED,kBAAe,wBAAwB,CAAC","sourcesContent":["import type { BaseConfig, BaseState } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport {\n safelyExecute,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport type { NetworkState } from '@metamask/network-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport type { AssetsContractController } from './AssetsContractController';\nimport { isTokenDetectionSupportedForNetwork } from './assetsUtil';\nimport type { TokenListState } from './TokenListController';\nimport type { Token } from './TokenRatesController';\nimport type { TokensController, TokensState } from './TokensController';\n\nconst DEFAULT_INTERVAL = 180000;\n\n/**\n * @type TokenDetectionConfig\n *\n * TokenDetection configuration\n * @property interval - Polling interval used to fetch new token rates\n * @property selectedAddress - Vault selected address\n * @property chainId - The chain ID of the current network\n * @property isDetectionEnabledFromPreferences - Boolean to track if detection is enabled from PreferencesController\n * @property isDetectionEnabledForNetwork - Boolean to track if detected is enabled for current network\n */\nexport interface TokenDetectionConfig extends BaseConfig {\n interval: number;\n selectedAddress: string;\n chainId: Hex;\n isDetectionEnabledFromPreferences: boolean;\n isDetectionEnabledForNetwork: boolean;\n}\n\n/**\n * Controller that passively polls on a set interval for Tokens auto detection\n */\nexport class TokenDetectionController extends BaseController<\n TokenDetectionConfig,\n BaseState\n> {\n private intervalId?: ReturnType<typeof setTimeout>;\n\n /**\n * Name of this controller used during composition\n */\n override name = 'TokenDetectionController';\n\n private readonly getBalancesInSingleCall: AssetsContractController['getBalancesInSingleCall'];\n\n private readonly addDetectedTokens: TokensController['addDetectedTokens'];\n\n private readonly getTokensState: () => TokensState;\n\n private readonly getTokenListState: () => TokenListState;\n\n /**\n * Creates a TokenDetectionController instance.\n *\n * @param options - The controller options.\n * @param options.onPreferencesStateChange - Allows subscribing to preferences controller state changes.\n * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.\n * @param options.onTokenListStateChange - Allows subscribing to token list controller state changes.\n * @param options.getBalancesInSingleCall - Gets the balances of a list of tokens for the given address.\n * @param options.addDetectedTokens - Add a list of detected tokens.\n * @param options.getTokenListState - Gets the current state of the TokenList controller.\n * @param options.getTokensState - Gets the current state of the Tokens controller.\n * @param options.getNetworkState - Gets the state of the network controller.\n * @param options.getPreferencesState - Gets the state of the preferences controller.\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 onTokenListStateChange,\n getBalancesInSingleCall,\n addDetectedTokens,\n getTokenListState,\n getTokensState,\n getNetworkState,\n getPreferencesState,\n }: {\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n onTokenListStateChange: (\n listener: (tokenListState: TokenListState) => void,\n ) => void;\n getBalancesInSingleCall: AssetsContractController['getBalancesInSingleCall'];\n addDetectedTokens: TokensController['addDetectedTokens'];\n getTokenListState: () => TokenListState;\n getTokensState: () => TokensState;\n getNetworkState: () => NetworkState;\n getPreferencesState: () => PreferencesState;\n },\n config?: Partial<TokenDetectionConfig>,\n state?: Partial<BaseState>,\n ) {\n const {\n providerConfig: { chainId: defaultChainId },\n } = getNetworkState();\n const { useTokenDetection: defaultUseTokenDetection } =\n getPreferencesState();\n\n super(config, state);\n this.defaultConfig = {\n interval: DEFAULT_INTERVAL,\n selectedAddress: '',\n disabled: true,\n chainId: defaultChainId,\n isDetectionEnabledFromPreferences: defaultUseTokenDetection,\n isDetectionEnabledForNetwork:\n isTokenDetectionSupportedForNetwork(defaultChainId),\n ...config,\n };\n\n this.initialize();\n this.getTokensState = getTokensState;\n this.getTokenListState = getTokenListState;\n this.addDetectedTokens = addDetectedTokens;\n this.getBalancesInSingleCall = getBalancesInSingleCall;\n\n onTokenListStateChange(({ tokenList }) => {\n const hasTokens = Object.keys(tokenList).length;\n\n if (hasTokens) {\n this.detectTokens();\n }\n });\n\n onPreferencesStateChange(({ selectedAddress, useTokenDetection }) => {\n const {\n selectedAddress: currentSelectedAddress,\n isDetectionEnabledFromPreferences,\n } = this.config;\n const isSelectedAddressChanged =\n selectedAddress !== currentSelectedAddress;\n const isDetectionChangedFromPreferences =\n isDetectionEnabledFromPreferences !== useTokenDetection;\n\n this.configure({\n isDetectionEnabledFromPreferences: useTokenDetection,\n selectedAddress,\n });\n\n if (\n useTokenDetection &&\n (isSelectedAddressChanged || isDetectionChangedFromPreferences)\n ) {\n this.detectTokens();\n }\n });\n\n onNetworkStateChange(({ providerConfig: { chainId } }) => {\n const { chainId: currentChainId } = this.config;\n const isDetectionEnabledForNetwork =\n isTokenDetectionSupportedForNetwork(chainId);\n const isChainIdChanged = currentChainId !== chainId;\n\n this.configure({\n chainId,\n isDetectionEnabledForNetwork,\n });\n\n if (isDetectionEnabledForNetwork && isChainIdChanged) {\n this.detectTokens();\n }\n });\n }\n\n /**\n * Start polling for detected tokens.\n */\n async start() {\n this.configure({ disabled: false });\n await this.startPolling();\n }\n\n /**\n * Stop polling for detected tokens.\n */\n stop() {\n this.configure({ disabled: true });\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 * @param interval - An interval on which to poll.\n */\n private async startPolling(interval?: number): Promise<void> {\n interval && this.configure({ interval }, false, false);\n this.stopPolling();\n await this.detectTokens();\n this.intervalId = setInterval(async () => {\n await this.detectTokens();\n }, this.config.interval);\n }\n\n /**\n * Triggers asset ERC20 token auto detection for each contract address in contract metadata on mainnet.\n */\n async detectTokens() {\n const {\n disabled,\n isDetectionEnabledForNetwork,\n isDetectionEnabledFromPreferences,\n } = this.config;\n if (\n disabled ||\n !isDetectionEnabledForNetwork ||\n !isDetectionEnabledFromPreferences\n ) {\n return;\n }\n const { tokens } = this.getTokensState();\n const { selectedAddress, chainId } = this.config;\n\n const tokensAddresses = tokens.map(\n /* istanbul ignore next*/ (token) => token.address.toLowerCase(),\n );\n const { tokenList } = this.getTokenListState();\n const tokensToDetect: string[] = [];\n for (const address in tokenList) {\n if (!tokensAddresses.includes(address)) {\n tokensToDetect.push(address);\n }\n }\n const sliceOfTokensToDetect = [];\n sliceOfTokensToDetect[0] = tokensToDetect.slice(0, 1000);\n sliceOfTokensToDetect[1] = tokensToDetect.slice(\n 1000,\n tokensToDetect.length - 1,\n );\n\n /* istanbul ignore else */\n if (!selectedAddress) {\n return;\n }\n\n for (const tokensSlice of sliceOfTokensToDetect) {\n if (tokensSlice.length === 0) {\n break;\n }\n\n await safelyExecute(async () => {\n const balances = await this.getBalancesInSingleCall(\n selectedAddress,\n tokensSlice,\n );\n const tokensToAdd: Token[] = [];\n for (const tokenAddress in balances) {\n let ignored;\n /* istanbul ignore else */\n const { ignoredTokens } = this.getTokensState();\n if (ignoredTokens.length) {\n ignored = ignoredTokens.find(\n (ignoredTokenAddress) =>\n ignoredTokenAddress === toChecksumHexAddress(tokenAddress),\n );\n }\n const caseInsensitiveTokenKey =\n Object.keys(tokenList).find(\n (i) => i.toLowerCase() === tokenAddress.toLowerCase(),\n ) || '';\n\n if (ignored === undefined) {\n const { decimals, symbol, aggregators, iconUrl, name } =\n tokenList[caseInsensitiveTokenKey];\n tokensToAdd.push({\n address: tokenAddress,\n decimals,\n symbol,\n aggregators,\n image: iconUrl,\n isERC721: false,\n name,\n });\n }\n }\n\n if (tokensToAdd.length) {\n await this.addDetectedTokens(tokensToAdd, {\n selectedAddress,\n chainId,\n });\n }\n });\n }\n }\n}\n\nexport default TokenDetectionController;\n"]}
|
|
1
|
+
{"version":3,"file":"TokenDetectionController.js","sourceRoot":"","sources":["../src/TokenDetectionController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BaseConfig, BaseState } from '@metamask/base-controller';\nimport {\n safelyExecute,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport type {\n NetworkClientId,\n NetworkController,\n NetworkState,\n} from '@metamask/network-controller';\nimport { PollingControllerV1 } from '@metamask/polling-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport type { AssetsContractController } from './AssetsContractController';\nimport { isTokenDetectionSupportedForNetwork } from './assetsUtil';\nimport type { TokenListState } from './TokenListController';\nimport type { Token } from './TokenRatesController';\nimport type { TokensController, TokensState } from './TokensController';\n\nconst DEFAULT_INTERVAL = 180000;\n\n/**\n * @type TokenDetectionConfig\n *\n * TokenDetection configuration\n * @property interval - Polling interval used to fetch new token rates\n * @property selectedAddress - Vault selected address\n * @property chainId - The chain ID of the current network\n * @property isDetectionEnabledFromPreferences - Boolean to track if detection is enabled from PreferencesController\n * @property isDetectionEnabledForNetwork - Boolean to track if detected is enabled for current network\n */\nexport interface TokenDetectionConfig extends BaseConfig {\n interval: number;\n selectedAddress: string;\n chainId: Hex;\n isDetectionEnabledFromPreferences: boolean;\n isDetectionEnabledForNetwork: boolean;\n}\n\n/**\n * Controller that passively polls on a set interval for Tokens auto detection\n */\nexport class TokenDetectionController extends PollingControllerV1<\n TokenDetectionConfig,\n BaseState\n> {\n private intervalId?: ReturnType<typeof setTimeout>;\n\n /**\n * Name of this controller used during composition\n */\n override name = 'TokenDetectionController';\n\n private readonly getBalancesInSingleCall: AssetsContractController['getBalancesInSingleCall'];\n\n private readonly addDetectedTokens: TokensController['addDetectedTokens'];\n\n private readonly getTokensState: () => TokensState;\n\n private readonly getTokenListState: () => TokenListState;\n\n private readonly getNetworkClientById: NetworkController['getNetworkClientById'];\n\n /**\n * Creates a TokenDetectionController instance.\n *\n * @param options - The controller options.\n * @param options.onPreferencesStateChange - Allows subscribing to preferences controller state changes.\n * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.\n * @param options.onTokenListStateChange - Allows subscribing to token list controller state changes.\n * @param options.getBalancesInSingleCall - Gets the balances of a list of tokens for the given address.\n * @param options.addDetectedTokens - Add a list of detected tokens.\n * @param options.getTokenListState - Gets the current state of the TokenList controller.\n * @param options.getTokensState - Gets the current state of the Tokens controller.\n * @param options.getNetworkState - Gets the state of the network controller.\n * @param options.getPreferencesState - Gets the state of the preferences controller.\n * @param options.getNetworkClientById - Gets the network client by ID.\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 onTokenListStateChange,\n getBalancesInSingleCall,\n addDetectedTokens,\n getTokenListState,\n getTokensState,\n getNetworkState,\n getPreferencesState,\n getNetworkClientById,\n }: {\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n onTokenListStateChange: (\n listener: (tokenListState: TokenListState) => void,\n ) => void;\n getBalancesInSingleCall: AssetsContractController['getBalancesInSingleCall'];\n addDetectedTokens: TokensController['addDetectedTokens'];\n getTokenListState: () => TokenListState;\n getTokensState: () => TokensState;\n getNetworkState: () => NetworkState;\n getPreferencesState: () => PreferencesState;\n getNetworkClientById: NetworkController['getNetworkClientById'];\n },\n config?: Partial<TokenDetectionConfig>,\n state?: Partial<BaseState>,\n ) {\n const {\n providerConfig: { chainId: defaultChainId },\n } = getNetworkState();\n const { useTokenDetection: defaultUseTokenDetection } =\n getPreferencesState();\n\n super(config, state);\n this.defaultConfig = {\n interval: DEFAULT_INTERVAL,\n selectedAddress: '',\n disabled: true,\n chainId: defaultChainId,\n isDetectionEnabledFromPreferences: defaultUseTokenDetection,\n isDetectionEnabledForNetwork:\n isTokenDetectionSupportedForNetwork(defaultChainId),\n ...config,\n };\n\n this.initialize();\n this.getTokensState = getTokensState;\n this.getTokenListState = getTokenListState;\n this.addDetectedTokens = addDetectedTokens;\n this.getBalancesInSingleCall = getBalancesInSingleCall;\n this.getNetworkClientById = getNetworkClientById;\n\n onTokenListStateChange(({ tokenList }) => {\n const hasTokens = Object.keys(tokenList).length;\n\n if (hasTokens) {\n this.detectTokens();\n }\n });\n\n onPreferencesStateChange(({ selectedAddress, useTokenDetection }) => {\n const {\n selectedAddress: currentSelectedAddress,\n isDetectionEnabledFromPreferences,\n } = this.config;\n const isSelectedAddressChanged =\n selectedAddress !== currentSelectedAddress;\n const isDetectionChangedFromPreferences =\n isDetectionEnabledFromPreferences !== useTokenDetection;\n\n this.configure({\n isDetectionEnabledFromPreferences: useTokenDetection,\n selectedAddress,\n });\n\n if (\n useTokenDetection &&\n (isSelectedAddressChanged || isDetectionChangedFromPreferences)\n ) {\n this.detectTokens();\n }\n });\n\n onNetworkStateChange(({ providerConfig: { chainId } }) => {\n const { chainId: currentChainId } = this.config;\n const isDetectionEnabledForNetwork =\n isTokenDetectionSupportedForNetwork(chainId);\n const isChainIdChanged = currentChainId !== chainId;\n\n this.configure({\n chainId,\n isDetectionEnabledForNetwork,\n });\n\n if (isDetectionEnabledForNetwork && isChainIdChanged) {\n this.detectTokens();\n }\n });\n }\n\n /**\n * Start polling for detected tokens.\n */\n async start() {\n this.configure({ disabled: false });\n await this.startPolling();\n }\n\n /**\n * Stop polling for detected tokens.\n */\n stop() {\n this.configure({ disabled: true });\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 * @param interval - An interval on which to poll.\n */\n private async startPolling(interval?: number): Promise<void> {\n interval && this.configure({ interval }, false, false);\n this.stopPolling();\n await this.detectTokens();\n this.intervalId = setInterval(async () => {\n await this.detectTokens();\n }, this.config.interval);\n }\n\n private getCorrectChainId(networkClientId?: NetworkClientId) {\n if (networkClientId) {\n return this.getNetworkClientById(networkClientId).configuration.chainId;\n }\n return this.config.chainId;\n }\n\n _executePoll(\n networkClientId: string,\n options: { address: string },\n ): Promise<void> {\n return this.detectTokens({\n networkClientId,\n accountAddress: options.address,\n });\n }\n\n /**\n * Triggers asset ERC20 token auto detection for each contract address in contract metadata on mainnet.\n *\n * @param options - Options to detect tokens.\n * @param options.networkClientId - The ID of the network client to use.\n * @param options.accountAddress - The account address to use.\n */\n async detectTokens(options?: {\n networkClientId?: NetworkClientId;\n accountAddress?: string;\n }) {\n const { networkClientId, accountAddress } = options || {};\n const {\n disabled,\n isDetectionEnabledForNetwork,\n isDetectionEnabledFromPreferences,\n } = this.config;\n if (\n disabled ||\n !isDetectionEnabledForNetwork ||\n !isDetectionEnabledFromPreferences\n ) {\n return;\n }\n const { tokens } = this.getTokensState();\n const selectedAddress = accountAddress || this.config.selectedAddress;\n const chainId = this.getCorrectChainId(networkClientId);\n\n const tokensAddresses = tokens.map(\n /* istanbul ignore next*/ (token) => token.address.toLowerCase(),\n );\n const { tokenList } = this.getTokenListState();\n const tokensToDetect: string[] = [];\n for (const address of Object.keys(tokenList)) {\n if (!tokensAddresses.includes(address)) {\n tokensToDetect.push(address);\n }\n }\n const sliceOfTokensToDetect = [];\n sliceOfTokensToDetect[0] = tokensToDetect.slice(0, 1000);\n sliceOfTokensToDetect[1] = tokensToDetect.slice(\n 1000,\n tokensToDetect.length - 1,\n );\n\n /* istanbul ignore else */\n if (!selectedAddress) {\n return;\n }\n\n for (const tokensSlice of sliceOfTokensToDetect) {\n if (tokensSlice.length === 0) {\n break;\n }\n\n await safelyExecute(async () => {\n const balances = await this.getBalancesInSingleCall(\n selectedAddress,\n tokensSlice,\n );\n const tokensToAdd: Token[] = [];\n for (const tokenAddress of Object.keys(balances)) {\n let ignored;\n /* istanbul ignore else */\n const { ignoredTokens } = this.getTokensState();\n if (ignoredTokens.length) {\n ignored = ignoredTokens.find(\n (ignoredTokenAddress) =>\n ignoredTokenAddress === toChecksumHexAddress(tokenAddress),\n );\n }\n const caseInsensitiveTokenKey =\n Object.keys(tokenList).find(\n (i) => i.toLowerCase() === tokenAddress.toLowerCase(),\n ) || '';\n\n if (ignored === undefined) {\n const { decimals, symbol, aggregators, iconUrl, name } =\n tokenList[caseInsensitiveTokenKey];\n tokensToAdd.push({\n address: tokenAddress,\n decimals,\n symbol,\n aggregators,\n image: iconUrl,\n isERC721: false,\n name,\n });\n }\n }\n\n if (tokensToAdd.length) {\n await this.addDetectedTokens(tokensToAdd, {\n selectedAddress,\n chainId,\n });\n }\n });\n }\n }\n}\n\nexport default TokenDetectionController;\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
|