Skip to content

Commit

Permalink
feat: link NFT to etherscan
Browse files Browse the repository at this point in the history
  • Loading branch information
tien committed Jan 18, 2024
1 parent b87016e commit edb876c
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 25 deletions.
9 changes: 6 additions & 3 deletions apps/web/src/domains/nfts/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,12 @@ const _nftsState = atomFamily<NftsProgress, string>({
throw new Error('No RPC available for fetching Bitcountry NFTs')
}

return worker(address, { batchSize, acalaRpc: acala.rpc, bitcountryRpc: bitcountry.rpc }).subscribe(
observer
)
return worker(address, {
batchSize,
acalaRpc: acala.rpc,
bitcountryRpc: bitcountry.rpc,
chaindataUrl: import.meta.env.REACT_APP_CHAINDATA,
}).subscribe(observer)
})
.pipe(
bufferTime(1000, null, batchSize),
Expand Down
7 changes: 5 additions & 2 deletions apps/web/src/domains/nfts/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ import {
import { Observable } from 'rxjs'
import { expose } from 'threads/worker'

const subscribeNfts = (address: string, options: { batchSize: number; acalaRpc: string; bitcountryRpc: string }) =>
const subscribeNfts = (
address: string,
options: { batchSize: number; acalaRpc: string; bitcountryRpc: string; chaindataUrl: string }
) =>
new Observable<Nft | { error: unknown }>(observer => {
const promises = (
address.startsWith('0x')
? [createOnfinalityNftGenerator]
? [createOnfinalityNftGenerator({ chaindataUrl: options.chaindataUrl })]
: [
createAcalaNftAsyncGenerator({ rpc: options.acalaRpc }),
createBitCountryNftAsyncGenerator({ rpc: options.bitcountryRpc }),
Expand Down
75 changes: 55 additions & 20 deletions packages/nft/src/generators/onfinality.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import request from 'graphql-request'
import { graphql } from '../../generated/gql/onfinality/index.js'
import type { CreateNftAsyncGenerator, Nft } from '../types.js'

export const createOnfinalityNftGenerator: CreateNftAsyncGenerator<Nft<'erc721' | 'erc1155', string>> =
export const createOnfinalityNftGenerator: (options?: {
chaindataUrl: string
}) => CreateNftAsyncGenerator<Nft<'erc721' | 'erc1155', string>> = options =>
async function* (address, { batchSize }) {
let after: string
while (true) {
Expand Down Expand Up @@ -45,31 +47,64 @@ export const createOnfinalityNftGenerator: CreateNftAsyncGenerator<Nft<'erc721'
}
)

yield* response.nfts?.edges
.map(x => x.node)
.filter((x): x is NonNullable<typeof x> => x !== null && x !== undefined)
.map(
nft =>
({
id: `${nft.collection?.contractType}-${nft.collection?.networkId}-${nft.collection?.contractAddress}-${nft.tokenId}`.toLowerCase(),
type: nft.collection?.contractType.toLowerCase() ?? '',
chain: nft.collection?.networkId ?? '',
const chainEtherscan = new Map<string, string | undefined>()
const getEtherscanUrl = async (chainId: string, contractAddress: string, tokenId: string) => {
chainEtherscan.set(
chainId,
chainEtherscan.get(chainId) ??
(await fetch(
new URL(
`./evmNetworks/byId/${chainId}.json`,
options?.chaindataUrl ?? 'https://raw.githubusercontent.com/TalismanSociety/chaindata/main/dist/'
)
)
.then(x => x.json())
.then(x => x.explorerUrl as string | undefined)
.catch())
)

if (!chainEtherscan.has(chainId)) {
return
}

return new URL(`./nft/${contractAddress}/${tokenId}`, chainEtherscan.get(chainId)).toString()
}

yield* await Promise.all(
response.nfts?.edges
.map(x => x.node)
.filter(
(
x
): x is Omit<NonNullable<typeof x>, 'collection'> & {
collection: NonNullable<NonNullable<typeof x>['collection']>
} => x !== null && x !== undefined && x.collection !== null && x.collection !== undefined
)
.map(async nft => {
const etherscanUrl = await getEtherscanUrl(
nft.collection.networkId,
nft.collection.contractAddress,
nft.tokenId
)
return {
id: `${nft.collection.contractType}-${nft.collection.networkId}-${nft.collection.contractAddress}-${nft.tokenId}`.toLowerCase(),
type: nft.collection.contractType.toLowerCase() ?? '',
chain: nft.collection.networkId ?? '',
name: nft.metadata?.name ?? undefined,
description: nft.metadata?.description ?? undefined,
media: nft.metadata?.imageUri ?? undefined,
thumbnail: nft.metadata?.imageUri ?? undefined,
serialNumber: Number(nft.tokenId),
properties: undefined,
externalLinks: undefined,
collection: !nft.collection
? undefined
: {
id: nft.collection.id,
name: nft.collection.name,
totalSupply: Number(nft.collection.totalSupply),
},
} as Nft<'erc721' | 'erc1155', string>)
) ?? []
externalLinks: etherscanUrl === undefined ? undefined : [{ name: 'Etherscan', url: etherscanUrl }],
collection: {
id: nft.collection.contractAddress,
name: nft.collection.name,
totalSupply: Number(nft.collection.totalSupply),
},
} as Nft<'erc721' | 'erc1155', string>
}) ?? []
)

if (!response.nfts?.pageInfo.hasNextPage) {
break
Expand Down

0 comments on commit edb876c

Please sign in to comment.