|
| 1 | +# Prompt 025 — Derivatives & Perps Routes |
| 2 | + |
| 3 | +## Preamble — Read Every Time |
| 4 | + |
| 5 | +You are an expert TypeScript engineer building **cryptocurrency.cv**. Stack: **Hono + TypeScript + Node.js**, Google Cloud Run, Redis caching, Zod validation. |
| 6 | + |
| 7 | +### Absolute Rules |
| 8 | + |
| 9 | +1. **Never mock, stub, or fake anything.** 2. **TypeScript strict mode** — no `any`. 3. **Always kill terminals** after every command. 4. **Commit and push as `nirholas`.** 5. **If close to hallucinating — tell the prompter.** 6. **Run `npx tsc --noEmit` and `npx vitest run`.** 7. **Improve any existing code you touch.** |
| 10 | + |
| 11 | +--- |
| 12 | + |
| 13 | +## Task |
| 14 | + |
| 15 | +Build / improve `src/routes/derivatives.ts` and `src/routes/perps.ts` — comprehensive derivatives, perpetual futures, and options data routes. |
| 16 | + |
| 17 | +### Source Imports |
| 18 | + |
| 19 | +```typescript |
| 20 | +import { Hono } from 'hono'; |
| 21 | +import * as coinglass from '../sources/coinglass.js'; |
| 22 | +import * as deribit from '../sources/deribit.js'; |
| 23 | +import * as dydx from '../sources/dydx.js'; |
| 24 | +import * as binance from '../sources/binance.js'; |
| 25 | +import * as hyperliquid from '../sources/hyperliquid.js'; |
| 26 | +import { ApiError } from '../lib/api-error.js'; |
| 27 | + |
| 28 | +export const derivativesRoutes = new Hono(); |
| 29 | +export const perpsRoutes = new Hono(); |
| 30 | +``` |
| 31 | + |
| 32 | +### Derivatives Endpoints |
| 33 | + |
| 34 | +| Method | Path | Description | |
| 35 | +|--------|------|-------------| |
| 36 | +| GET | `/open-interest` | Aggregated open interest across exchanges | |
| 37 | +| GET | `/open-interest/:symbol` | OI breakdown by exchange for a symbol | |
| 38 | +| GET | `/open-interest/history/:symbol` | Historical OI chart | |
| 39 | +| GET | `/funding-rates` | Current funding rates across exchanges | |
| 40 | +| GET | `/funding-rates/:symbol` | Funding rate history for symbol | |
| 41 | +| GET | `/funding-heatmap` | Funding rate heatmap (all symbols × exchanges) | |
| 42 | +| GET | `/liquidations` | Real-time liquidation feed | |
| 43 | +| GET | `/liquidations/:symbol` | Liquidation history for symbol | |
| 44 | +| GET | `/liquidation-heatmap` | Liquidation heatmap by price level | |
| 45 | +| GET | `/long-short-ratio` | Long/short ratio across exchanges | |
| 46 | +| GET | `/options/overview` | Options market overview | |
| 47 | +| GET | `/options/chain/:symbol` | Options chain (calls + puts by strike/expiry) | |
| 48 | +| GET | `/options/oi` | Options open interest by strike/expiry | |
| 49 | +| GET | `/options/max-pain/:symbol` | Max pain calculation | |
| 50 | +| GET | `/options/volatility/:symbol` | Implied and historical volatility | |
| 51 | +| GET | `/options/greeks/:symbol` | Greeks surface | |
| 52 | +| GET | `/etf/flows` | BTC/ETH ETF flow data | |
| 53 | +| GET | `/etf/holdings` | ETF AUM and holdings | |
| 54 | + |
| 55 | +### Perps Endpoints |
| 56 | + |
| 57 | +| Method | Path | Description | |
| 58 | +|--------|------|-------------| |
| 59 | +| GET | `/markets` | All perpetual markets across DEXs | |
| 60 | +| GET | `/market/:protocol/:id` | Specific perp market | |
| 61 | +| GET | `/orderbook/:protocol/:id` | Perp orderbook (dYdX, Hyperliquid) | |
| 62 | +| GET | `/trades/:protocol/:id` | Recent perp trades | |
| 63 | +| GET | `/funding/:protocol` | Funding rates for a DEX | |
| 64 | +| GET | `/leaderboard/:protocol` | Top traders leaderboard | |
| 65 | +| GET | `/volume-comparison` | DEX perps volume comparison | |
| 66 | +| GET | `/oi-comparison` | DEX perps OI comparison | |
| 67 | + |
| 68 | +### Aggregated Open Interest |
| 69 | + |
| 70 | +```typescript |
| 71 | +derivativesRoutes.get('/open-interest', async (c) => { |
| 72 | + const [coinglassOI, dydxMarkets, hlMarkets] = await Promise.allSettled([ |
| 73 | + coinglass.getOpenInterest(), |
| 74 | + dydx.getMarkets(), |
| 75 | + hyperliquid.getExchangeInfo(), |
| 76 | + ]); |
| 77 | + |
| 78 | + // Merge OI data from all sources, normalize by symbol |
| 79 | + // Return total OI per symbol across all venues |
| 80 | + // Sort by total OI descending |
| 81 | + |
| 82 | + return c.json({ |
| 83 | + data: { |
| 84 | + totalOpenInterest: totalOI, |
| 85 | + symbols: mergedSymbols, |
| 86 | + byExchange: exchangeBreakdown, |
| 87 | + }, |
| 88 | + timestamp: new Date().toISOString(), |
| 89 | + }); |
| 90 | +}); |
| 91 | +``` |
| 92 | + |
| 93 | +### Funding Rate Heatmap |
| 94 | + |
| 95 | +```typescript |
| 96 | +derivativesRoutes.get('/funding-heatmap', async (c) => { |
| 97 | + // Fetch funding rates from binance, bybit, okx, dydx, hyperliquid |
| 98 | + // Build a matrix: symbols (rows) × exchanges (columns) × funding rate (value) |
| 99 | + |
| 100 | + return c.json({ |
| 101 | + data: { |
| 102 | + symbols: ['BTC', 'ETH', 'SOL', ...], |
| 103 | + exchanges: ['binance', 'bybit', 'okx', 'dydx', 'hyperliquid'], |
| 104 | + rates: { |
| 105 | + BTC: { binance: 0.0001, bybit: 0.00012, okx: 0.0001, dydx: 0.00015, hyperliquid: 0.0002 }, |
| 106 | + // ... |
| 107 | + }, |
| 108 | + annualized: { ... }, // rates * 3 * 365 (for 8-hour funding) or * 8760 (hourly) |
| 109 | + }, |
| 110 | + timestamp: new Date().toISOString(), |
| 111 | + }); |
| 112 | +}); |
| 113 | +``` |
| 114 | + |
| 115 | +### Options Max Pain Calculation |
| 116 | + |
| 117 | +```typescript |
| 118 | +derivativesRoutes.get('/options/max-pain/:symbol', async (c) => { |
| 119 | + const { symbol } = c.req.param(); |
| 120 | + const expiry = c.req.query('expiry'); |
| 121 | + |
| 122 | + // Fetch option chain from Deribit |
| 123 | + const instruments = await deribit.getInstruments(`${symbol.toUpperCase()}-USD`, 'option'); |
| 124 | + |
| 125 | + // For each strike price, calculate total pain: |
| 126 | + // pain(strike) = sum(call_oi * max(0, strike - call_strike)) + sum(put_oi * max(0, put_strike - strike)) |
| 127 | + // Max pain = strike with minimum total pain |
| 128 | + |
| 129 | + return c.json({ |
| 130 | + data: { |
| 131 | + symbol, |
| 132 | + expiry, |
| 133 | + maxPainStrike: maxPainPrice, |
| 134 | + currentPrice: spotPrice, |
| 135 | + distancePercent: ((spotPrice - maxPainPrice) / spotPrice) * 100, |
| 136 | + painByStrike: painLevels, |
| 137 | + }, |
| 138 | + timestamp: new Date().toISOString(), |
| 139 | + }); |
| 140 | +}); |
| 141 | +``` |
| 142 | + |
| 143 | +### Liquidation Map |
| 144 | + |
| 145 | +```typescript |
| 146 | +derivativesRoutes.get('/liquidation-heatmap', async (c) => { |
| 147 | + const symbol = c.req.query('symbol') || 'BTC'; |
| 148 | + |
| 149 | + // Fetch liquidation data from CoinGlass |
| 150 | + // Build a price-level heatmap showing estimated liquidation clusters |
| 151 | + // Key insight: Show where leveraged positions would be liquidated |
| 152 | + |
| 153 | + return c.json({ |
| 154 | + data: { |
| 155 | + symbol, |
| 156 | + currentPrice: price, |
| 157 | + longLiquidations: [ // price levels where longs get liquidated (below current price) |
| 158 | + { price: 59000, estimatedUsd: 150_000_000 }, |
| 159 | + // ... |
| 160 | + ], |
| 161 | + shortLiquidations: [ // price levels where shorts get liquidated (above current price) |
| 162 | + { price: 67000, estimatedUsd: 200_000_000 }, |
| 163 | + // ... |
| 164 | + ], |
| 165 | + total24hLiquidations: total, |
| 166 | + longTotal: longSum, |
| 167 | + shortTotal: shortSum, |
| 168 | + }, |
| 169 | + timestamp: new Date().toISOString(), |
| 170 | + }); |
| 171 | +}); |
| 172 | +``` |
| 173 | + |
| 174 | +### DEX Perps Volume Comparison |
| 175 | + |
| 176 | +```typescript |
| 177 | +perpsRoutes.get('/volume-comparison', async (c) => { |
| 178 | + const [dydxData, hlData] = await Promise.allSettled([ |
| 179 | + dydx.getMarkets(), |
| 180 | + hyperliquid.getExchangeInfo(), |
| 181 | + ]); |
| 182 | + |
| 183 | + // Compare 24h volume, OI, unique traders, number of markets |
| 184 | + return c.json({ |
| 185 | + data: [ |
| 186 | + { protocol: 'dydx', volume24h, openInterest, markets, topPairs }, |
| 187 | + { protocol: 'hyperliquid', volume24h, openInterest, markets, topPairs }, |
| 188 | + ], |
| 189 | + timestamp: new Date().toISOString(), |
| 190 | + }); |
| 191 | +}); |
| 192 | +``` |
| 193 | + |
| 194 | +### Acceptance Criteria |
| 195 | + |
| 196 | +- [ ] All 26+ endpoints compile and return JSON |
| 197 | +- [ ] Multi-source OI aggregation works across CEXs and DEXs |
| 198 | +- [ ] Funding heatmap covers 5+ exchanges |
| 199 | +- [ ] Options chain, max pain, and volatility surface work via Deribit |
| 200 | +- [ ] Liquidation heatmap builds price-level clusters |
| 201 | +- [ ] DEX perps routes support dYdX and Hyperliquid |
| 202 | +- [ ] Annualized funding correctly handles 8h vs 1h funding periods |
| 203 | +- [ ] Tests pass, committed and pushed as `nirholas`, terminals killed |
| 204 | + |
| 205 | +### Hallucination Warning |
| 206 | + |
| 207 | +CoinGlass API response format varies by endpoint. Open interest endpoints return data keyed by exchange. Deribit instruments for options use naming like `BTC-28MAR25-100000-C`. dYdX v4 has hourly funding (multiply by 8760 for annual), while CEXs have 8-hour funding (multiply by 1095). If unsure about CoinGlass or Deribit specifics, tell the prompter. |
0 commit comments