Парсинг данных с CoinGecko / CoinMarketCap
CoinGecko и CoinMarketCap — два основных агрегатора рыночных данных для крипто: цены, капитализация, объёмы, списки токенов, данные по биржам. Оба предоставляют API, но с разными ограничениями, покрытием и качеством данных. Для большинства задач CoinGecko API предпочтительнее: более щедрый бесплатный tier и лучшее покрытие DeFi-токенов.
CoinGecko API: что, как, сколько
Free tier (без ключа): 10-30 запросов/минуту, нет SLA. Для тестирования и MVP — достаточно.
Demo tier (бесплатный ключ): 30 req/min, 10,000 req/month — практически то же самое, но с ключом для трекинга.
Pro tier ($129/month): 500 req/min, исторические данные без ограничений, endpoint /coins/{id}/market_chart с диапазоном до 5 лет.
Основные endpoints:
const COINGECKO_BASE = 'https://api.coingecko.com/api/v3'
// Pro: 'https://pro-api.coingecko.com/api/v3'
class CoinGeckoClient {
constructor(private apiKey?: string) {}
private async request<T>(path: string, params?: Record<string, string>): Promise<T> {
const url = new URL(`${COINGECKO_BASE}${path}`)
if (params) Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v))
if (this.apiKey) url.searchParams.set('x_cg_pro_api_key', this.apiKey)
const res = await fetch(url.toString())
if (res.status === 429) {
const retryAfter = res.headers.get('Retry-After')
await sleep((parseInt(retryAfter || '60') + 1) * 1000)
return this.request(path, params) // retry
}
if (!res.ok) throw new Error(`CoinGecko ${res.status}: ${await res.text()}`)
return res.json()
}
// Текущие цены для списка токенов
async getSimplePrice(
ids: string[],
vsCurrencies: string[] = ['usd'],
includeMarketCap = false,
include24hVol = false,
include24hChange = false
) {
return this.request<Record<string, Record<string, number>>>('/simple/price', {
ids: ids.join(','),
vs_currencies: vsCurrencies.join(','),
include_market_cap: String(includeMarketCap),
include_24hr_vol: String(include24hVol),
include_24hr_change: String(include24hChange),
})
}
// Маркет данные с пагинацией
async getMarkets(page = 1, perPage = 250) {
return this.request<CoinMarketData[]>('/coins/markets', {
vs_currency: 'usd',
order: 'market_cap_desc',
per_page: String(perPage),
page: String(page),
sparkline: 'false',
})
}
// Исторические данные (Pro)
async getMarketChart(coinId: string, days: number | 'max') {
return this.request<MarketChart>(`/coins/${coinId}/market_chart`, {
vs_currency: 'usd',
days: String(days),
interval: days === 'max' || days > 90 ? 'daily' : 'hourly',
})
}
}
Получение полного списка монет
Для матчинга contract address → CoinGecko ID нужен /coins/list (все 15,000+ монет) и /coins/list?include_platform=true (с адресами по цепочкам). Эти данные меняются редко — кешировать на 24 часа:
async function buildTokenAddressIndex(): Promise<Map<string, string>> {
const coins = await client.request<CoinWithPlatforms[]>(
'/coins/list',
{ include_platform: 'true' }
)
const index = new Map<string, string>() // 'chain:address' → coingecko_id
for (const coin of coins) {
for (const [platform, address] of Object.entries(coin.platforms || {})) {
if (address) {
index.set(`${platform}:${address.toLowerCase()}`, coin.id)
}
}
}
return index
}
CoinMarketCap API
CMC API требует ключ даже для базовых запросов. Бесплатный plan — 10,000 кредитов/месяц (1 кредит ≈ 1 запрос). Список токенов, котировки, metadata.
class CoinMarketCapClient {
private headers = {
'X-CMC_PRO_API_KEY': process.env.CMC_API_KEY!,
'Accept': 'application/json',
}
async getLatestQuotes(symbols: string[]): Promise<CMCQuoteResponse> {
const res = await fetch(
`https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?symbol=${symbols.join(',')}`,
{ headers: this.headers }
)
const data = await res.json()
if (data.status.error_code !== 0) {
throw new Error(`CMC error: ${data.status.error_message}`)
}
return data
}
}
CMC даёт более точные данные по объёмам с крупных CEX, CoinGecko — лучше для DeFi и long-tail токенов. Для production систем мониторинга цен — используем оба с fallback логикой.
Кеширование и хранение
Для price feed с обновлением каждую минуту — Redis с TTL:
class PriceCache {
constructor(private redis: RedisClient, private client: CoinGeckoClient) {}
async getPrice(coinId: string): Promise<number> {
const cached = await this.redis.get(`price:${coinId}`)
if (cached) return parseFloat(cached)
const prices = await this.client.getSimplePrice([coinId])
const price = prices[coinId]?.usd
if (price) await this.redis.setEx(`price:${coinId}`, 60, String(price))
return price
}
// Батчевое обновление для списка токенов
async refreshPrices(coinIds: string[]): Promise<void> {
// CoinGecko принимает до 250 ID за запрос
const chunks = chunk(coinIds, 250)
for (const ids of chunks) {
const prices = await this.client.getSimplePrice(ids, ['usd'], true, true, true)
const pipeline = this.redis.pipeline()
for (const [id, data] of Object.entries(prices)) {
pipeline.setEx(`price:${id}`, 120, JSON.stringify(data))
}
await pipeline.exec()
}
}
}
Исторические данные — PostgreSQL с индексом по (coin_id, timestamp). Для интенсивных временных запросов — TimescaleDB hypertable.
Типичные задачи
Price alert система: фоновый джоб каждую минуту обновляет цены топ-N токенов, проверяет пользовательские алерты (цена выше/ниже порога, изменение на X% за Y часов).
Portfolio tracker: текущие цены + исторические для P&L расчёта. CoinGecko /coins/{id}/history?date=dd-mm-yyyy для стоимости на конкретную дату.
Token discovery: регулярный парсинг новых листингов через /coins/markets?order=id_asc&page=N с отслеживанием появления новых ID.
Интеграция занимает 1-3 дня: API клиент с rate limiting и retry, кеш в Redis, хранение в PostgreSQL, фоновый воркер для обновлений.







