Files
miti99bot/plans/260415-1010-d1-cron-infra/phase-03-trading-history.md

2.7 KiB

Phase 03 — Trading Trade History

Priority: P1 Status: Complete Depends on: Phase 01

Overview

Persist every buy/sell in trading_trades table. Add /history [n] command to show last N trades for the caller (default 10, max 50).

Requirements

Functional

  • Every successful buy/sell inserts a row: (id, user_id, symbol, side, qty, price_vnd, ts).
  • /history → last 10 trades (newest first).
  • /history 25 → last 25 (clamp 1..50).
  • Rendered as compact table (HTML-escaped).
  • No inline cap enforcement — cleanup cron (Phase 04) handles it.

Non-functional

  • Insert is fire-and-forget from the user's perspective but must complete before ctx.reply (use await).
  • Failure to persist does NOT fail the trade — log + swallow (portfolio KV is source of truth for positions).

Architecture

src/modules/trading/
├── index.js          # export crons[] + commands[] (unchanged shape, new cron + new command)
├── handlers.js       # buy/sell call recordTrade() after portfolio update
├── history.js        # NEW — recordTrade(), listTrades(), /history handler, format
├── migrations/
│   └── 0001_trades.sql   # NEW

Schema (trading_trades)

CREATE TABLE trading_trades (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  user_id INTEGER NOT NULL,
  symbol TEXT NOT NULL,
  side TEXT NOT NULL CHECK (side IN ('buy','sell')),
  qty INTEGER NOT NULL,
  price_vnd INTEGER NOT NULL,
  ts INTEGER NOT NULL  -- unix ms
);
CREATE INDEX idx_trading_trades_user_ts ON trading_trades(user_id, ts DESC);
CREATE INDEX idx_trading_trades_ts ON trading_trades(ts);  -- for global FIFO trim

Create

  • src/modules/trading/history.js
  • src/modules/trading/migrations/0001_trades.sql
  • tests/modules/trading/history.test.js

Modify

  • src/modules/trading/index.js — register /history command, accept sql in init
  • src/modules/trading/handlers.js — call recordTrade() on buy/sell

Todo List

  • Migration SQL
  • recordTrade(sql, { userId, symbol, side, qty, priceVnd })
  • listTrades(sql, userId, n)
  • /history command handler + HTML formatter
  • Wire into buy/sell handlers
  • Tests (Miniflare D1): record + list + max-cap clamp

Success Criteria

  • Buy + sell produce rows in trading_trades.
  • /history returns last 10 newest-first.
  • /history 50 returns 50. /history 999 clamps to 50. /history 0 falls back to default.
  • Persistence failure is logged but does not break the trade reply.

Risks

  • D1 write latency inside a user-facing handler — measured in tests; if >300ms, consider ctx.waitUntil(insert) non-blocking.

Next Steps

  • Phase 04 adds the retention cron consuming this table.