forked from MixinNetwork/ocean.one
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmarket.go
123 lines (109 loc) · 3.07 KB
/
market.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package persistence
import (
"context"
"fmt"
"sort"
"strings"
"time"
"cloud.google.com/go/spanner"
"github.com/gofrs/uuid"
"google.golang.org/api/iterator"
)
func LastTrade(ctx context.Context, market string) (*Trade, error) {
base, quote := getBaseQuote(market)
if base == "" || quote == "" {
return nil, nil
}
it := Spanner(ctx).Single().Query(ctx, spanner.Statement{
SQL: "SELECT * FROM trades@{FORCE_INDEX=trades_by_base_quote_created_desc} WHERE base_asset_id=@base AND quote_asset_id=@quote ORDER BY base_asset_id,quote_asset_id,created_at DESC",
Params: map[string]interface{}{"base": base, "quote": quote},
})
defer it.Stop()
row, err := it.Next()
if err == iterator.Done {
return nil, nil
} else if err != nil {
return nil, err
}
var t Trade
err = row.ToStruct(&t)
return &t, err
}
func MarketTrades(ctx context.Context, market string, offset time.Time, order string, limit int) ([]*Trade, error) {
txn := Spanner(ctx).ReadOnlyTransaction()
defer txn.Close()
if limit > 100 {
limit = 100
}
cmp := "<"
if order != "DESC" {
order = "ASC"
cmp = ">"
}
base, quote := getBaseQuote(market)
if base == "" || quote == "" {
return nil, nil
}
query := "SELECT trade_id FROM trades@{FORCE_INDEX=trades_by_base_quote_created_%s} WHERE base_asset_id=@base AND quote_asset_id=@quote AND created_at%s=@offset AND liquidity=@liquidity"
query = fmt.Sprintf(query, strings.ToLower(order), cmp)
query = query + " ORDER BY base_asset_id,quote_asset_id,created_at " + order
query = fmt.Sprintf("%s LIMIT %d", query, limit)
params := map[string]interface{}{"base": base, "quote": quote, "offset": offset, "liquidity": TradeLiquidityMaker}
iit := txn.Query(ctx, spanner.Statement{query, params})
defer iit.Stop()
var tradeIds []string
for {
row, err := iit.Next()
if err == iterator.Done {
break
} else if err != nil {
return nil, err
}
var id string
err = row.Columns(&id)
if err != nil {
return nil, err
}
tradeIds = append(tradeIds, id)
}
tit := txn.Query(ctx, spanner.Statement{
SQL: "SELECT * FROM trades WHERE trade_id IN UNNEST(@trade_ids) AND liquidity=@liquidity",
Params: map[string]interface{}{"trade_ids": tradeIds, "liquidity": TradeLiquidityMaker},
})
defer tit.Stop()
var trades []*Trade
for {
row, err := tit.Next()
if err == iterator.Done {
break
} else if err != nil {
return trades, err
}
var t Trade
err = row.ToStruct(&t)
if err != nil {
return trades, err
}
trades = append(trades, &t)
}
if order == "DESC" {
sort.Slice(trades, func(i, j int) bool { return trades[i].CreatedAt.After(trades[j].CreatedAt) })
} else {
sort.Slice(trades, func(i, j int) bool { return trades[i].CreatedAt.Before(trades[j].CreatedAt) })
}
return trades, nil
}
func getBaseQuote(market string) (string, string) {
if len(market) != 73 {
return "", ""
}
base := uuid.FromStringOrNil(market[0:36])
if base.String() == uuid.Nil.String() {
return "", ""
}
quote := uuid.FromStringOrNil(market[37:73])
if quote.String() == uuid.Nil.String() {
return "", ""
}
return base.String(), quote.String()
}