Skip to content

Commit

Permalink
move nft fetching logic to graphql worker (#5421)
Browse files Browse the repository at this point in the history
* nfts query

* tf ready

* rm migration + change react query persister version

* reset arc endpoints

* nit
  • Loading branch information
benisgold committed Feb 23, 2024
1 parent 4021fd6 commit fff25a6
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 109 deletions.
184 changes: 184 additions & 0 deletions src/graphql/queries/arc.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -289,3 +289,187 @@ query getPointsTweetIntent($id: String!) {
url
}
}

fragment simpleHashPaymentToken on SimpleHashPaymentToken {
payment_token_id
name
symbol
address
decimals
}

query getNFTs($walletAddress: String!) {
nfts(walletAddress: $walletAddress) {
nft_id
chain
contract_address
token_id
name
description
previews {
image_small_url
image_medium_url
image_large_url
image_opengraph_url
blurhash
predominant_color
}
image_url
image_properties {
width
height
size
mime_type
}
video_url
video_properties {
width
height
duration
video_coding
audio_coding
size
mime_type
}
audio_url
audio_properties {
duration
audio_coding
size
mime_type
}
model_url
model_properties {
size
mime_type
}
background_color
external_url
created_date
status
token_count
owner_count
owners {
owner_address
quantity
first_acquired_date
last_acquired_date
}
last_sale {
from_address
to_address
quantity
quantity_string
timestamp
transaction
marketplace_id
marketplace_name
is_bundle_sale
payment_token {
...simpleHashPaymentToken
}
unit_price
total_price
unit_price_usd_cents
}
first_created {
minted_to
quantity
quantity_string
timestamp
block_number
transaction
transaction_initiator
}
contract {
type
name
symbol
deployed_by
deployed_via_contract
owned_by
has_multiple_collections
}
collection {
collection_id
name
description
image_url
banner_image_url
category
is_nsfw
external_url
twitter_username
discord_url
instagram_url
medium_username
telegram_url
marketplace_pages {
marketplace_id
marketplace_name
marketplace_collection_id
nft_url
collection_url
verified
}
metaplex_mint
metaplex_candy_machine
metaplex_first_verified_creator
spam_score
floor_prices {
marketplace_id
value
payment_token {
...simpleHashPaymentToken
}
value_usd_cents
}
top_bids {
marketplace_id
value
payment_token {
...simpleHashPaymentToken
}
value_usd_cents
}
distinct_owner_count
distinct_nft_count
total_quantity
chains
top_contracts
collection_royalties {
source
total_creator_fee_basis_points
recipients {
address
percentage
basis_points
}
}
}
rarity {
rank
score
unique_attributes
}
royalty {
source
total_creator_fee_basis_points
recipients {
address
percentage
basis_points
}
}
extra_metadata {
image_original_url
animation_original_url
metadata_original_url
attributes {
trait_type
value
display_type
}
}
}
}
64 changes: 16 additions & 48 deletions src/resources/nfts/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
import { createQueryKey, queryClient } from '@/react-query';
import { NFT, PolygonAllowlist } from '@/resources/nfts/types';
import { fetchSimpleHashNFTListing, fetchSimpleHashNFTs } from '@/resources/nfts/simplehash';
import { useEffect, useMemo } from 'react';
import { filterSimpleHashNFTs, simpleHashNFTToUniqueAsset } from '@/resources/nfts/simplehash/utils';
import { rainbowFetch } from '@/rainbow-fetch';
import { useQuery } from '@tanstack/react-query';
import { createQueryKey } from '@/react-query';
import { NFT } from '@/resources/nfts/types';
import { fetchSimpleHashNFTListing } from '@/resources/nfts/simplehash';
import { useMemo } from 'react';
import { simpleHashNFTToUniqueAsset } from '@/resources/nfts/simplehash/utils';
import { useSelector } from 'react-redux';
import { AppState } from '@/redux/store';
import { Network } from '@/helpers';
import { UniqueAsset } from '@/entities';
import { arcClient } from '@/graphql';

const NFTS_LIMIT = 2000;
const NFTS_STALE_TIME = 300000; // 5 minutes
const NFTS_CACHE_TIME_EXTERNAL = 3600000; // 1 hour
const NFTS_CACHE_TIME_INTERNAL = 604800000; // 1 week
const POLYGON_ALLOWLIST_STALE_TIME = 600000; // 10 minutes

export const nftsQueryKey = ({ address }: { address: string }) => createQueryKey('nfts', { address }, { persisterVersion: 1 });
export const nftsQueryKey = ({ address }: { address: string }) => createQueryKey('nfts', { address }, { persisterVersion: 2 });

export const nftListingQueryKey = ({
contractAddress,
Expand All @@ -28,25 +26,6 @@ export const nftListingQueryKey = ({
network: Omit<Network, Network.goerli>;
}) => createQueryKey('nftListing', { contractAddress, tokenId, network });

function fetchPolygonAllowlist() {
return queryClient.fetchQuery<PolygonAllowlist>(
['polygon-allowlist'],
async () => {
const polygonAllowlistAddresses = (
await rainbowFetch('https://metadata.p.rainbow.me/token-list/137-allowlist.json', { method: 'get' })
).data.data.addresses;

const polygonAllowlist: PolygonAllowlist = {};
polygonAllowlistAddresses.forEach((address: string) => {
polygonAllowlist[address] = true;
});

return polygonAllowlist;
},
{ staleTime: POLYGON_ALLOWLIST_STALE_TIME }
);
}

export function useNFTs(): NFT[] {
// normal react query where we get new NFT formatted data
return [];
Expand All @@ -61,25 +40,20 @@ export function useLegacyNFTs({ address }: { address: string }) {
);
const isImportedWallet = walletAddresses.includes(address);

const { data, error, fetchNextPage, hasNextPage, isFetchingNextPage, isFetching } = useInfiniteQuery({
const { data, error, isFetching } = useQuery({
queryKey: nftsQueryKey({ address }),
queryFn: async ({ pageParam }) => {
const [simplehashResponse, polygonAllowlist] = await Promise.all([fetchSimpleHashNFTs(address, pageParam), fetchPolygonAllowlist()]);
const { data, nextCursor } = simplehashResponse;
const newNFTs = filterSimpleHashNFTs(data, polygonAllowlist).map(nft => simpleHashNFTToUniqueAsset(nft, address));
return {
data: newNFTs,
nextCursor,
};
queryFn: async () => {
const queryResponse = await arcClient.getNFTs({ walletAddress: address });
const nfts = queryResponse?.nfts?.map(nft => simpleHashNFTToUniqueAsset(nft, address));
return nfts;
},
getNextPageParam: lastPage => lastPage.nextCursor,
keepPreviousData: true,
staleTime: NFTS_STALE_TIME,
retry: 3,
cacheTime: isImportedWallet ? NFTS_CACHE_TIME_INTERNAL : NFTS_CACHE_TIME_EXTERNAL,
enabled: !!address,
});

const nfts = useMemo(() => (data?.pages ? data.pages.flatMap(page => page.data) : []), [data?.pages]);
const nfts = useMemo(() => data ?? [], [data]);

const nftsMap = useMemo(
() =>
Expand All @@ -95,16 +69,10 @@ export function useLegacyNFTs({ address }: { address: string }) {
[nfts]
);

useEffect(() => {
if (hasNextPage && !isFetchingNextPage && nfts.length < NFTS_LIMIT) {
fetchNextPage();
}
}, [hasNextPage, fetchNextPage, isFetchingNextPage, nfts.length]);

return {
data: { nfts, nftsMap },
error,
isInitialLoading: !nfts.length && isFetching,
isInitialLoading: !data?.length && isFetching,
};
}

Expand Down
Loading

0 comments on commit fff25a6

Please sign in to comment.