| | 1 | = Prototype Implementation |
| | 2 | |
| | 3 | The prototype is a Go command-line application in `server/` that works against |
| | 4 | the `project` schema in PostgreSQL. It implements all seven use cases from |
| | 5 | [UseCaseModel](../P3-UseCaseModel/UseCaseModel.md) — the rubric requires at least three — with |
| | 6 | every database access shown as real, executed SQL. An auxiliary program in |
| | 7 | `bots/` simulates a live market so prices move while the prototype is running. |
| | 8 | |
| | 9 | Build, configure, run and test instructions: [BuildInstructions](BuildInstructions.md). |
| | 10 | |
| | 11 | == Implemented use-cases |
| | 12 | |
| | 13 | || Page | Use-case || Source || |
| | 14 | || [UseCase0001Implementation](UseCase0001Implementation.md) || Register a new account || `server/auth.go` || |
| | 15 | || [UseCase0002Implementation](UseCase0002Implementation.md) || Log in || `server/auth.go` || |
| | 16 | || [UseCase0003Implementation](UseCase0003Implementation.md) || Deposit virtual funds || `server/account.go` || |
| | 17 | || [UseCase0004Implementation](UseCase0004Implementation.md) || Place market BUY order || `server/trade.go` || |
| | 18 | || [UseCase0005Implementation](UseCase0005Implementation.md) || Place market SELL order || `server/trade.go` || |
| | 19 | || [UseCase0006Implementation](UseCase0006Implementation.md) || View portfolio and history || `server/portfolio.go` || |
| | 20 | || [UseCase0007Implementation](UseCase0007Implementation.md) || Manage watchlist || `server/watchlist.go` || |
| | 21 | |
| | 22 | Each page mirrors its P3 use-case page and adds the actual SQL emitted by the Go |
| | 23 | code plus a screenshot of the corresponding run against the live database. |
| | 24 | |
| | 25 | == What the prototype demonstrates about the database design |
| | 26 | |
| | 27 | - **The current price is never stored as a column.** It is always the price of |
| | 28 | the most recent row in `market_trades`, read through the `v_latest_prices` |
| | 29 | view. Both the user's own fills and the bot's simulated trades feed the same |
| | 30 | table, so there is exactly one definition of "the price". |
| | 31 | - **Money movements are transactional.** Buying touches five tables — `orders`, |
| | 32 | `users`, `holdings`, `transactions`, `market_trades` — inside one transaction. |
| | 33 | A failed balance check rolls the whole thing back: after a rejected purchase |
| | 34 | there is no order row, no ledger entry and no holding. This is verified in the |
| | 35 | failure-path tests in [BuildInstructions](BuildInstructions.md). |
| | 36 | - **Constraints do real work.** `UNIQUE (user_id, crypto_id)` on `holdings` is |
| | 37 | what makes the `INSERT … ON CONFLICT DO UPDATE` upsert possible, so the |
| | 38 | weighted-average entry price is recomputed by the database in one statement |
| | 39 | instead of by a read-modify-write in application code. |
| | 40 | - **No identifiers are ever typed.** Markets are listed with their prices before |
| | 41 | any choice is made, and everything else is selected by symbol. |
| | 42 | |
| | 43 | == Known limitations |
| | 44 | |
| | 45 | Deliberately out of scope for a first prototype, and the natural content of the |
| | 46 | later phases: |
| | 47 | |
| | 48 | - Only `market` orders execute. `limit` is accepted by the schema |
| | 49 | (`orders.type`) but the matching logic is not implemented. |
| | 50 | - Passwords are SHA-256 without a salt. Adequate to demonstrate that the |
| | 51 | password itself is never stored; not adequate for real use. A proper |
| | 52 | password hash belongs in P9 (security). |
| | 53 | - Money is handled as `float64` in Go while the database columns are `numeric`. |
| | 54 | All arithmetic that must be exact — the weighted average — is done in SQL for |
| | 55 | that reason, but the Go side would need a decimal type for real use. |
| | 56 | - There is no connection pooling configuration and no explicit isolation level; |
| | 57 | both are P8 topics. |