-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
market.go
147 lines (128 loc) · 3.9 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package types
import (
"errors"
"fmt"
"strings"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
ununifitypes "github.com/UnUniFi/chain/types"
)
// NewMarket returns a new Market
func NewMarket(id, base, quote string, oracles []sdk.AccAddress, active bool) Market {
return Market{
MarketId: id,
BaseAsset: base,
QuoteAsset: quote,
Oracles: ununifitypes.StringAccAddresses(oracles),
Active: active,
}
}
// Validate performs a basic validation of the market params
func (m Market) Validate() error {
if strings.TrimSpace(m.MarketId) == "" {
return errors.New("market id cannot be blank")
}
if err := sdk.ValidateDenom(m.BaseAsset); err != nil {
return fmt.Errorf("invalid base asset: %w", err)
}
if err := sdk.ValidateDenom(m.QuoteAsset); err != nil {
return fmt.Errorf("invalid quote asset: %w", err)
}
seenOracles := make(map[string]bool)
for i, oracle := range m.Oracles {
if oracle.AccAddress().Empty() {
return fmt.Errorf("oracle %d is empty", i)
}
if seenOracles[oracle.AccAddress().String()] {
return fmt.Errorf("duplicated oracle %s", oracle)
}
seenOracles[oracle.AccAddress().String()] = true
}
return nil
}
// Markets array type for oracle
type Markets []Market
// Validate checks if all the markets are valid and there are no duplicated
// entries.
func (ms Markets) Validate() error {
seenMarkets := make(map[string]bool)
for _, m := range ms {
if seenMarkets[m.MarketId] {
return fmt.Errorf("duplicated market %s", m.MarketId)
}
if err := m.Validate(); err != nil {
return err
}
seenMarkets[m.MarketId] = true
}
return nil
}
// String implements fmt.Stringer
func (ms Markets) String() string {
out := "Markets:\n"
for _, m := range ms {
out += fmt.Sprintf("%s\n", m.String())
}
return strings.TrimSpace(out)
}
// NewCurrentPrice returns an instance of CurrentPrice
func NewCurrentPrice(marketID string, price sdk.Dec) CurrentPrice {
return CurrentPrice{MarketId: marketID, Price: price}
}
// CurrentPrices type for an array of CurrentPrice
type CurrentPrices []CurrentPrice
// NewPostedPrice returns a new PostedPrice
func NewPostedPrice(marketID string, oracle sdk.AccAddress, price sdk.Dec, expiry time.Time) PostedPrice {
return PostedPrice{
MarketId: marketID,
OracleAddress: oracle.Bytes(),
Price: price,
Expiry: expiry,
}
}
// Validate performs a basic check of a PostedPrice params.
func (pp PostedPrice) Validate() error {
if strings.TrimSpace(pp.MarketId) == "" {
return errors.New("market id cannot be blank")
}
if pp.OracleAddress.AccAddress().Empty() {
return errors.New("oracle address cannot be empty")
}
if pp.Price.IsNegative() {
return fmt.Errorf("posted price cannot be negative %s", pp.Price)
}
if pp.Expiry.Unix() <= 0 {
return errors.New("expiry time cannot be zero")
}
return nil
}
// PostedPrices type for an array of PostedPrice
type PostedPrices []PostedPrice
// Validate checks if all the posted prices are valid and there are no duplicated
// entries.
func (pps PostedPrices) Validate() error {
seenPrices := make(map[string]bool)
for _, pp := range pps {
if pp.OracleAddress != nil && seenPrices[pp.MarketId+pp.OracleAddress.AccAddress().String()] {
return fmt.Errorf("duplicated posted price for marked id %s and oracle address %s", pp.MarketId, pp.OracleAddress)
}
if err := pp.Validate(); err != nil {
return err
}
seenPrices[pp.MarketId+pp.OracleAddress.AccAddress().String()] = true
}
return nil
}
// String implements fmt.Stringer
func (ps PostedPrices) String() string {
out := "Posted Prices:\n"
for _, p := range ps {
out += fmt.Sprintf("%s\n", p.String())
}
return strings.TrimSpace(out)
}
// SortDecs provides the interface needed to sort sdk.Dec slices
type SortDecs []sdk.Dec
func (a SortDecs) Len() int { return len(a) }
func (a SortDecs) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a SortDecs) Less(i, j int) bool { return a[i].LT(a[j]) }