UNPKG

viem

Version:

TypeScript Interface for Ethereum

107 lines (97 loc) 3.07 kB
import type { Client } from '../../../clients/createClient.js' import type { Transport } from '../../../clients/transports/createTransport.js' import type { ErrorType } from '../../../errors/utils.js' import type { Chain } from '../../../types/chain.js' import type { AssetGatewayUrls } from '../../../types/ens.js' import { type GetJsonImageErrorType, type GetMetadataAvatarUriErrorType, type GetNftTokenUriErrorType, type ParseAvatarUriErrorType, type ParseNftUriErrorType, type ResolveAvatarUriErrorType, getJsonImage, getMetadataAvatarUri, getNftTokenUri, parseAvatarUri, parseNftUri, resolveAvatarUri, } from './utils.js' export type ParseAvatarRecordErrorType = | ParseNftAvatarUriErrorType | ParseAvatarUriErrorType | ErrorType /* * @description Parses an ENS avatar record. * * @example * parseAvatarRecord('eip155:1/erc1155:0xb32979486938aa9694bfc898f35dbed459f44424/10063') * 'https://ipfs.io/ipfs/QmSP4nq9fnN9dAiCj42ug9Wa79rqmQerZXZch82VqpiH7U/image.gif' * * @see https://docs.ens.domains/web/avatars * */ export async function parseAvatarRecord<chain extends Chain | undefined>( client: Client<Transport, chain>, { gatewayUrls, record, }: { gatewayUrls?: AssetGatewayUrls | undefined record: string }, ): Promise<string> { if (/eip155:/i.test(record)) return parseNftAvatarUri(client, { gatewayUrls, record }) return parseAvatarUri({ uri: record, gatewayUrls }) } type ParseNftAvatarUriErrorType = | ParseNftUriErrorType | GetNftTokenUriErrorType | ResolveAvatarUriErrorType | ParseAvatarUriErrorType | GetJsonImageErrorType | GetMetadataAvatarUriErrorType | ErrorType async function parseNftAvatarUri<chain extends Chain | undefined>( client: Client<Transport, chain>, { gatewayUrls, record, }: { gatewayUrls?: AssetGatewayUrls | undefined record: string }, ): Promise<string> { // parse NFT URI into properties const nft = parseNftUri(record) // fetch tokenURI from the NFT contract const nftUri = await getNftTokenUri(client, { nft }) // resolve the URI from the fetched tokenURI const { uri: resolvedNftUri, isOnChain, isEncoded, } = resolveAvatarUri({ uri: nftUri, gatewayUrls }) // if the resolved URI is on chain, return the data if ( isOnChain && (resolvedNftUri.includes('data:application/json;base64,') || resolvedNftUri.startsWith('{')) ) { const encodedJson = isEncoded ? // if it is encoded, decode it atob(resolvedNftUri.replace('data:application/json;base64,', '')) : // if it isn't encoded assume it is a JSON string, but it could be anything (it will error if it is) resolvedNftUri const decoded = JSON.parse(encodedJson) return parseAvatarUri({ uri: getJsonImage(decoded), gatewayUrls }) } let uriTokenId = nft.tokenID if (nft.namespace === 'erc1155') uriTokenId = uriTokenId.replace('0x', '').padStart(64, '0') return getMetadataAvatarUri({ gatewayUrls, uri: resolvedNftUri.replace(/(?:0x)?{id}/, uriTokenId), }) }