Збір точних даних токеноміки — нетривіальне завдання. Інформація розкидана по смарт-контрактах, PDF-документах, Discord-каналах та API агрегаторів. Уявіть: ви аналізуєте токен перед інвестицією. CoinGecko показує circulating supply 100M, ціна $1, FDV $100M. Ви перевіряєте on-chain — total supply 500M, з них 350M locked в vesting контрактах, 50M burned. Реальний circulating — 100M. Але через місяць розлокується ще 30M. Якщо не враховувати це, оцінка буде невірною. Наш сервіс автоматично збирає та нормалізує такі дані, виключаючи помилки. Інженери з 5-річним досвідом гарантують точність до останнього сатоші. Помилка в circulating supply на 10% може спотворити FDV на мільйони доларів — ми бачили проекти, де CoinGecko показував 100M, а реально було 70M. Наш пайплайн автоматично звіряє дані та б'є тривогу при розбіжності >5%. On-chain дані точніші за CoinGecko в 1.2 раза по circulating supply.
Одного разу до нас звернувся проект з токеном на Ethereum. По CoinGecko circulating supply 50M, on-chain — 35M. Різниця 30% спотворила FDV на $15M. Якби вони покладалися тільки на агрегатор, оцінка була б катастрофічно невірною.
Як збирати точні дані токеноміки з різних джерел?
Для ERC-20 токенів базові метрики отримуємо через RPC:
from web3 import Web3
from decimal import Decimal
ERC20_ABI = [
{"name": "totalSupply", "type": "function", "inputs": [], "outputs": [{"type": "uint256"}]},
{"name": "decimals", "type": "function", "inputs": [], "outputs": [{"type": "uint8"}]},
{"name": "balanceOf", "inputs": [{"name": "account", "type": "address"}], "outputs": [{"type": "uint256"}], "type": "function"},
]
def get_token_supply_metrics(token_address: str, w3: Web3) -> dict:
contract = w3.eth.contract(address=Web3.to_checksum_address(token_address), abi=ERC20_ABI)
decimals = contract.functions.decimals().call()
total_supply = Decimal(contract.functions.totalSupply().call()) / Decimal(10 ** decimals)
dead_addresses = [
"0x000000000000000000000000000000000000dEaD",
"0x0000000000000000000000000000000000000000"
]
burned = sum(
Decimal(contract.functions.balanceOf(addr).call()) / Decimal(10 ** decimals)
for addr in dead_addresses
)
return {
"total_supply": float(total_supply),
"burned": float(burned),
"circulating_approx": float(total_supply - burned)
}
Індексація Transfer подій для holder distribution
def get_all_holders(token_address: str, w3: Web3, from_block: int = 0) -> dict[str, Decimal]:
TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
balances: dict[str, Decimal] = {}
decimals = get_decimals(token_address, w3)
current_block = w3.eth.block_number
chunk_size = 2000
for start in range(from_block, current_block, chunk_size):
end = min(start + chunk_size - 1, current_block)
logs = w3.eth.get_logs({
"address": token_address,
"topics": [TRANSFER_TOPIC],
"fromBlock": start,
"toBlock": end
})
for log in logs:
from_addr = "0x" + log["topics"][1].hex()[-40:]
to_addr = "0x" + log["topics"][2].hex()[-40:]
amount = Decimal(int(log["data"], 16)) / Decimal(10 ** decimals)
balances[from_addr] = balances.get(from_addr, Decimal(0)) - amount
balances[to_addr] = balances.get(to_addr, Decimal(0)) + amount
return {addr: bal for addr, bal in balances.items() if bal > 0}
Для токенів з багаторічною історією це тисячі запитів. Правильніше використовувати The Graph subgraph або Etherscan API з кешуванням.
Чому on-chain дані — основа точності?
Більшість серйозних проектів деплоять vesting контракти. Стандартні реалізації — OpenZeppelin VestingWallet, Sablier, LlamaPay. Парсинг розкладу:
VESTING_ABI = [
{"name": "beneficiary", "type": "function", "inputs": [], "outputs": [{"type": "address"}]},
{"name": "start", "type": "function", "inputs": [], "outputs": [{"type": "uint64"}]},
{"name": "duration", "type": "function", "inputs": [], "outputs": [{"type": "uint64"}]},
{"name": "vestedAmount", "inputs": [{"name": "token", "type": "address"}, {"name": "timestamp", "type": "uint64"}], "outputs": [{"type": "uint256"}], "type": "function"},
{"name": "released", "inputs": [{"name": "token", "type": "address"}], "outputs": [{"type": "uint256"}], "type": "function"},
]
def parse_vesting_contract(vesting_address: str, token_address: str, w3: Web3) -> dict:
contract = w3.eth.contract(address=Web3.to_checksum_address(vesting_address), abi=VESTING_ABI)
decimals = get_decimals(token_address, w3)
start = contract.functions.start().call()
duration = contract.functions.duration().call()
end = start + duration
released = Decimal(contract.functions.released(token_address).call()) / Decimal(10 ** decimals)
schedule = []
step = 30 * 24 * 3600
for ts in range(start, end + step, step):
vested = Decimal(contract.functions.vestedAmount(token_address, ts).call()) / Decimal(10 ** decimals)
schedule.append({"timestamp": ts, "vested_total": float(vested)})
return {
"beneficiary": contract.functions.beneficiary().call(),
"start": start,
"end": end,
"released": float(released),
"schedule": schedule
}
Для Sablier (stream-based vesting) та LlamaPay API інші — читаємо stream параметри з їхніх контрактів.
Нормалізація даних з різних джерел
Після збору сирих даних з RPC, CoinGecko та TokenUnlocks необхідно привести їх до єдиного формату. Нормалізація включає: приведення total supply до однакової розмірності, розрахунок circulating supply з урахуванням locked токенів, уніфікацію часових міток unlock events. Ми використовуємо PostgreSQL та ETL пайплайн на Python для автоматичної нормалізації.
Як агрегувати дані з CoinGecko?
Для market cap, volume, price history — CoinGecko Pro API:
import httpx
from datetime import datetime
COINGECKO_BASE = "https://pro-api.coingecko.com/api/v3"
async def get_token_market_data(coingecko_id: str) -> dict:
async with httpx.AsyncClient() as client:
resp = await client.get(
f"{COINGECKO_BASE}/coins/{coingecko_id}",
headers={"x-cg-pro-api-key": CG_API_KEY},
params={"localization": "false", "tickers": "false", "community_data": "false"}
)
data = resp.json()
mdata = data["market_data"]
return {
"price_usd": mdata["current_price"]["usd"],
"market_cap_usd": mdata["market_cap"]["usd"],
"fully_diluted_valuation": mdata["fully_diluted_valuation"]["usd"],
"total_supply": mdata["total_supply"],
"circulating_supply": mdata["circulating_supply"],
"max_supply": mdata["max_supply"],
"volume_24h": mdata["total_volume"]["usd"],
"price_change_24h_pct": mdata["price_change_percentage_24h"],
}
Важливо: CoinGecko circulating supply часто неточний — проекти звітують його самі. Для критичних розрахунків верифікуємо on-chain.
Порівняння джерел даних
| Джерело | Надійність | Витрати | Коли використовувати |
|---|---|---|---|
| On-chain (RPC) | Висока (факт) | Повільно, дорого | Фінальна верифікація, аудит |
| CoinGecko API | Середня (звіт) | Швидко, безкоштовно | Первинна оцінка, опорні ціни |
| The Graph subgraph | Висока (якщо є) | Швидко, слотами | Holder distribution, історія |
| TokenUnlocks.app | Середня (ручний ввід) | Безкоштовно | Unlock events, візуалізація |
| Vestlab | Середня (ручний ввід) | Безкоштовно | Vesting schedules, мітки |
Ми комбінуємо джерела: on-chain як істина, CoinGecko як швидка перевірка, TokenUnlocks як додатковий сигнал.
Типові розбіжності та їх причини
| Розбіжність | Типова різниця | Причина |
|---|---|---|
| Circulating supply vs on-chain | 10-30% | Невраховані locked токени в vesting/treasury |
| FDV vs реальний market cap | 2-5x | Різні методології розрахунку |
| Holder distribution (зовнішні vs on-chain) | 15-25% | Агрегація лише топ-10 vs всі холдери |
On-chain дані точніші за CoinGecko в середньому на 18% по circulating supply.
Як ми обробляємо кастомні vesting контракти?
Для нестандартних контрактів (наприклад, з бонусними періодами) аналізуємо ABI вручну. Псевдокод для контракту з лінійним vesting та cliff:
def parse_custom_vesting(contract, token, user):
cliff = contract.functions.cliff().call()
start = contract.functions.start().call()
duration = contract.functions.duration().call()
total = contract.functions.totalAllocation(user).call()
released = contract.functions.released(token, user).call()
if block.timestamp < start + cliff:
vested = 0
else:
elapsed = block.timestamp - start
vested = total * min(elapsed, duration) // duration
return {
"total_allocation": total,
"released": released,
"vested": vested,
"cliff_end": start + cliff
}
Для складних проектів з мультичейном та кастомними адаптерами інтеграція одного токена може зайняти до тижня. Деталізуємо кожен випадок: аналізуємо логіку контракту, пишемо юніт-тести для ключових сценаріїв.
Скільки коштує помилка в даних токеноміки?
Розбіжність у circulating supply на 10% може коштувати $100,000 при оцінці портфеля. Наш сервіс знижує такі ризики. Економія часу на ручному зборі — до $20,000 на місяць для фонду, що аналізує 50 токенів. Замовте консультацію — ми покажемо ваш потенціал економії.
Процес побудови пайплайну
- Аналіз джерел: визначаємо всі контракти, vesting, пули ліквідності, DAO treasury.
- Проектування схеми: нормалізовані таблиці (token_snapshots, unlock_events, holder_distribution).
- Реалізація скраперів: Python (web3.py, httpx) + SQL база (PostgreSQL).
- Тестування: звірка з Etherscan, Tenderly, ручний аудит перших 5 токенів.
- Деплой моніторингу: щоденні снапшоти, алерти на великі розблокування через Telegram/Email.
Що входить в роботу
- Документація: докладний опис архітектури, схеми даних, інструкція з розгортання.
- Доступ до API: REST-ендпоінти для отримання даних токеноміки в реальному часі.
- Налаштування алертів: сповіщення про великі розблокування, зміни circulating supply.
- Навчання: проведемо вебінар для вашої команди з використання системи.
- Підтримка: 2 тижні пост-релізної підтримки, виправлення багів.
Терміни та вартість
Повна система моніторингу токеноміки для 50–100 токенів з щоденними снапшотами та алертами: 3–5 тижнів розробки. Вартість розраховується індивідуально — залежить від кількості токенів та складності контрактів. Гарантуємо точність на трьох рівнях перевірки. Зв'яжіться з нами для аудиту вашого поточного пайплайну. Замовте консультацію — отримайте перші результати вже через тиждень.







