-
Notifications
You must be signed in to change notification settings - Fork 55
/
pool.go
147 lines (128 loc) · 4.16 KB
/
pool.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 (
"fmt"
"regexp"
"strconv"
"strings"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
farmingtypes "github.com/crescent-network/crescent/x/farming/types"
"github.com/crescent-network/crescent/x/liquidity/amm"
)
var (
_ amm.OrderSource = (*BasicPoolOrderSource)(nil)
poolCoinDenomRegexp = regexp.MustCompile(`^pool([1-9]\d*)$`)
)
// PoolReserveAddress returns a unique pool reserve account address for each pool.
func PoolReserveAddress(poolId uint64) sdk.AccAddress {
return farmingtypes.DeriveAddress(
AddressType,
ModuleName,
strings.Join([]string{PoolReserveAddressPrefix, strconv.FormatUint(poolId, 10)}, ModuleAddressNameSplitter),
)
}
// NewPool returns a new pool object.
func NewPool(id, pairId uint64) Pool {
return Pool{
Id: id,
PairId: pairId,
ReserveAddress: PoolReserveAddress(id).String(),
PoolCoinDenom: PoolCoinDenom(id),
LastDepositRequestId: 0,
LastWithdrawRequestId: 0,
Disabled: false,
}
}
// PoolCoinDenom returns a unique pool coin denom for a pool.
func PoolCoinDenom(poolId uint64) string {
return fmt.Sprintf("pool%d", poolId)
}
// ParsePoolCoinDenom parses a pool coin denom and returns the pool id.
func ParsePoolCoinDenom(denom string) (poolId uint64, err error) {
chunks := poolCoinDenomRegexp.FindStringSubmatch(denom)
if len(chunks) == 0 {
return 0, fmt.Errorf("%s is not a pool coin denom", denom)
}
poolId, err = strconv.ParseUint(chunks[1], 10, 64)
if err != nil {
return 0, fmt.Errorf("parse pool id: %w", err)
}
return poolId, nil
}
func (pool Pool) GetReserveAddress() sdk.AccAddress {
addr, err := sdk.AccAddressFromBech32(pool.ReserveAddress)
if err != nil {
panic(err)
}
return addr
}
// Validate validates Pool for genesis.
func (pool Pool) Validate() error {
if pool.Id == 0 {
return fmt.Errorf("pool id must not be 0")
}
if pool.PairId == 0 {
return fmt.Errorf("pair id must not be 0")
}
if _, err := sdk.AccAddressFromBech32(pool.ReserveAddress); err != nil {
return fmt.Errorf("invalid reserve address %s: %w", pool.ReserveAddress, err)
}
if err := sdk.ValidateDenom(pool.PoolCoinDenom); err != nil {
return fmt.Errorf("invalid pool coin denom: %w", err)
}
return nil
}
// BasicPoolOrderSource is the order source for a pool which implements
// amm.OrderSource.
type BasicPoolOrderSource struct {
amm.Pool
PoolId uint64
PoolReserveAddress sdk.AccAddress
BaseCoinDenom, QuoteCoinDenom string
}
// NewBasicPoolOrderSource returns a new BasicPoolOrderSource.
func NewBasicPoolOrderSource(
pool amm.Pool, poolId uint64, reserveAddr sdk.AccAddress, baseCoinDenom, quoteCoinDenom string) *BasicPoolOrderSource {
return &BasicPoolOrderSource{
Pool: pool,
PoolId: poolId,
PoolReserveAddress: reserveAddr,
BaseCoinDenom: baseCoinDenom,
QuoteCoinDenom: quoteCoinDenom,
}
}
func (os *BasicPoolOrderSource) BuyOrdersOver(price sdk.Dec) []amm.Order {
amt := os.BuyAmountOver(price)
if amt.IsZero() {
return nil
}
quoteCoin := sdk.NewCoin(os.QuoteCoinDenom, amm.OfferCoinAmount(amm.Buy, price, amt))
return []amm.Order{NewPoolOrder(os.PoolId, os.PoolReserveAddress, amm.Buy, price, amt, quoteCoin, os.BaseCoinDenom)}
}
func (os *BasicPoolOrderSource) SellOrdersUnder(price sdk.Dec) []amm.Order {
amt := os.SellAmountUnder(price)
if amt.IsZero() {
return nil
}
baseCoin := sdk.NewCoin(os.BaseCoinDenom, amt)
return []amm.Order{NewPoolOrder(os.PoolId, os.PoolReserveAddress, amm.Sell, price, amt, baseCoin, os.QuoteCoinDenom)}
}
// MustMarshalPool returns the pool bytes.
// It throws panic if it fails.
func MustMarshalPool(cdc codec.BinaryCodec, pool Pool) []byte {
return cdc.MustMarshal(&pool)
}
// MustUnmarshalPool return the unmarshalled pool from bytes.
// It throws panic if it fails.
func MustUnmarshalPool(cdc codec.BinaryCodec, value []byte) Pool {
pool, err := UnmarshalPool(cdc, value)
if err != nil {
panic(err)
}
return pool
}
// UnmarshalPool returns the pool from bytes.
func UnmarshalPool(cdc codec.BinaryCodec, value []byte) (pool Pool, err error) {
err = cdc.Unmarshal(value, &pool)
return pool, err
}