import { guardedFetch } from "./endpoint-allowlist.mjs";
import { getMarketCache } from "./market-cache.mjs";
//#region extensions/crypto/src/services/dexscreener-service.ts
/**
* DexScreener Service — shared API client for token data.
*
* Centralizes all DexScreener calls. Previously duplicated across
* defi-price.ts, defi-balance.ts, and market-intel.ts.
*/
const BASE_URL = "https://api.dexscreener.com";
const CHAIN_ALIASES = {
	base: "base",
	ethereum: "ethereum",
	eth: "ethereum",
	arbitrum: "arbitrum",
	arb: "arbitrum",
	optimism: "optimism",
	op: "optimism",
	polygon: "polygon",
	matic: "polygon"
};
function resolveChain(input) {
	return CHAIN_ALIASES[input.toLowerCase()] || input;
}
/**
* Infer the cache category from the DexScreener API path.
*/
function inferCacheCategory(path) {
	if (path.includes("/token-boosts/") || path.includes("/trending")) return "trending";
	if (path.includes("/latest/dex/pairs/")) return "new_pairs";
	if (path.includes("/tokens/") || path.includes("/simple/price")) return "token_price";
	if (path.includes("/search")) return "token_search";
	if (path.includes("/profiles")) return "token_profile";
	return "token_price";
}
async function fetchDexScreener(path) {
	const cache = getMarketCache();
	const category = inferCacheCategory(path);
	return cache.getOrFetch(category, `dexscreener:${path}`, async () => {
		const response = await guardedFetch(`${BASE_URL}${path}`, {
			headers: { Accept: "application/json" },
			signal: AbortSignal.timeout(15e3)
		});
		if (!response.ok) throw new Error(`DexScreener API error: ${response.status} ${response.statusText}`);
		return response.json();
	});
}
/**
* Search for a token by symbol, name, or address.
* Returns pairs sorted by liquidity (highest first).
*/
async function searchToken(query, chain) {
	let data;
	if (query.startsWith("0x") && query.length === 42 && chain) data = await fetchDexScreener(`/tokens/v1/${resolveChain(chain)}/${query}`);
	else data = await fetchDexScreener(`/latest/dex/search?q=${encodeURIComponent(query)}`);
	return (data?.pairs ?? (Array.isArray(data) ? data : [])).filter((p) => !chain || p.chainId === resolveChain(chain)).sort((a, b) => (b.liquidity?.usd ?? 0) - (a.liquidity?.usd ?? 0));
}
/**
* Get the USD price for a token. Returns 0 if not found.
*/
async function getTokenPriceUsd(query, chain = "base") {
	try {
		const top = (await searchToken(query, chain))[0];
		if (!top) return {
			priceUsd: 0,
			pair: null
		};
		return {
			priceUsd: parseFloat(top.priceUsd ?? "0"),
			pair: top
		};
	} catch {
		return {
			priceUsd: 0,
			pair: null
		};
	}
}
/**
* Get ETH price in USD (via WETH/USDC pair on Base).
*/
async function getEthPriceUsd() {
	try {
		const basePair = (await fetchDexScreener("/latest/dex/search?q=WETH%20USDC")).pairs?.find((p) => p.chainId === "base" && p.baseToken?.symbol === "WETH");
		return basePair ? parseFloat(basePair.priceUsd ?? "0") : 0;
	} catch {
		return 0;
	}
}
/**
* Get top boosted (trending) tokens.
*/
async function getTrending(chain, limit = 20) {
	return (await fetchDexScreener("/token-boosts/top/v1") ?? []).filter((t) => !chain || t.chainId === resolveChain(chain)).slice(0, limit);
}
/**
* Get latest pairs on a chain.
*/
async function getNewPairs(chain = "base", limit = 10) {
	return ((await fetchDexScreener(`/latest/dex/pairs/${resolveChain(chain)}`))?.pairs ?? []).slice(0, limit);
}
//#endregion
export { fetchDexScreener, getEthPriceUsd, getNewPairs, getTokenPriceUsd, getTrending, resolveChain, searchToken };

//# sourceMappingURL=dexscreener-service.mjs.map