# Workflow: init bazy + app stack + ingest przez API (tokeny + basic auth) Docelowy podział na 3 compose’y: 1) `devops/db/docker-compose.yml` → **Postgres/TimescaleDB + Hasura + pgAdmin** (DB stack) 2) `devops/tools/bootstrap/docker-compose.yml` → **one-shot tools** (init SQL + Hasura metadata) 3) `devops/app/docker-compose.yml` → **API + frontend (+ opcjonalny ingestor)** (app stack) ## TL;DR (local, end-to-end) 1) `npm install` 2) DB: `docker compose -f devops/db/docker-compose.yml up -d` 3) Schema/metadata: `docker compose -f devops/tools/bootstrap/docker-compose.yml run --rm db-init` + `docker compose -f devops/tools/bootstrap/docker-compose.yml run --rm hasura-bootstrap` 4) Tokeny: skopiuj `tokens/*.example.json` → `tokens/*.json` + ustaw RPC w `tokens/heliusN.json` (albo po prostu `cp tokens/helius.json tokens/heliusN.json`) 5) API: `docker compose -f devops/app/docker-compose.yml up -d api` + `curl -sS http://localhost:8787/healthz` 6) Tokeny (revocable): `npm run token:api -- --scopes write --out tokens/alg.json` + `npm run token:api -- --scopes read --out tokens/read.json` 7) Frontend: `docker compose -f devops/app/docker-compose.yml up -d frontend` 8) Ingestor: `docker compose -f devops/app/docker-compose.yml --profile ingest up -d` Uwaga: ceny w `drift_ticks` są `NUMERIC` (Hasura zwykle zwraca/oczekuje stringów dla `numeric`); `trade-api` normalizuje je do `number` w `/v1/chart`. ## Migracja (bez kasowania danych) Szybka sekwencja do migracji schematu + odpalenia stacka (bez `down -v`) jest w `r1.txt`. ## Wersjonowanie API/UI (v2, v3...) bez ruszania DB/Hasury Cel: uruchamiasz nową wersję `api+frontend(+ingestor)` równolegle, na **nowych tabelach**, na **nowych portach**, a potem robisz cutover ingestora. Konwencja: - v1: tabela `drift_ticks`, funkcja `get_drift_candles`, porty `8787/8081` - vN: tabela `drift_ticks_vN`, funkcja `get_drift_candles_vN`, porty `8787+(N-1)` i `8081+(N-1)` - wspólne: Postgres/Hasura/pgAdmin + `api_tokens` (tokeny) zostają bez wersjonowania Skrypty: `scripts/ops/` (tworzą też env w `devops/versions/vN.env`) - `bash scripts/ops/version-init.sh 2` migracja DB + create `drift_ticks_v2` + track w Hasurze - `bash scripts/ops/version-up.sh 2` start `api+frontend` v2 (host: `8788/8082`) - `bash scripts/ops/version-ingestor-up.sh 2` start ingestor v2 (pisze do v2 API → `drift_ticks_v2`) - `bash scripts/ops/version-cutover.sh 1 2` start v2 ingestor, potem stop v1 ingestor - `bash scripts/ops/version-backfill.sh 1 2` backfill ALL: `drift_ticks` → `drift_ticks_v2` - `bash scripts/ops/version-down.sh 1` usuń stare kontenery v1 (DB bez zmian) - `bash scripts/ops/version-check.sh 2` healthz/ticks/chart dla v2 ## Reset (UWAGA: kasuje dane z bazy) Jeśli uruchomisz `docker compose -f devops/db/docker-compose.yml down -v`, Postgres/Timescale traci cały wolumen (czyli rekordy z `drift_ticks`). ## Dane logowania (dev) - Postgres: `postgres://admin:pass@localhost:5432/crypto` - Hasura: `http://localhost:8080` (admin secret: `tokens/hasura.json` → `adminSecret`) - pgAdmin: `http://localhost:5050` (login: `admin@example.com`, hasło: `admin`) - Frontend UI: `http://localhost:8081` (basic auth: `tokens/frontend.json` → `username`/`password`) ## 0) Start DB stack Z root repo: ```bash docker compose -f devops/db/docker-compose.yml up -d ``` Ten krok tworzy wspólną sieć Dockera `trade-net`, przez którą app stack łączy się do Hasury. ## 1) Init / upgrade schematu bazy (idempotent) Użyj zwłaszcza, jeśli masz istniejący wolumen Postgresa: ```bash docker compose -f devops/tools/bootstrap/docker-compose.yml run --rm db-init ``` To jest też krok, który trzeba odpalić po zmianach w `devops/db/initdb/001_init.sql` (np. migracja `DOUBLE PRECISION` → `NUMERIC`). ## 2) Hasura metadata bootstrap (track tabel + permissions) ```bash docker compose -f devops/tools/bootstrap/docker-compose.yml run --rm hasura-bootstrap ``` ## 3) Skonfiguruj API + frontend Utwórz lokalne pliki (gitignored) w `tokens/`: - `tokens/hasura.json` z `tokens/hasura.example.json` (URL + admin secret dla Hasury, używane przez `trade-api`) - `tokens/api.json` z `tokens/api.example.json` (sekret admina do tworzenia/revoke tokenów API) - `tokens/frontend.json` z `tokens/frontend.example.json` (basic auth do UI) - `tokens/heliusN.json` (RPC dla Drift; albo `heliusApiKey`, albo pełny `rpcUrl`) Jeśli odpalasz lokalne skrypty (`npm run token:*`, `npm run ingest:*`) wykonaj też: ```bash npm install ``` ## 4) Start API (trade-api) ```bash docker compose -f devops/app/docker-compose.yml up -d api ``` - API: `http://localhost:8787` Healthcheck: ```bash curl -sS http://localhost:8787/healthz ``` ## 5) Wygeneruj tokeny (revocable) **Write token** dla ingestora (domyślnie zapisuje do `tokens/alg.json`): ```bash npm run token:api -- --name algo1 --scopes write --out tokens/alg.json ``` Jeśli wcześniej uruchomiłeś `frontend` bez pliku `tokens/read.json`, Docker mógł utworzyć katalog `tokens/read.json`. Usuń go przed generacją tokena: ```bash rm -rf tokens/read.json ``` **Read token** dla frontendu (proxy wstrzykuje go serwerowo; nie trafia do JS): ```bash npm run token:api -- --name reader-ui --scopes read --out tokens/read.json ``` ## 6) Start frontend (UI) ```bash docker compose -f devops/app/docker-compose.yml up -d frontend ``` - Frontend: `http://localhost:8081` (basic auth) Dev mode (Vite + proxy `/api` z tokenem z `tokens/read.json`): ```bash npm run visualizer:dev ``` - Dev UI: `http://localhost:5173` ## 7) Uruchom kontener ingestora, który wysyła ticki do API W ramach app stack (profil `ingest`): ```bash docker compose -f devops/app/docker-compose.yml --profile ingest up -d ``` Alternatywnie (bez Dockera) możesz odpalić ingest lokalnie: ```bash npm run ingest:oracle -- --ingest-via api --market-name PUMP-PERP --interval-ms 1000 --source drift_oracle ``` Wymaga: `tokens/heliusN.json` (RPC) + `tokens/alg.json` (write token do API) + działającego `trade-api`. Override (przykład): ```bash MARKET_NAME=PUMP-PERP INTERVAL_MS=250 SOURCE=drift_oracle \ docker compose -f devops/app/docker-compose.yml --profile ingest up -d ``` ## 8) Sprawdź, czy rekordy wpadają Przez API (wymaga read tokena): ```bash curl -sS "http://localhost:8787/v1/ticks?symbol=PUMP-PERP&limit=5" \ -H "Authorization: Bearer $(node -p 'require("./tokens/read.json").token')" ``` W UI: `http://localhost:8081` → wykres powinien się aktualizować. Sprawdź agregacje + wskaźniki (candles + indicators z backendu): ```bash curl -sS "http://localhost:8787/v1/chart?symbol=PUMP-PERP&tf=1m&limit=120" \ -H "Authorization: Bearer $(node -p 'require("./tokens/read.json").token')" ``` ## Checklist (copy/paste) - `npm install` zainstaluj zależności do `npm run token:*` / `npm run ingest:*` - `cp tokens/hasura.example.json tokens/hasura.json` skopiuj konfigurację Hasury - `cp tokens/api.example.json tokens/api.json` skopiuj konfigurację API (adminSecret) - `cp tokens/frontend.example.json tokens/frontend.json` skopiuj basic auth do UI - `cp tokens/helius.json tokens/heliusN.json` ustaw RPC dla Drift (fallback jest też `tokens/helius.json`) - `docker compose -f devops/db/docker-compose.yml up -d` uruchom Postgres/Timescale + Hasura + pgAdmin - `docker compose -f devops/tools/bootstrap/docker-compose.yml run --rm db-init` zastosuj schemat PG (tabele/indeksy/hypertable) - `docker compose -f devops/tools/bootstrap/docker-compose.yml run --rm hasura-bootstrap` track tabel + permissions w Hasurze - `docker compose -f devops/app/docker-compose.yml up -d api` uruchom API - `curl -sS http://localhost:8787/healthz` sprawdź czy API działa - `npm run token:api -- --name algo1 --scopes write --out tokens/alg.json` wygeneruj write token dla ingestora - `npm run token:api -- --name reader-ui --scopes read --out tokens/read.json` wygeneruj read token dla UI/curl - `docker compose -f devops/app/docker-compose.yml up -d frontend` uruchom frontend - `docker compose -f devops/app/docker-compose.yml --profile ingest up -d` uruchom ingestora (Drift → API → DB) - `curl -sS "http://localhost:8787/v1/ticks?symbol=PUMP-PERP&limit=5" -H "Authorization: Bearer $(node -p 'require("./tokens/read.json").token')"` sprawdź czy ticki wpadają - `curl -sS "http://localhost:8787/v1/chart?symbol=PUMP-PERP&tf=1m&limit=120" -H "Authorization: Bearer $(node -p 'require("./tokens/read.json").token')"` sprawdź candles + wskaźniki z backendu