feat(jobs): cut coin stats over to on-chain data and remove Birdeye - #1007
Conversation
Retires the Birdeye-backed CoinStatsJob. CoinStatsOnchainJob now writes artist_coin_stats directly (it already read the AUDIO anchor from that table and iterated artist_coins), so every consumer — the artist_coin_prices view, v1_coins, v1_coin_insights, get_users, coin_dbc — keeps reading the same table unchanged. This is the Phase-2 cutover of the shadow-table rollout: the on-chain values were validated against Birdeye via artist_coin_stats_comparison before flipping. With CoinStatsJob gone and AudioPriceJob already sourcing the AUDIO/USDC pool on-chain, nothing calls Birdeye anymore, so this removes it entirely: - delete the birdeye client package, the dead server BirdeyeClient interface + field + unused mock, and the BirdeyeToken config field - drop the now-unused artist_coin_stats_onchain shadow table and the artist_coin_stats_comparison view (migration 0235) - de-Birdeye the artist_coin_prices view comment, swagger coin_insights description, and stale test/model comments Rendered stats (price, market cap, liquidity, holder, total supply, 24h change) are all on-chain-derived; the ~40 unrendered Birdeye-only columns stay in the table (NULL for new rows; consumers COALESCE to 0). Market cap shifts -8.5% in aggregate, concentrated entirely in dormant coins: Birdeye holds a stale last-trade price for the ~34 coins with no trades in months, while the on-chain value tracks the current pool. Coins that actually trade match within 0.3%; numberMarkets=1 for 53/57 and totalSupply==circulatingSupply, so it is neither a multi-market nor a supply-basis effect. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
383afad to
88987a6
Compare
Verified: the market-cap change is Birdeye correcting to reality, not on-chain under-countingFollowed up on the market-cap delta with live prod data + on-chain checks. Summary: No missing markets / not a supply artifact. It's Birdeye price staleness on dormant coins, and our value is provably correct. Three independent sources converge on the on-chain price, not Birdeye's:
Every coin that has traded recently (ICT, DREAM, JAY, AUDIO) matches Birdeye within ~1%. Aggregate market-cap change is −8.5%, 100% of it in coins that haven't traded in months (avg 87 days), where Birdeye holds a stale last-trade quote. Net: switching the anchor + stats on-chain makes prices more accurate for the long tail, with zero change to any liquid coin. |
What
Phase-2 cutover of the coin-stats shadow rollout: retires the Birdeye-backed
CoinStatsJob, makes the on-chain job the source of truth, and removes Birdeye from the service entirely. Follows #1006 (AUDIO anchor on-chain), which was the last Birdeye call outsideCoinStatsJob.Mechanism (why consumers don't change)
CoinStatsOnchainJobalready read the AUDIO anchor fromartist_coin_statsand iteratedartist_coins. The cutover just repoints its upsert fromartist_coin_stats_onchain→artist_coin_stats. Every consumer — theartist_coin_pricesview,v1_coins,v1_coin_insights,get_users,coin_dbc— keeps readingartist_coin_statsunchanged.(Renaming tables was rejected: Postgres views bind to table OID, so a rename would leave the view pointing at the old data.)
The AUDIO row bootstrap holds: AUDIO is one of the 57
artist_coins, so the on-chain job upserts its row (price kept viaCOALESCE, never clobbered), andAudioPriceJobmaintains its price from the pool.Birdeye removal
birdeye/client package, the dead serverBirdeyeClientinterface + field + unusedmock_birdeye_client.go, and theBirdeyeTokenconfig field.jobs/coin_stats.goand its indexer scheduling.artist_coin_stats_onchainshadow table andartist_coin_stats_comparisonview (migration 0235).artist_coin_pricesview comment, swaggercoin_insightsdescription, and stale test/model comments. (Applied migrations 0229–0231 keep their historical comments.)Behavior — market-cap change (verified against live prod data)
Rendered stats — price, market cap, liquidity, holder, total supply, 24h change — are all on-chain-derived. The ~40 unrendered Birdeye-only columns remain in the table (NULL on new rows; consumers
COALESCE(...,0)).Market cap moves −8.5% in aggregate ($4.64M → $4.25M), and it is a stale-price effect on dormant coins — not market aggregation and not a supply basis. Evidence from the live
/v1/coinspayload:numberMarkets= 1 for 53 of 57 coins. Only AUDIO (12) and KITT/UWU/JAY (2) have more, and those match within ~2%.totalSupply == circulatingSupplyfor every coin.Schema dump
sql/01_schema.sqlhand-edited to remove only the shadow table + comparison view (the committed dump was stale on unrelated merged migrations; a full regen would have pulled innew_chain_queueetc.). Diff is 1 comment reword + 113 deletions. Verified by reloading the dump into a fresh DB.Test
go build ./...,go vet ./...,go test ./jobs/(coin-stats + audio-price) andgo test ./api/(Coin/Wallet/Users) all pass against the regenerated DB.🤖 Generated with Claude Code