| 1 | = Prototype Implementation =
|
|---|
| 2 |
|
|---|
| 3 | The prototype is a Go command-line application in
|
|---|
| 4 | [https://github.com/StefanTrsunov/bp/tree/main/server server/] that works against the `project`
|
|---|
| 5 | schema in PostgreSQL. It implements all seven use cases from
|
|---|
| 6 | [https://github.com/StefanTrsunov/bp/blob/main/docs/P3-UseCaseModel/UseCaseModel.md UseCaseModel]
|
|---|
| 7 | – the rubric requires at least three – with every database access shown as real, executed SQL.
|
|---|
| 8 | An auxiliary program in [https://github.com/StefanTrsunov/bp/tree/main/bots bots/] simulates a
|
|---|
| 9 | live market so prices move while the prototype is running.
|
|---|
| 10 |
|
|---|
| 11 | Build, configure, run and test instructions:
|
|---|
| 12 | [https://github.com/StefanTrsunov/bp/blob/main/docs/P4-Prototype/BuildInstructions.md BuildInstructions].
|
|---|
| 13 |
|
|---|
| 14 | All pages listed below, together with the screenshots of each run, are kept in the project's
|
|---|
| 15 | GitHub repository, [https://github.com/StefanTrsunov/bp StefanTrsunov/bp], under
|
|---|
| 16 | `docs/P4-Prototype/`.
|
|---|
| 17 |
|
|---|
| 18 | == Implemented use-cases ==
|
|---|
| 19 |
|
|---|
| 20 | ||=Page=||=Use-case=||=Source=||
|
|---|
| 21 | ||[https://github.com/StefanTrsunov/bp/blob/main/docs/P4-Prototype/UseCase0001Implementation.md UseCase0001Implementation]||Register a new account||[https://github.com/StefanTrsunov/bp/blob/main/server/auth.go server/auth.go]||
|
|---|
| 22 | ||[https://github.com/StefanTrsunov/bp/blob/main/docs/P4-Prototype/UseCase0002Implementation.md UseCase0002Implementation]||Log in||[https://github.com/StefanTrsunov/bp/blob/main/server/auth.go server/auth.go]||
|
|---|
| 23 | ||[https://github.com/StefanTrsunov/bp/blob/main/docs/P4-Prototype/UseCase0003Implementation.md UseCase0003Implementation]||Deposit virtual funds||[https://github.com/StefanTrsunov/bp/blob/main/server/account.go server/account.go]||
|
|---|
| 24 | ||[https://github.com/StefanTrsunov/bp/blob/main/docs/P4-Prototype/UseCase0004Implementation.md UseCase0004Implementation]||Place market BUY order||[https://github.com/StefanTrsunov/bp/blob/main/server/trade.go server/trade.go]||
|
|---|
| 25 | ||[https://github.com/StefanTrsunov/bp/blob/main/docs/P4-Prototype/UseCase0005Implementation.md UseCase0005Implementation]||Place market SELL order||[https://github.com/StefanTrsunov/bp/blob/main/server/trade.go server/trade.go]||
|
|---|
| 26 | ||[https://github.com/StefanTrsunov/bp/blob/main/docs/P4-Prototype/UseCase0006Implementation.md UseCase0006Implementation]||View portfolio and history||[https://github.com/StefanTrsunov/bp/blob/main/server/portfolio.go server/portfolio.go]||
|
|---|
| 27 | ||[https://github.com/StefanTrsunov/bp/blob/main/docs/P4-Prototype/UseCase0007Implementation.md UseCase0007Implementation]||Manage watchlist||[https://github.com/StefanTrsunov/bp/blob/main/server/watchlist.go server/watchlist.go]||
|
|---|
| 28 |
|
|---|
| 29 | Each page mirrors its P3 use-case page and adds the actual SQL emitted by the Go code plus a
|
|---|
| 30 | screenshot of the corresponding run against the live database. The screenshots are committed
|
|---|
| 31 | alongside the pages, in
|
|---|
| 32 | [https://github.com/StefanTrsunov/bp/tree/main/docs/P4-Prototype/screenshots docs/P4-Prototype/screenshots/].
|
|---|
| 33 |
|
|---|
| 34 | == What the prototype demonstrates about the database design ==
|
|---|
| 35 |
|
|---|
| 36 | * '''The current price is never stored as a column.''' It is always the price of the most recent
|
|---|
| 37 | row in `market_trades`, read through the `v_latest_prices` view. Both the user's own fills and
|
|---|
| 38 | the bot's simulated trades feed the same table, so there is exactly one definition of "the
|
|---|
| 39 | price".
|
|---|
| 40 | * '''Money movements are transactional.''' Buying touches five tables – `orders`, `users`,
|
|---|
| 41 | `holdings`, `transactions`, `market_trades` – inside one transaction. A failed balance check
|
|---|
| 42 | rolls the whole thing back: after a rejected purchase there is no order row, no ledger entry
|
|---|
| 43 | and no holding. This is verified in the failure-path tests in
|
|---|
| 44 | [https://github.com/StefanTrsunov/bp/blob/main/docs/P4-Prototype/BuildInstructions.md BuildInstructions].
|
|---|
| 45 | * '''Constraints do real work.''' `UNIQUE (user_id, crypto_id)` on `holdings` is what makes the
|
|---|
| 46 | `INSERT … ON CONFLICT DO UPDATE` upsert possible, so the weighted-average entry price is
|
|---|
| 47 | recomputed by the database in one statement instead of by a read-modify-write in application
|
|---|
| 48 | code. `CHECK (reserved_quantity >= 0 AND reserved_quantity <= quantity)` is the same idea
|
|---|
| 49 | applied to the sell path: an inconsistent reservation is impossible at the database level, not
|
|---|
| 50 | just something `trade.go` is careful about.
|
|---|
| 51 | * '''Selling reserves before it removes.''' A sell order locks the holding row, reserves the
|
|---|
| 52 | quantity being sold, then settles by removing it — see
|
|---|
| 53 | [UseCase0005Implementation](UseCase0005Implementation.md). Two sell orders placed at the same
|
|---|
| 54 | instant for more than the available quantity are serialised correctly by `SELECT ... FOR
|
|---|
| 55 | UPDATE`, not just by luck of everything happening in one CLI process; this is demonstrated
|
|---|
| 56 | there with two concurrent processes.
|
|---|
| 57 | * '''No identifiers are ever typed.''' Markets are listed with their prices before any choice is
|
|---|
| 58 | made, and everything else is selected by symbol.
|
|---|
| 59 |
|
|---|
| 60 | == Known limitations ==
|
|---|
| 61 |
|
|---|
| 62 | Deliberately out of scope for a first prototype, and the natural content of the later phases:
|
|---|
| 63 |
|
|---|
| 64 | * Only `market` orders execute. `limit` is accepted by the schema (`orders.type`) but the
|
|---|
| 65 | matching logic is not implemented.
|
|---|
| 66 | * Passwords are SHA-256 without a salt. Adequate to demonstrate that the password itself is
|
|---|
| 67 | never stored; not adequate for real use. A proper password hash belongs in P9 (security).
|
|---|
| 68 | * Money is handled as `float64` in Go while the database columns are `numeric`. All arithmetic
|
|---|
| 69 | that must be exact – the weighted average – is done in SQL for that reason, but the Go side
|
|---|
| 70 | would need a decimal type for real use.
|
|---|
| 71 | * There is no connection pooling configuration and no explicit isolation level; both are P8
|
|---|
| 72 | topics.
|
|---|
| 73 | * Reservation only ever lives inside one transaction, because only market orders (which settle
|
|---|
| 74 | immediately) exist. A real limit-order matcher would leave `holdings.reserved_quantity` set
|
|---|
| 75 | and `orders.status = 'open'` between two separate commits, and would need a way to cancel an
|
|---|
| 76 | order to release the reservation — neither is implemented, since nothing in the prototype
|
|---|
| 77 | produces an order that stays open.
|
|---|
| 78 |
|
|---|
| 79 | == AI usage ==
|
|---|
| 80 |
|
|---|
| 81 | AI was used in this phase and is logged in full, per the course rule for P1 onward.
|
|---|
| 82 |
|
|---|
| 83 | * '''Phase log:'''
|
|---|
| 84 | [https://github.com/StefanTrsunov/bp/blob/main/docs/P4-Prototype/PrototypeImplementationAIUsage.md PrototypeImplementationAIUsage.md]
|
|---|
| 85 | – service used, the bugs found and fixed, the test evidence, and what I decided myself.
|
|---|
| 86 | * '''Full conversation transcript:'''
|
|---|
| 87 | [https://github.com/StefanTrsunov/bp/blob/main/docs/P1-ConceptualModel/ERModelAIUsage.md ERModelAIUsage.md]
|
|---|
| 88 | – the same conversation produced the P1–P4 artefacts, so the complete prompt/response log is
|
|---|
| 89 | kept in one place. Direct links:
|
|---|
| 90 | [https://github.com/StefanTrsunov/bp/blob/main/docs/P1-ConceptualModel/ERModelAIUsage.md#session-1--2026-04-21 Session 1 – 2026-04-21],
|
|---|
| 91 | [https://github.com/StefanTrsunov/bp/blob/main/docs/P1-ConceptualModel/ERModelAIUsage.md#session-2--2026-08-06--2026-08-07 Session 2 – 2026-08-06/07],
|
|---|
| 92 | [https://github.com/StefanTrsunov/bp/blob/main/docs/P1-ConceptualModel/ERModelAIUsage.md#session-3--2026-09-16 Session 3 – 2026-09-16].
|
|---|
| 93 |
|
|---|
| 94 | '''Service:''' Claude Code (Anthropic), https://claude.com/claude-code – Claude subscription,
|
|---|
| 95 | model Claude Opus 4.7 (1M context) in sessions 1–2, Claude Sonnet 5 in session 3.
|
|---|
| 96 |
|
|---|
| 97 | '''In short:''' session 1 rewrote the existing Chi/HTTP backend as the CLI prototype covering
|
|---|
| 98 | UC0001–UC0007 and added the market bot. Session 2 was a review pass I asked for, which found and
|
|---|
| 99 | fixed three bugs – a path-resolution bug that made the documented build instructions fail, an
|
|---|
| 100 | infinite loop at end of input, and an error check in the wrong order that misreported database
|
|---|
| 101 | failures as "Insufficient holding" – and replaced the read-modify-write holding update with a
|
|---|
| 102 | single `INSERT … ON CONFLICT DO UPDATE`. Session 3 added `holdings.reserved_quantity` and changed
|
|---|
| 103 | `trade.go`'s sell path to reserve crypto before removing it, closing a gap where two sell orders
|
|---|
| 104 | could be granted the same units; see
|
|---|
| 105 | [PrototypeImplementationAIUsage](PrototypeImplementationAIUsage.md#session-3--2026-09-16).
|
|---|