Commit Graph
33 Commits
Author SHA1 Message Date
magnusandClaude Opus 4.6 bba9652ced Add datetime field to kraken-hour and kraken-minute API responses
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:41:52 +01:00
magnusandClaude Opus 4.6 b6c8745a86 Add /api/kraken-minute endpoint and limit kraken-hour to 24 rows
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:37:00 +01:00
magnusandClaude Opus 4.6 42454646bb Add /api/kraken-hour endpoint returning last 60 hourly candles
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:33:08 +01:00
magnusandClaude Opus 4.6 44bb9a68d4 Add OHLC values to Kraken minute poller log output
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:18:05 +01:00
magnusandClaude Opus 4.6 ae65ea3722 Show human-readable timestamps in Kraken minute poller logs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:14:35 +01:00
magnusandClaude Opus 4.6 f27c198634 Limit minute poller to last 5 candles after initial fetch
Reduces unnecessary upserts on each 15-second poll cycle by only
processing the 5 most recent candles from Kraken's response.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:09:24 +01:00
magnusandClaude Opus 4.6 b49e8afd59 Add kraken_minute table with 15-second polling
1-minute OHLC candles from Kraken, polled every 15 seconds to keep the
in-progress candle fresh. Unlike hourly/daily pollers, this one keeps
the last candle and upserts it as it updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:06:36 +01:00
magnusandClaude Opus 4.6 747c834e6a Add KRAKEN_ENABLED flag to disable Kraken pollers in local dev
Same pattern as BINANCE_ENABLED and STRIKE_ENABLED. Prevents local
dev from fetching external pricing data when pointed at btcprod.
Docker explicitly sets KRAKEN_ENABLED=true.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:45:10 +01:00
magnusandClaude Opus 4.6 8b5c1faeaa Add deposits rebuild endpoint and fix date serialization
Add POST /api/deposits/rebuild to re-project all bank_to_exchange events.
Fix date-off-by-one by converting java.sql.Date to LocalDate via
ReadableColumn and serializing with Jackson JavaTimeModule.
Sort all event/deposit queries by occurred_at, id.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 17:30:43 +01:00
magnusandClaude Opus 4.6 96d12f170b Change events.occurred_at from TIMESTAMPTZ to DATE
Make date required, remove default. Simplifies date handling
throughout the controller.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:04:24 +01:00
magnusandClaude Opus 4.6 130815e32f Add BINANCE_ENABLED and STRIKE_ENABLED env flags
Skip live WebSocket/API connections when set to false.
Defaults to true so Docker keeps fetching.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:54:50 +01:00
magnusandClaude Opus 4.6 793c63927c Add wallet_type column to distinguish exchanges from wallets
Exchanges (can receive bank deposits) vs wallets (cold storage only).
Supports ?type= filter on GET /api/wallets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:48:41 +01:00
magnusandClaude Opus 4.6 174ea24786 Add deposits read table (CQRS projection from bank_to_exchange events)
Project each bank_to_exchange event into a denormalized deposits table
with pre-computed EUR, DKK, and USD amounts using Frankfurter currency
rates. Replaces the aggregate get-deposit-totals query.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 12:52:32 +01:00
magnusandClaude Opus 4.6 0446d928e6 Add deposit totals API endpoint
GET /api/deposits/totals returns fiat deposited per exchange per currency
from bank_to_exchange events, aggregated via SQL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 12:32:05 +01:00
magnusandClaude Opus 4.6 5874952115 Add event-sourced wallet and transaction tracking system
Wallets table with 7 seeded wallets, events table for three transaction
types (bank_to_exchange, exchange_to_wallet, wallet_to_wallet). Balances
computed from event credits/debits in sats. REST endpoints for CRUD.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:30:48 +01:00
magnusandClaude Opus 4.6 e61f38d4f3 Add GET /api/currencies/:date endpoint for historical EUR/DKK rates
Returns rates for a given date: today uses latest DB row, past dates
check DB first then fetch from Frankfurter and persist for caching.
Future dates and invalid formats return 400.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 12:36:22 +01:00
magnusandClaude Opus 4.6 11a1fc6b8f Persist Frankfurter EUR/DKK rates in currencies table
Store daily exchange rates in PostgreSQL with EUR/DKK cross rate.
Seed rates atom from DB on startup so WebSocket works immediately
even if Frankfurter is unreachable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 12:16:53 +01:00
magnusandClaude Opus 4.6 146c3a4788 Add Strike quote endpoint for real sats price with fee-adjusted amount
Use POST /v1/currency-exchange-quotes to get actual buy price including
spread, matching the Strike app. Fee is cached daily to calculate the
pre-fee amount from the configured total (default 55 EUR). Store
quote_sats in the strike_price DB table.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 11:42:35 +01:00
magnusandClaude Opus 4.6 3e5fd490b4 Move HTML rendering to btcprice, send raw JSON over both WebSockets
Price and Strike WebSockets now emit JSON instead of HTML fragments.
Added Strike WebSocket endpoint and wired strike/ticker into API routes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:18:48 +01:00
magnus c786b01679 Ignore affald.txt 2026-03-06 09:17:29 +01:00
magnusandClaude Opus 4.6 8125b4a743 Rename shared network to btc-network, remove default network
- All services use btc-network exclusively
- Increase Frankfurter retry to 12x10s for cold start resilience

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 09:10:56 +01:00
magnusandClaude Opus 4.6 dbf19566e8 Add Strike ticker poller, Docker .env config, and Frankfurter retry logic
- Poll Strike API every 10s, store all rates as JSONB in strike_price table
- Move Docker env vars to .env file, use shared network for cross-project communication
- Add startup retry (5x 5s) for Frankfurter poller to handle container race condition

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 08:50:21 +01:00
magnusandClaude Opus 4.6 26420fd6ec Use idiomatic undertow/websocket maps instead of raw WebSocket API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 07:50:55 +01:00
magnusandClaude Opus 4.6 faad73c4ef Use Danish number formatting for all prices and rates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 15:03:17 +01:00
magnusandClaude Opus 4.6 1a22cc3b02 Enlarge EUR/DKK converted prices and show exchange rates below
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:51:38 +01:00
magnusandClaude Opus 4.6 46666aa994 Fix Frankfurter integration: require namespace, use v1 API, show converted BTC prices
- Require frankfurter.rates namespace in core.clj so Integrant can find it
- Use /v1/ prefix for self-hosted Frankfurter API
- Display BTC price converted to EUR and DKK instead of raw exchange rates
- Remove unused host port mapping for Frankfurter container

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:43:19 +01:00
magnusandClaude Opus 4.6 7d6ca3911f Add Frankfurter EUR/DKK rate polling and include rates in WebSocket stream
Polls self-hosted Frankfurter API hourly for USD-based EUR and DKK exchange
rates. Both the WebSocket HTML fragments and the /api/price/latest JSON
endpoint now include the currency rates alongside BTC price.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:22:24 +01:00
magnusandClaude Opus 4.6 39ec47b5e1 Add self-hosted Frankfurter currency exchange rate service to docker-compose
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:14:55 +01:00
magnusandClaude Opus 4.6 991d520b5d Fix WebSocket price stream by guarding nil responses from ring-defaults
ring-defaults middleware (wrap-content-type, wrap-xss-protection) was
converting the nil response from the raw WebSocket upgrade handler into
a partial response map (headers only, no status), causing the Undertow
adapter to attempt ending the already-upgraded exchange.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 10:54:52 +01:00
magnusandClaude Opus 4.6 917b020be4 Use HTMX-compatible HTML fragments on WebSocket, fix multi-connection
- WebSocket sends HTML fragments with id="price-display" instead of JSON
  for direct HTMX OOB swap on the client
- Switch from ring-undertow-adapter ws wrapper to raw Undertow WebSocket
  API (proxy) to fix single-connection limitation
- Keep JSON endpoint at /api/price/latest unchanged
- Update CLAUDE.md and README.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:28:24 +01:00
magnusandClaude Opus 4.6 9283826ac4 Replace SSE price stream with WebSocket, use separate Docker port
- Replace SSE endpoint (/api/price/stream) with WebSocket (/api/price/ws)
  using ring-undertow-adapter's built-in WebSocket support
- Change Docker internal port from 4100 to 4101 to avoid conflicts with
  local dev (make run still uses 4100)
- Add free-port.sh utility script

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:32:19 +01:00
magnusandClaude Opus 4.6 6f20cd63c6 Add docker-compose, README, fix SSE dispatch
Use Undertow dispatch for SSE handler to avoid Ring adapter conflict.
Add docker-compose.yml (port 4101 to coexist with local dev on 4100).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:48:54 +01:00
magnusandClaude Opus 4.6 f64aa98b04 Initial commit: btcdata — BTC data backend service
Split from btcprice monolith. Owns DB, migrations, Binance WebSocket,
Kraken OHLC pollers, and exposes a JSON API with SSE price stream.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:07:30 +01:00