Skip to content

Commit

Permalink
feat: add limiter to collectibles
Browse files Browse the repository at this point in the history
  • Loading branch information
alter-eggo committed Mar 15, 2024
1 parent 6d18d64 commit d5e474c
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 11 deletions.
6 changes: 4 additions & 2 deletions src/app/common/hooks/account/use-account-names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export function CollectibleImage(props: CollectibleImageProps) {
<img
alt={alt}
onError={() => setIsError(true)}
loading="lazy"
onLoad={event => {
const target = event.target as HTMLImageElement;
setWidth(target.naturalWidth);
Expand All @@ -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',
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@ 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' });
return res.data;
}

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,
Expand Down
14 changes: 7 additions & 7 deletions src/app/query/stacks/bns/bns.query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -25,18 +25,16 @@ type BnsNameFetcher = (address: string) => Promise<BnsNamesOwnByAddressResponse>

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 });
};
}
Expand All @@ -48,13 +46,15 @@ export function useGetBnsNamesOwnedByAddress<T extends unknown = BnsNameFetcherR
options?: AppUseQueryConfig<BnsNameFetcherResp, T>
) {
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,
});
Expand Down
19 changes: 19 additions & 0 deletions src/app/query/stacks/rate-limiter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 };

0 comments on commit d5e474c

Please sign in to comment.