70 lines
2.4 KiB
TypeScript
70 lines
2.4 KiB
TypeScript
import { TokenList } from '@uniswap/token-lists'
|
|
import schema from '@uniswap/token-lists/src/tokenlist.schema.json'
|
|
import Ajv from 'ajv'
|
|
import contenthashToUri from './contenthashToUri'
|
|
import { parseENSAddress } from './parseENSAddress'
|
|
import uriToHttp from './uriToHttp'
|
|
|
|
const tokenListValidator = new Ajv({ allErrors: true }).compile(schema)
|
|
|
|
/**
|
|
* Contains the logic for resolving a list URL to a validated token list
|
|
* @param listUrl list url
|
|
* @param resolveENSContentHash resolves an ens name to a contenthash
|
|
*/
|
|
export default async function getTokenList(
|
|
listUrl: string,
|
|
resolveENSContentHash: (ensName: string) => Promise<string>
|
|
): Promise<TokenList> {
|
|
const parsedENS = parseENSAddress(listUrl)
|
|
let urls: string[]
|
|
if (parsedENS) {
|
|
let contentHashUri
|
|
try {
|
|
contentHashUri = await resolveENSContentHash(parsedENS.ensName)
|
|
} catch (error) {
|
|
console.debug(`Failed to resolve ENS name: ${parsedENS.ensName}`, error)
|
|
throw new Error(`Failed to resolve ENS name: ${parsedENS.ensName}`)
|
|
}
|
|
let translatedUri
|
|
try {
|
|
translatedUri = contenthashToUri(contentHashUri)
|
|
} catch (error) {
|
|
console.debug('Failed to translate contenthash to URI', contentHashUri)
|
|
throw new Error(`Failed to translate contenthash to URI: ${contentHashUri}`)
|
|
}
|
|
urls = uriToHttp(`${translatedUri}${parsedENS.ensPath ?? ''}`)
|
|
} else {
|
|
urls = uriToHttp(listUrl)
|
|
}
|
|
for (let i = 0; i < urls.length; i++) {
|
|
const url = urls[i]
|
|
const isLast = i === urls.length - 1
|
|
let response
|
|
try {
|
|
response = await fetch(url, { credentials: 'omit' })
|
|
} catch (error) {
|
|
console.debug('Failed to fetch list', listUrl, error)
|
|
if (isLast) throw new Error(`Failed to download list ${listUrl}`)
|
|
continue
|
|
}
|
|
|
|
if (!response.ok) {
|
|
if (isLast) throw new Error(`Failed to download list ${listUrl}`)
|
|
continue
|
|
}
|
|
|
|
const json = await response.json()
|
|
if (!tokenListValidator(json)) {
|
|
const validationErrors: string =
|
|
tokenListValidator.errors?.reduce<string>((memo, error) => {
|
|
const add = `${error.dataPath} ${error.message ?? ''}`
|
|
return memo.length > 0 ? `${memo}; ${add}` : `${add}`
|
|
}, '') ?? 'unknown error'
|
|
throw new Error(`Token list failed validation: ${validationErrors}`)
|
|
}
|
|
return json
|
|
}
|
|
throw new Error('Unrecognized list URL protocol.')
|
|
}
|