UNPKG

@fanitrade/fani-solana-tokenlist

Version:
190 lines 15 kB
import * as anchor from '@project-serum/anchor'; import { PublicKey } from '@solana/web3.js'; import axios from 'axios'; import { fetch } from 'cross-fetch'; import Joi from 'joi'; import { decodeMetadata } from '../utils/Metadata'; import { sendToSolanaTokenList } from '../utils/sendTokenToSolanaTokenList'; import tokenlist from './../tokens/solana.tokenlist.json'; const TOKEN_METADATA_PROGRAM_ID = new anchor.web3.PublicKey('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'); const schema = Joi.object({ chainId: Joi.number(). required(), address: Joi.string() .required(), symbol: Joi.string() .required(), name: Joi.string() .required(), decimals: Joi.string(). required(), logoURI: Joi.string() .required(), extensions: Joi.object().optional() }); export var ENV; (function (ENV) { ENV[ENV["MainnetBeta"] = 101] = "MainnetBeta"; ENV[ENV["Testnet"] = 102] = "Testnet"; ENV[ENV["Devnet"] = 103] = "Devnet"; })(ENV || (ENV = {})); export const CLUSTER_SLUGS = { 'mainnet-beta': ENV.MainnetBeta, testnet: ENV.Testnet, devnet: ENV.Devnet }; export class GitHubTokenListResolutionStrategy { constructor() { this.repositories = [ 'https://raw.githubusercontent.com/FaniTrade-Investment-L-L-C/fani-token-list/main/src/tokens/solana.tokenlist.json' ]; this.resolve = () => { return queryJsonFiles(this.repositories); }; } } export class CDNTokenListResolutionStrategy { constructor() { this.repositories = [ 'https://cdn.jsdelivr.net/gh/solana-labs/token-list@latest/src/tokens/solana.tokenlist.json' ]; this.resolve = () => { return queryJsonFiles(this.repositories); }; } } export class SolanaTokenListResolutionStrategy { constructor() { this.repositories = ['https://token-list.solana.com/solana.tokenlist.json']; this.resolve = () => { return queryJsonFiles(this.repositories); }; } } const queryJsonFiles = async (files) => { const responses = (await Promise.all(files.map(async (repo) => { try { const response = await fetch(repo); const json = (await response.json()); return json; } catch { console.info(`@solana/token-registry: falling back to static repository.`); return tokenlist; } }))); return responses .map((tokenlist) => tokenlist.tokens || []) .reduce((acc, arr) => acc.concat(arr), []); }; export var Strategy; (function (Strategy) { Strategy["GitHub"] = "GitHub"; Strategy["Static"] = "Static"; Strategy["Solana"] = "Solana"; Strategy["CDN"] = "CDN"; })(Strategy || (Strategy = {})); export class StaticTokenListResolutionStrategy { constructor() { this.resolve = () => { return tokenlist.tokens || []; }; } } export class TokenListProvider { constructor() { this.resolve = async (strategy = Strategy.CDN) => { return new TokenListContainer(await TokenListProvider.strategies[strategy].resolve()); }; } } TokenListProvider.strategies = { [Strategy.GitHub]: new GitHubTokenListResolutionStrategy(), [Strategy.Static]: new StaticTokenListResolutionStrategy(), [Strategy.Solana]: new SolanaTokenListResolutionStrategy(), [Strategy.CDN]: new CDNTokenListResolutionStrategy() }; async function getMetadata(mint) { return (await anchor.web3.PublicKey.findProgramAddress([ Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer() ], TOKEN_METADATA_PROGRAM_ID))[0]; } export async function addTokenToList(gitAccessToken, tokenDetails) { // const { address, symbol, name, decimals, logoURI, extensions } = tokenDetails; console.log(gitAccessToken); const { error } = schema.validate({ ...tokenDetails }); if (error) { console.log(error); return ({ status: "Failed", message: "Error Creating Token", detail: error.details[0].message }); } else { const isEmpty = Object.values(tokenDetails.extensions).every(x => x === null || x === ''); if (isEmpty) { delete tokenDetails.extensions; console.log("deleting extension obj values..."); console.log(tokenDetails); } else { Object.keys(tokenDetails.extensions).forEach((k) => tokenDetails.extensions[k] == '' && delete tokenDetails.extensions[k]); console.log("deleting unused values"); console.log(tokenDetails); } const reuslt = await sendToSolanaTokenList(gitAccessToken, tokenDetails); return reuslt; } } export async function getTokenMetaData(connection, mint) { let fetchedData; const metaData = await getMetadata(new PublicKey(mint)); const accountInfo = await connection.getParsedAccountInfo(metaData); const decodedData = decodeMetadata(accountInfo?.value?.data); if (decodedData) { const url = encodeURI(decodedData.data.uri); return axios.get(url.split('%00%00%00%00')[0]).then((res) => { fetchedData = res.data; return new Promise(function (resolve) { resolve(fetchedData); }); }); } else { return {}; // // @ts-ignore // new Promise(function (resolve, reject) { // reject({}); // }); } } export class TokenListContainer { constructor(tokenList) { this.tokenList = tokenList; this.filterByTag = (tag) => { return new TokenListContainer(this.tokenList.filter((item) => (item.tags || []).includes(tag))); }; this.filterByChainId = (chainId) => { return new TokenListContainer(this.tokenList.filter((item) => item.chainId === chainId)); }; this.excludeByChainId = (chainId) => { return new TokenListContainer(this.tokenList.filter((item) => item.chainId !== chainId)); }; this.excludeByTag = (tag) => { return new TokenListContainer(this.tokenList.filter((item) => !(item.tags || []).includes(tag))); }; this.filterByClusterSlug = (slug) => { if (slug in CLUSTER_SLUGS) { return this.filterByChainId(CLUSTER_SLUGS[slug]); } throw new Error(`Unknown slug: ${slug}, please use one of ${Object.keys(CLUSTER_SLUGS)}`); }; this.getList = () => { return this.tokenList; }; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW5saXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi90b2tlbmxpc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE1BQU0sTUFBTSx1QkFBdUIsQ0FBQztBQUNoRCxPQUFPLEVBQWMsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDeEQsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQzFCLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDcEMsT0FBTyxHQUFHLE1BQU0sS0FBSyxDQUFDO0FBRXRCLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUM1RSxPQUFPLFNBQVMsTUFBTSxtQ0FBbUMsQ0FBQztBQUMxRCxNQUFNLHlCQUF5QixHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQ3pELDZDQUE2QyxDQUM5QyxDQUFDO0FBR0YsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQztJQUN4QixPQUFPLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtRQUNSLFFBQVEsRUFBRTtJQUN2QixPQUFPLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUNoQixRQUFRLEVBQUU7SUFFZixNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUNSLFFBQVEsRUFBRTtJQUV0QixJQUFJLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUNSLFFBQVEsRUFBRTtJQUVwQixRQUFRLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtRQUNiLFFBQVEsRUFBRTtJQUNuQixPQUFPLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUNSLFFBQVEsRUFBRTtJQUN2QixVQUFVLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtDQUNw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