-
Notifications
You must be signed in to change notification settings - Fork 55
/
order.go
121 lines (108 loc) 路 3.1 KB
/
order.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
package types
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
utils "github.com/crescent-network/crescent/v5/types"
"github.com/crescent-network/crescent/v5/x/liquidity/amm"
)
// OrderDirectionFromAMM converts amm.OrderDirection to liquidity module's
// OrderDirection.
func OrderDirectionFromAMM(dir amm.OrderDirection) OrderDirection {
switch dir {
case amm.Buy:
return OrderDirectionBuy
case amm.Sell:
return OrderDirectionSell
default:
panic(fmt.Errorf("invalid order direction: %s", dir))
}
}
type UserOrder struct {
*amm.BaseOrder
Orderer sdk.AccAddress
OrderId uint64
BatchId uint64
OfferCoinDenom, DemandCoinDenom string
}
// NewUserOrder returns a new user order.
func NewUserOrder(order Order) *UserOrder {
var dir amm.OrderDirection
var amt sdk.Int
switch order.Direction {
case OrderDirectionBuy:
dir = amm.Buy
utils.SafeMath(func() {
amt = sdk.MinInt(
order.OpenAmount,
order.RemainingOfferCoin.Amount.ToDec().QuoTruncate(order.Price).TruncateInt(),
)
}, func() {
amt = order.OpenAmount
})
case OrderDirectionSell:
dir = amm.Sell
amt = order.OpenAmount
}
return &UserOrder{
BaseOrder: amm.NewBaseOrder(dir, order.Price, amt, order.RemainingOfferCoin.Amount),
Orderer: order.GetOrderer(),
OrderId: order.Id,
BatchId: order.BatchId,
OfferCoinDenom: order.OfferCoin.Denom,
DemandCoinDenom: order.ReceivedCoin.Denom,
}
}
func (order *UserOrder) GetBatchId() uint64 {
return order.BatchId
}
func (order *UserOrder) HasPriority(other amm.Order) bool {
if !order.Amount.Equal(other.GetAmount()) {
return order.BaseOrder.HasPriority(other)
}
switch other := other.(type) {
case *UserOrder:
return order.OrderId < other.OrderId
case *PoolOrder:
return true
default:
panic(fmt.Errorf("invalid order type: %T", other))
}
}
func (order *UserOrder) String() string {
return fmt.Sprintf("UserOrder(%d,%d,%s,%s,%s)",
order.OrderId, order.BatchId, order.Direction, order.Price, order.Amount)
}
type PoolOrder struct {
*amm.BaseOrder
PoolId uint64
ReserveAddress sdk.AccAddress
OfferCoinDenom, DemandCoinDenom string
}
func NewPoolOrder(
poolId uint64, reserveAddr sdk.AccAddress, dir amm.OrderDirection, price sdk.Dec, amt sdk.Int,
offerCoinDenom, demandCoinDenom string) *PoolOrder {
return &PoolOrder{
BaseOrder: amm.NewBaseOrder(dir, price, amt, amm.OfferCoinAmount(dir, price, amt)),
PoolId: poolId,
ReserveAddress: reserveAddr,
OfferCoinDenom: offerCoinDenom,
DemandCoinDenom: demandCoinDenom,
}
}
func (order *PoolOrder) HasPriority(other amm.Order) bool {
if !order.Amount.Equal(other.GetAmount()) {
return order.BaseOrder.HasPriority(other)
}
switch other := other.(type) {
case *UserOrder:
return false
case *PoolOrder:
return order.PoolId < other.PoolId
default:
panic(fmt.Errorf("invalid order type: %T", other))
}
}
func (order *PoolOrder) String() string {
return fmt.Sprintf("PoolOrder(%d,%s,%s,%s)",
order.PoolId, order.Direction, order.Price, order.Amount)
}