feat: expand non-evm relay and route planning support

This commit is contained in:
defiQUG
2026-04-18 12:05:34 -07:00
parent da78073104
commit 843cdbf71c
113 changed files with 8542 additions and 222 deletions

View File

@@ -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,