# MARKETS.md — Módulo de mercados Referencia para el frontend: contrato HTTP, mapping de datos de Polymarket, evento socket y errores. --- ## Variables de entorno requeridas ``` DATABASE_URL=file:./backend/prisma/polysignal.db PORT=7860 ``` No se necesita clave de API para Polymarket Gamma (pública). --- ## Endpoints ### `GET /api/v1/markets` Lista paginada de mercados activos sincronizados desde Polymarket. **No requiere autenticación.** **Query params** | Param | Tipo | Default | Descripción | |---|---|---|---| | `limit` | int (1-100) | `20` | Máximo de resultados | | `offset` | int | `0` | Paginación por offset | | `category` | string | — | Filtro: `politics` \| `crypto` \| `economics` \| `sports` | | `status` | string | `active` | Filtro: `active` \| `closed` \| `resolved` | **Respuesta `200`** ```json { "ok": true, "data": [ { "id": "559677", "question": "Will Hillary Clinton win the 2028 Democratic presidential nomination?", "category": null, "countryCode": null, "yesPrice": 0.0075, "noPrice": 0.9925, "volumeEur": 38608906.44, "liquidityEur": 2301398.64, "status": "active", "closesAt": "2028-11-07T00:00:00.000Z", "lastSynced": "2026-05-16T09:38:30.204Z" } ], "meta": { "total": 100, "limit": 1, "offset": 0 } } ``` > `category` y `countryCode` pueden ser `null` si Polymarket no los proporciona. --- ### `GET /api/v1/markets/:id` Detalle de un mercado por su ID de Polymarket. **No requiere autenticación.** **Params** | Param | Tipo | Descripción | |---|---|---| | `id` | string | ID numérico de Polymarket (ej. `559677`) | **Respuesta `200`** ```json { "ok": true, "data": { "id": "559677", "question": "Will Hillary Clinton win the 2028 Democratic presidential nomination?", "category": null, "countryCode": null, "yesPrice": 0.0075, "noPrice": 0.9925, "volumeEur": 38608906.44, "liquidityEur": 2301398.64, "status": "active", "closesAt": "2028-11-07T00:00:00.000Z", "lastSynced": "2026-05-16T09:38:30.204Z" } } ``` **Respuesta `404`** ```json { "ok": false, "error": { "code": "NOT_FOUND", "message": "Market not found" } } ``` --- ### `GET /api/v1/markets/:id/signal` Señal AI más reciente para un mercado. Ver [SIGNALS.md](SIGNALS.md) para el contrato completo. --- ## Mapping Polymarket Gamma API → `Market` URL de origen: `https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=100` | Campo Gamma API | Campo `Market` | Transformación | |---|---|---| | `id` | `id` | String (ID numérico de Polymarket) | | `question` | `question` | Directo | | `category` | `category` | Minúsculas; `null` si Gamma no lo envía | | — | `countryCode` | `null` por defecto (no proporcionado por Gamma) | | `outcomePrices[0]` | `yesPrice` | `parseFloat`; rango 0.0–1.0 | | `outcomePrices[1]` | `noPrice` | `parseFloat`; rango 0.0–1.0 | | `volume` | `volumeEur` | `parseFloat(volume) * 0.93` (USD→EUR tasa fija) | | `liquidity` | `liquidityEur` | Igual que `volumeEur` | | `active` + `closed` + `archived` | `status` | `active=true → "active"`, `closed=true → "closed"`, `archived=true → "resolved"` | | `endDateIso` | `closesAt` | `new Date(endDateIso)` | | — | `lastSynced` | `new Date()` en el momento del upsert | La sincronización usa `prisma.market.upsert({ where: { id }, ... })` para evitar duplicados. --- ## Socket — evento `market_update` Emitido por `src/socket/broadcaster.js` cada 30 s (tras `syncMarkets`). **Nombre del evento:** `market_update` **Payload** ```json { "marketId": "0x1a2b...", "yesPrice": 0.63, "noPrice": 0.37, "volumeEur": 125000.00 } ``` **Uso en el frontend (Socket.io client)** ```js import { io } from 'socket.io-client'; const socket = io('http://localhost:7860'); socket.on('market_update', ({ marketId, yesPrice, noPrice }) => { // actualizar estado local del mercado }); ``` En producción (HF Spaces) el frontend y backend comparten origen → usar `io()` sin URL. --- ## Ejemplos `curl` ```bash # Listar mercados (primeros 5) curl "http://localhost:7860/api/v1/markets?limit=5" # Filtrar por estado curl "http://localhost:7860/api/v1/markets?status=active&limit=10" # Detalle de un mercado curl "http://localhost:7860/api/v1/markets/559677" # Señal AI del mercado curl "http://localhost:7860/api/v1/markets/559677/signal" ``` --- ## Códigos de error relevantes | HTTP | Código | Cuándo | |---|---|---| | `400` | `VALIDATION_ERROR` | Parámetro inválido (ej. `limit` > 100) | | `404` | `NOT_FOUND` | ID de mercado no existe en DB | | `500` | `INTERNAL` | Error inesperado del servidor | Los endpoints de markets **no requieren autenticación** — son datos públicos.