diff --git a/src/app/common/hooks/account/use-account-names.ts b/src/app/common/hooks/account/use-account-names.ts index dbfe0849c73..fb23aad90d6 100644 --- a/src/app/common/hooks/account/use-account-names.ts +++ b/src/app/common/hooks/account/use-account-names.ts @@ -24,9 +24,11 @@ export function useCurrentAccountDisplayName() { } export function useAccountDisplayName({ address, index }: { index: number; address: string }) { - const { data: names = [] } = useGetAccountNamesByAddressQuery(address); + const { data: names = [], isLoading } = useGetAccountNamesByAddressQuery(address); return useMemo(() => { + // TO-DO - add proper UI loader + if (isLoading) return 'Loading bns name...'; if (names[0]) return parseIfValidPunycode(names[0]); return getAutogeneratedAccountDisplayName(index); - }, [names, index]); + }, [names, index, isLoading]); } diff --git a/src/app/features/collectibles/components/_collectible-types/collectible-image.tsx b/src/app/features/collectibles/components/_collectible-types/collectible-image.tsx index 0949c4b471e..02a88a5deaf 100644 --- a/src/app/features/collectibles/components/_collectible-types/collectible-image.tsx +++ b/src/app/features/collectibles/components/_collectible-types/collectible-image.tsx @@ -29,6 +29,7 @@ export function CollectibleImage(props: CollectibleImageProps) { {alt} setIsError(true)} + loading="lazy" onLoad={event => { const target = event.target as HTMLImageElement; setWidth(target.naturalWidth); @@ -40,7 +41,7 @@ export function CollectibleImage(props: CollectibleImageProps) { height: '100%', aspectRatio: '1 / 1', objectFit: 'cover', - display: !isApprovedByLimiter || isLoading ? 'none' : 'inherit', + opacity: !isApprovedByLimiter || isLoading ? '0' : '1', imageRendering: width <= 40 ? 'pixelated' : 'auto', }} /> diff --git a/src/app/query/bitcoin/ordinals/inscription-text-content.query.ts b/src/app/query/bitcoin/ordinals/inscription-text-content.query.ts index a233d28aa16..53be0829b16 100644 --- a/src/app/query/bitcoin/ordinals/inscription-text-content.query.ts +++ b/src/app/query/bitcoin/ordinals/inscription-text-content.query.ts @@ -2,6 +2,7 @@ import { useQuery } from '@tanstack/react-query'; import axios from 'axios'; import { QueryPrefixes } from '@app/query/query-prefixes'; +import { useHiroApiRateLimiter } from '@app/query/stacks/rate-limiter'; async function getInscriptionTextContent(src: string) { const res = await axios.get(src, { responseType: 'text' }); @@ -9,9 +10,13 @@ async function getInscriptionTextContent(src: string) { } export function useInscriptionTextContentQuery(contentSrc: string) { + const limiter = useHiroApiRateLimiter(); return useQuery( [QueryPrefixes.OrdinalTextContent, contentSrc], - () => getInscriptionTextContent(contentSrc), + async () => { + await limiter.removeTokens(1); + return getInscriptionTextContent(contentSrc); + }, { cacheTime: Infinity, staleTime: Infinity, diff --git a/src/app/query/stacks/bns/bns.query.ts b/src/app/query/stacks/bns/bns.query.ts index 528879ead79..bbe882ea058 100644 --- a/src/app/query/stacks/bns/bns.query.ts +++ b/src/app/query/stacks/bns/bns.query.ts @@ -7,7 +7,7 @@ import { StacksClient } from '@app/query/stacks/stacks-client'; import { useStacksClient } from '@app/store/common/api-clients.hooks'; import { useCurrentNetworkState } from '@app/store/networks/networks.hooks'; -import { RateLimiter, useHiroApiRateLimiter } from '../rate-limiter'; +import { useHiroBnsNamesRateLimiter } from '../rate-limiter'; import { fetchNamesForAddress } from './bns.utils'; const staleTime = 15 * 60 * 1000; // 15 min @@ -25,18 +25,16 @@ type BnsNameFetcher = (address: string) => Promise interface GetBnsNameFetcherFactoryArgs { client: StacksClient; - limiter: RateLimiter; isTestnet: boolean; signal?: AbortSignal; } + function getBnsNameFetcherFactory({ client, - limiter, isTestnet, signal, }: GetBnsNameFetcherFactoryArgs): BnsNameFetcher { return async (address: string) => { - await limiter.removeTokens(1); return fetchNamesForAddress({ client, address, isTestnet, signal }); }; } @@ -48,13 +46,15 @@ export function useGetBnsNamesOwnedByAddress ) { const client = useStacksClient(); - const limiter = useHiroApiRateLimiter(); + const limiter = useHiroBnsNamesRateLimiter(); const { isTestnet } = useCurrentNetworkState(); return useQuery({ enabled: address !== '', queryKey: [QueryPrefixes.BnsNamesByAddress, address], - queryFn: ({ signal }) => - getBnsNameFetcherFactory({ client, limiter, isTestnet, signal })(address), + queryFn: async ({ signal }) => { + await limiter.removeTokens(1); + return getBnsNameFetcherFactory({ client, isTestnet, signal })(address); + }, ...bnsQueryOptions, ...options, }); diff --git a/src/app/query/stacks/rate-limiter.ts b/src/app/query/stacks/rate-limiter.ts index 511329c9efd..d2e9ccfb250 100644 --- a/src/app/query/stacks/rate-limiter.ts +++ b/src/app/query/stacks/rate-limiter.ts @@ -23,4 +23,23 @@ export function useHiroApiRateLimiter() { }); } +const hiroBnsNamesRateLimiter = new RateLimiter({ + tokensPerInterval: 5, + interval: 5000, +}); + +const hiroBnsNamesTestnetRateLimiter = new RateLimiter({ + tokensPerInterval: 10, + interval: 5000, +}); + +export function useHiroBnsNamesRateLimiter() { + const currentNetwork = useCurrentNetworkState(); + + return whenStacksChainId(currentNetwork.chain.stacks.chainId)({ + [ChainID.Mainnet]: hiroBnsNamesRateLimiter, + [ChainID.Testnet]: hiroBnsNamesTestnetRateLimiter, + }); +} + export type { RateLimiter };