feat: expand non-evm relay and route planning support
This commit is contained in:
@@ -16,6 +16,11 @@ import {
|
||||
resolveCanonicalQuoteAddress,
|
||||
} from '../../config/canonical-tokens';
|
||||
import { getLiveDodoPools } from '../../services/live-dodo-fallback';
|
||||
import {
|
||||
buildExplorerLinks,
|
||||
mergeMarketWithValuation,
|
||||
resolveUsdValuation,
|
||||
} from '../../services/valuation-precedence';
|
||||
|
||||
const router: Router = Router();
|
||||
const tokenRepo = new TokenRepository();
|
||||
@@ -26,6 +31,26 @@ const coingeckoAdapter = new CoinGeckoAdapter();
|
||||
const cmcAdapter = new CoinMarketCapAdapter();
|
||||
const dexscreenerAdapter = new DexScreenerAdapter();
|
||||
|
||||
function buildMarketPricingExplorer(
|
||||
chainId: number,
|
||||
displayAddress: string,
|
||||
lookupAddress: string,
|
||||
marketData: Awaited<ReturnType<MarketDataRepository['getMarketData']>>,
|
||||
external: { coingecko?: Awaited<ReturnType<CoinGeckoAdapter['getMarketData']>>; cmc?: Awaited<ReturnType<CoinMarketCapAdapter['getMarketData']>>; dexscreener?: Awaited<ReturnType<DexScreenerAdapter['getMarketData']>> } | null
|
||||
) {
|
||||
const pricing = resolveUsdValuation({
|
||||
chainId,
|
||||
normalizedAddress: lookupAddress.toLowerCase(),
|
||||
indexer: marketData,
|
||||
coingecko: external?.coingecko ?? undefined,
|
||||
cmc: external?.cmc ?? undefined,
|
||||
dexscreener: external?.dexscreener ?? undefined,
|
||||
});
|
||||
const market = mergeMarketWithValuation(chainId, displayAddress.toLowerCase(), marketData, pricing);
|
||||
const explorer = buildExplorerLinks(chainId, displayAddress);
|
||||
return { market, pricing, explorer };
|
||||
}
|
||||
|
||||
function tokenFromCanonical(chainId: number, address: string): Token | null {
|
||||
const spec = getCanonicalTokenByAddress(chainId, address.toLowerCase());
|
||||
if (!spec) {
|
||||
@@ -182,10 +207,20 @@ router.get('/tokens', cacheMiddleware(60 * 1000), async (req: Request, res: Resp
|
||||
const { tokens, source } = await getTokensWithFallback(chainId, limit, offset);
|
||||
const tokensWithMarketData = await Promise.all(
|
||||
tokens.map(async (token) => {
|
||||
const marketData = await marketDataRepo.getMarketData(chainId, token.address);
|
||||
const resolution = resolveCanonicalQuoteAddress(chainId, token.address);
|
||||
const marketData = await marketDataRepo.getMarketData(chainId, resolution.lookupAddress);
|
||||
const { market, pricing, explorer } = buildMarketPricingExplorer(
|
||||
chainId,
|
||||
token.address,
|
||||
resolution.lookupAddress,
|
||||
marketData,
|
||||
null
|
||||
);
|
||||
const out: Record<string, unknown> = {
|
||||
...token,
|
||||
market: marketData || undefined,
|
||||
market: market || undefined,
|
||||
pricing,
|
||||
explorer,
|
||||
};
|
||||
if (includeDodoPool) {
|
||||
const pools = await getPoolsByTokenWithFallback(chainId, token.address);
|
||||
@@ -228,13 +263,32 @@ router.get('/tokens/:address', cacheMiddleware(60 * 1000), async (req: Request,
|
||||
return res.status(404).json({ error: 'Token not found' });
|
||||
}
|
||||
|
||||
const [marketData, pools, coingeckoData, cmcData, dexscreenerData] = await Promise.all([
|
||||
const [
|
||||
marketDataRaw,
|
||||
pools,
|
||||
coingeckoData,
|
||||
cmcData,
|
||||
dexscreenerData,
|
||||
coingeckoMarket,
|
||||
cmcMarket,
|
||||
dexscreenerMarket,
|
||||
] = await Promise.all([
|
||||
marketDataRepo.getMarketData(chainId, resolution.lookupAddress),
|
||||
getPoolsByTokenWithFallback(chainId, normalizedAddress),
|
||||
coingeckoAdapter.getTokenByContract(chainId, resolution.lookupAddress),
|
||||
cmcAdapter.getTokenByContract(chainId, resolution.lookupAddress),
|
||||
dexscreenerAdapter.getTokenByContract(chainId, resolution.lookupAddress),
|
||||
coingeckoAdapter.getMarketData(chainId, resolution.lookupAddress),
|
||||
cmcAdapter.getMarketData(chainId, resolution.lookupAddress),
|
||||
dexscreenerAdapter.getMarketData(chainId, resolution.lookupAddress),
|
||||
]);
|
||||
const { market: marketData, pricing, explorer } = buildMarketPricingExplorer(
|
||||
chainId,
|
||||
normalizedAddress,
|
||||
resolution.lookupAddress,
|
||||
marketDataRaw,
|
||||
{ coingecko: coingeckoMarket, cmc: cmcMarket, dexscreener: dexscreenerMarket }
|
||||
);
|
||||
|
||||
res.json({
|
||||
token: {
|
||||
@@ -243,6 +297,8 @@ router.get('/tokens/:address', cacheMiddleware(60 * 1000), async (req: Request,
|
||||
totalSupply: token.totalSupply,
|
||||
},
|
||||
market: marketData || undefined,
|
||||
pricing,
|
||||
explorer,
|
||||
external: {
|
||||
coingecko: coingeckoData || undefined,
|
||||
cmc: cmcData || undefined,
|
||||
|
||||
Reference in New Issue
Block a user