source: server/market.go@ 1549dae

main
Last change on this file since 1549dae was ef1c1c7, checked in by Stefan <trsunovstefan@…>, 6 days ago

Wiki docs, phase 6 and phase 7 added

  • Property mode set to 100644
File size: 3.7 KB
Line 
1package main
2
3import (
4 "database/sql"
5 "fmt"
6 "strconv"
7
8 "bp_project/server/db"
9)
10
11// Market represents a trading pair.
12type Market struct {
13 ID string
14 CryptoID string
15 Symbol string
16 Quote string
17}
18
19// ListMarkets prints all active markets, numbered, with their latest price,
20// and returns them in the printed order so a caller can pick one by number.
21func ListMarkets() []Market {
22 rows, err := db.DB.Query(`
23 SELECT m.id, c.id, c.symbol, m.quote_currency,
24 COALESCE(lp.price, 0) AS price
25 FROM markets m
26 JOIN crypto c ON c.id = m.crypto_id
27 LEFT JOIN v_latest_prices lp ON lp.market_id = m.id
28 WHERE m.is_active = true
29 ORDER BY c.symbol`)
30 if err != nil {
31 fmt.Println("Error:", err)
32 return nil
33 }
34 defer rows.Close()
35
36 fmt.Println()
37 fmt.Printf(" %-4s %-8s %-5s %15s\n", "#", "Symbol", "Quote", "Last price")
38 fmt.Println(" -----------------------------------------")
39 var list []Market
40 for rows.Next() {
41 var m Market
42 var price float64
43 if err := rows.Scan(&m.ID, &m.CryptoID, &m.Symbol, &m.Quote, &price); err != nil {
44 fmt.Println("scan error:", err)
45 return nil
46 }
47 list = append(list, m)
48 fmt.Printf(" %-4d %-8s %-5s %15.6f\n", len(list), m.Symbol, m.Quote, price)
49 }
50 return list
51}
52
53// pickNumber reads a 1-based choice from a list of n items.
54func pickNumber(label string, n int) (int, error) {
55 if n == 0 {
56 return 0, fmt.Errorf("Nothing to choose from.")
57 }
58 k, err := strconv.Atoi(prompt(label))
59 if err != nil || k < 1 || k > n {
60 return 0, fmt.Errorf("Invalid choice, enter a number from 1 to %d.", n)
61 }
62 return k - 1, nil
63}
64
65// ChooseMarket lists the active markets and lets the user pick one by its
66// number in the list.
67func ChooseMarket() (*Market, error) {
68 list := ListMarkets()
69 k, err := pickNumber("Market #: ", len(list))
70 if err != nil {
71 return nil, err
72 }
73 return &list[k], nil
74}
75
76// ChooseHolding lists only the markets the user can sell in — cryptos they
77// hold with some quantity still free (not reserved by an open sell order) —
78// with how much is held and free, and lets them pick one by number.
79func ChooseHolding(s *Session) (*Market, error) {
80 rows, err := db.DB.Query(`
81 SELECT m.id, c.id, c.symbol, m.quote_currency,
82 h.quantity, h.quantity - h.reserved_quantity AS free,
83 COALESCE(lp.price, 0) AS price
84 FROM holdings h
85 JOIN crypto c ON c.id = h.crypto_id
86 JOIN markets m ON m.crypto_id = c.id AND m.is_active = true
87 LEFT JOIN v_latest_prices lp ON lp.market_id = m.id
88 WHERE h.user_id = $1
89 AND h.quantity - h.reserved_quantity > 0
90 ORDER BY c.symbol`, s.UserID)
91 if err != nil {
92 return nil, err
93 }
94 defer rows.Close()
95
96 fmt.Println()
97 fmt.Printf(" %-4s %-8s %-5s %12s %12s %15s\n", "#", "Symbol", "Quote", "Held", "Free to sell", "Last price")
98 fmt.Println(" -------------------------------------------------------------------")
99 var list []Market
100 for rows.Next() {
101 var m Market
102 var held, free, price float64
103 if err := rows.Scan(&m.ID, &m.CryptoID, &m.Symbol, &m.Quote, &held, &free, &price); err != nil {
104 return nil, err
105 }
106 list = append(list, m)
107 fmt.Printf(" %-4d %-8s %-5s %12.4f %12.4f %15.6f\n", len(list), m.Symbol, m.Quote, held, free, price)
108 }
109 if len(list) == 0 {
110 return nil, fmt.Errorf("you hold no crypto that is free to sell")
111 }
112 k, err := pickNumber("Holding #: ", len(list))
113 if err != nil {
114 return nil, err
115 }
116 return &list[k], nil
117}
118
119// LatestPrice returns the last traded price on a market.
120func LatestPrice(marketID string) (float64, error) {
121 var price float64
122 err := db.DB.QueryRow(
123 `SELECT price FROM v_latest_prices WHERE market_id = $1`, marketID,
124 ).Scan(&price)
125 if err == sql.ErrNoRows {
126 return 0, fmt.Errorf("no trades yet for this market")
127 }
128 return price, err
129}
Note: See TracBrowser for help on using the repository browser.