UNPKG

@yoroi/resolver

Version:
153 lines (131 loc) 3.75 kB
import {Api, Resolver} from '@yoroi/types' import {fetchData, FetchData, getApiError, isLeft} from '@yoroi/common' import {z} from 'zod' import {AxiosRequestConfig} from 'axios' const initialDeps = {request: fetchData} as const export const unstoppableApiGetCryptoAddress = ( {apiKey}: {apiKey: string}, {request}: {request: FetchData} = initialDeps, ) => { return async ( resolve: Resolver.Receiver['resolve'], fetcherConfig?: AxiosRequestConfig, ): Promise<string> => { if (!resolve.includes('.')) throw new Resolver.Errors.InvalidDomain() if (!isUnstoppableDomain(resolve)) throw new Resolver.Errors.UnsupportedTld() const config = { url: `${unstoppableApiConfig.mainnet.getCryptoAddress}${resolve}`, headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}`, }, } as const try { const response = await request<UnstoppableApiGetCryptoAddressResponse>( config, fetcherConfig, ) if (isLeft(response)) { const error = response.error as UnstoppableApiGetCryptoAddressError if (error.responseData?.message?.includes('Unsupported TLD')) throw new Resolver.Errors.UnsupportedTld() throw getApiError(error) } else { // parsing const safeParsedAdaResponse = UnstoppableApiAdaResponseSchema.safeParse( response.value.data, ) const safeParsedGeneralResponse = UnstoppableApiGeneralResponseSchema.safeParse(response.value.data) // checking const hasCardanoAddress = safeParsedAdaResponse.success const hasOtherBlockchainAddress = safeParsedGeneralResponse.success if (hasCardanoAddress) return response.value.data.records['crypto.ADA.address'] if (hasOtherBlockchainAddress) throw new Resolver.Errors.WrongBlockchain() throw new Resolver.Errors.InvalidResponse() } } catch (error: unknown) { throw getUnstoppableApiError(error) } } } // https://docs.unstoppabledomains.com/openapi/resolution/#operation/DomainsController.getDomain export type UnstoppableApiGetCryptoAddressResponse = { meta: { domain: string tokenId: string namehash: string blockchain: string networkId: number owner: string resolver: string registry: string reverse: boolean type: string } records: { 'crypto.ADA.address': string } } export type UnstoppableApiGetCryptoAddressError = { responseData: { message: string } status: number message: string } const UnstoppableApiAdaResponseSchema = z.object({ records: z.object({ 'crypto.ADA.address': z.string(), }), }) const UnstoppableApiGeneralResponseSchema = z.object({ meta: z.object({ blockchain: z.string(), }), records: z.record(z.string(), z.string()), }) // curl https://api.unstoppabledomains.com/resolve/supported_tlds export const unstoppableSupportedTlds = [ '.x', '.polygon', '.nft', '.crypto', '.blockchain', '.bitcoin', '.dao', '.888', '.wallet', '.binanceus', '.hi', '.klever', '.kresus', '.anime', '.manga', '.go', '.altimist', '.pudgy', '.unstoppable', '.austin', '.bitget', '.pog', '.clay', '.zil', '.eth', ] as const export const isUnstoppableDomain = (value: string) => { return unstoppableSupportedTlds.some((tld) => value.endsWith(tld)) } export const unstoppableApiConfig = { mainnet: { getCryptoAddress: 'https://api.unstoppabledomains.com/resolve/domains/', }, } as const export const getUnstoppableApiError = (error: unknown) => { if (error instanceof Api.Errors.NotFound) return new Resolver.Errors.NotFound() return error }