From f375463c1117176a4991bf07f12dd4afc2cc31e9 Mon Sep 17 00:00:00 2001 From: h0ngcha0 Date: Wed, 14 Aug 2024 22:28:58 +0200 Subject: [PATCH] Fix NFT display; reduce API calls --- packages/extension/src/background/index.ts | 5 ++- .../extension/src/background/networkStatus.ts | 2 +- .../accountNfts/alephium-nft.service.ts | 10 +++++- .../features/accountNfts/useNFTCollections.ts | 1 + .../ui/features/accountTokens/tokens.state.ts | 34 +++++++++++++------ 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts index 48567cd6..976b7f7c 100644 --- a/packages/extension/src/background/index.ts +++ b/packages/extension/src/background/index.ts @@ -1,4 +1,5 @@ import browser from "webextension-polyfill" +import { getAccountSelector, withoutHiddenSelector } from "../shared/account/selectors" import { accountStore, getAccounts } from "../shared/account/store" import { globalActionQueueStore } from "../shared/actionQueue/store" @@ -44,7 +45,9 @@ setTokenListUpdateAlarm() browser.alarms.onAlarm.addListener(async (alarm) => { if (alarm.name === transactionTrackerHistoryAlarm) { console.info("~> fetching transaction history") - await transactionTracker.loadHistory(await getAccounts()) + const selectedAccount = await walletStore.get("selected") + const accountSelector = selectedAccount ? getAccountSelector(selectedAccount) : withoutHiddenSelector + await transactionTracker.loadHistory(await getAccounts(accountSelector)) } if (alarm.name === transactionTrackerUpdateAlarm) { diff --git a/packages/extension/src/background/networkStatus.ts b/packages/extension/src/background/networkStatus.ts index dece1e85..e823dc41 100644 --- a/packages/extension/src/background/networkStatus.ts +++ b/packages/extension/src/background/networkStatus.ts @@ -13,7 +13,7 @@ const swrStorage = new KeyValueStorage>( // see: https://github.com/jperasmus/stale-while-revalidate-cache#configuration const swr = createStaleWhileRevalidateCache({ storage: swrStorage, // can be any object with getItem and setItem methods - minTimeToStale: 60e3, // 1 minute + minTimeToStale: 2 * 60e3, // 2 minutes maxTimeToLive: 30 * 60e3, // 30 minutes }) diff --git a/packages/extension/src/ui/features/accountNfts/alephium-nft.service.ts b/packages/extension/src/ui/features/accountNfts/alephium-nft.service.ts index a9cd3bc0..fe6c14b9 100644 --- a/packages/extension/src/ui/features/accountNfts/alephium-nft.service.ts +++ b/packages/extension/src/ui/features/accountNfts/alephium-nft.service.ts @@ -3,14 +3,22 @@ import { NFTCollection } from "./alephium-nft.model" import { Network } from "../../../shared/network" import { ExplorerProvider, NodeProvider } from "@alephium/web3" import { fetchImmutable } from "../../../shared/utils/fetchImmutable" +import { chunk } from 'lodash' export const fetchCollectionAndNfts = async ( nonFungibleTokenIds: string[], network: Network ): Promise => { + const maxSizeTokens = 80 const explorerProvider = new ExplorerProvider(network.explorerApiUrl) const parentAndTokenIds: CollectionAndNFTMap = {} - const nftMetadataz = await explorerProvider.tokens.postTokensNftMetadata(nonFungibleTokenIds) + + const nftMetadataz = (await Promise.all( + chunk(nonFungibleTokenIds, maxSizeTokens).map((nftIds) => + explorerProvider.tokens.postTokensNftMetadata(nftIds) + ) + )).flat() + for (const nftMetadata of nftMetadataz) { const tokenId = nftMetadata.id const collectionId = nftMetadata.collectionId diff --git a/packages/extension/src/ui/features/accountNfts/useNFTCollections.ts b/packages/extension/src/ui/features/accountNfts/useNFTCollections.ts index 1f309b6c..b6788f83 100644 --- a/packages/extension/src/ui/features/accountNfts/useNFTCollections.ts +++ b/packages/extension/src/ui/features/accountNfts/useNFTCollections.ts @@ -22,6 +22,7 @@ export const useCollectionAndNFTs = ( () => fetchCollectionAndNfts(nonFungibleTokenIds, network), { ...config, + dedupingInterval: 5000, refreshInterval: 30000, } ) diff --git a/packages/extension/src/ui/features/accountTokens/tokens.state.ts b/packages/extension/src/ui/features/accountTokens/tokens.state.ts index b14597fa..318b8361 100644 --- a/packages/extension/src/ui/features/accountTokens/tokens.state.ts +++ b/packages/extension/src/ui/features/accountTokens/tokens.state.ts @@ -1,4 +1,4 @@ -import { ALPH_TOKEN_ID, HexString, NodeProvider } from "@alephium/web3" +import { ALPH_TOKEN_ID, NodeProvider } from "@alephium/web3" import { BigNumber } from "ethers" import { memoize } from "lodash-es" import { useEffect, useMemo, useRef } from "react" @@ -268,6 +268,7 @@ export const useAllTokensWithBalance = ( }, { refreshInterval: 30000, + dedupingInterval: 5000, shouldRetryOnError: (error: any) => { const errorCode = error?.status || error?.errorCode const suppressError = @@ -337,17 +338,28 @@ async function fetchFungibleTokenFromFullNode(network: Network, tokenId: string) return undefined } - const metadata = await fetchImmutable(`${tokenId}-token-metadata`, () => nodeProvider.fetchFungibleTokenMetaData(tokenId)) - const token: Token = { - id: tokenId, - networkId: network.id, - name: Buffer.from(metadata.name, 'hex').toString('utf8'), - symbol: Buffer.from(metadata.symbol, 'hex').toString('utf8'), - decimals: metadata.decimals, - verified: false + const metadata = await fetchImmutable(`${tokenId}-token-metadata`, async () => { + try { + return (await nodeProvider.fetchFungibleTokenMetaData(tokenId)) + } catch (e: any) { + if (e.message.startsWith('Failed to call contract')) { + return { name: undefined, symbol: undefined, decimals: 0 } + } else { + throw e + } + } + }) + + if (metadata.name && metadata.symbol) { + return { + id: tokenId, + networkId: network.id, + name: Buffer.from(metadata.name, 'hex').toString('utf8'), + symbol: Buffer.from(metadata.symbol, 'hex').toString('utf8'), + decimals: metadata.decimals, + verified: false + } } - - return token } catch (e) { console.debug(`Failed to fetch token metadata for ${tokenId}`, e) return undefined