/
liquidity_pool_deposit.go
155 lines (134 loc) · 4.68 KB
/
liquidity_pool_deposit.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
148
149
150
151
152
153
154
155
//lint:file-ignore U1001 Ignore all unused code, staticcheck doesn't understand testify/suite
package txnbuild
import (
"github.com/diamcircle/go/amount"
"github.com/diamcircle/go/support/errors"
"github.com/diamcircle/go/xdr"
)
// LiquidityPoolDeposit represents the Diamcircle liquidity pool deposit operation. See
// https://developers.diamcircle.org/docs/start/list-of-operations/
type LiquidityPoolDeposit struct {
SourceAccount string
LiquidityPoolID LiquidityPoolId
MaxAmountA string
MaxAmountB string
MinPrice string
MaxPrice string
}
// NewLiquidityPoolDeposit creates a new LiquidityPoolDeposit operation,
// checking the ordering assets so we generate the correct pool id. minPrice,
// and maxPrice are in terms of a/b. Each AssetAmount is a pair of the asset
// with the maximum amount of that asset to deposit.
func NewLiquidityPoolDeposit(
sourceAccount string,
a, b AssetAmount,
minPrice,
maxPrice string,
) (LiquidityPoolDeposit, error) {
if b.Asset.LessThan(a.Asset) {
return LiquidityPoolDeposit{}, errors.New("AssetA must be <= AssetB")
}
poolId, err := NewLiquidityPoolId(a.Asset, b.Asset)
if err != nil {
return LiquidityPoolDeposit{}, err
}
return LiquidityPoolDeposit{
SourceAccount: sourceAccount,
LiquidityPoolID: poolId,
MaxAmountA: a.Amount,
MaxAmountB: b.Amount,
MinPrice: minPrice,
MaxPrice: maxPrice,
}, nil
}
// BuildXDR for LiquidityPoolDeposit returns a fully configured XDR Operation.
func (lpd *LiquidityPoolDeposit) BuildXDR(withMuxedAccounts bool) (xdr.Operation, error) {
xdrLiquidityPoolId, err := lpd.LiquidityPoolID.ToXDR()
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "couldn't build liquidity pool ID XDR")
}
xdrMaxAmountA, err := amount.Parse(lpd.MaxAmountA)
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to parse 'MaxAmountA'")
}
xdrMaxAmountB, err := amount.Parse(lpd.MaxAmountB)
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to parse 'MaxAmountB'")
}
var minPrice, maxPrice price
err = minPrice.parse(lpd.MinPrice)
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to parse 'MinPrice'")
}
err = maxPrice.parse(lpd.MaxPrice)
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to parse 'MaxPrice'")
}
xdrOp := xdr.LiquidityPoolDepositOp{
LiquidityPoolId: xdrLiquidityPoolId,
MaxAmountA: xdrMaxAmountA,
MaxAmountB: xdrMaxAmountB,
MinPrice: minPrice.toXDR(),
MaxPrice: maxPrice.toXDR(),
}
opType := xdr.OperationTypeLiquidityPoolDeposit
body, err := xdr.NewOperationBody(opType, xdrOp)
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to build XDR OperationBody")
}
op := xdr.Operation{Body: body}
if withMuxedAccounts {
SetOpSourceMuxedAccount(&op, lpd.SourceAccount)
} else {
SetOpSourceAccount(&op, lpd.SourceAccount)
}
return op, nil
}
// FromXDR for LiquidityPoolDeposit initializes the txnbuild struct from the corresponding xdr Operation.
func (lpd *LiquidityPoolDeposit) FromXDR(xdrOp xdr.Operation, withMuxedAccounts bool) error {
result, ok := xdrOp.Body.GetLiquidityPoolDepositOp()
if !ok {
return errors.New("error parsing liquidity_pool_deposit operation from xdr")
}
liquidityPoolID, err := liquidityPoolIdFromXDR(result.LiquidityPoolId)
if err != nil {
return errors.New("error parsing LiquidityPoolId in liquidity_pool_deposit operation from xdr")
}
lpd.LiquidityPoolID = liquidityPoolID
lpd.SourceAccount = accountFromXDR(xdrOp.SourceAccount, withMuxedAccounts)
lpd.MaxAmountA = amount.String(result.MaxAmountA)
lpd.MaxAmountB = amount.String(result.MaxAmountB)
if result.MinPrice != (xdr.Price{}) {
lpd.MinPrice = priceFromXDR(result.MinPrice).string()
}
if result.MaxPrice != (xdr.Price{}) {
lpd.MaxPrice = priceFromXDR(result.MaxPrice).string()
}
return nil
}
// Validate for LiquidityPoolDeposit validates the required struct fields. It returns an error if any of the fields are
// invalid. Otherwise, it returns nil.
func (lpd *LiquidityPoolDeposit) Validate(withMuxedAccounts bool) error {
err := validateAmount(lpd.MaxAmountA)
if err != nil {
return NewValidationError("MaxAmountA", err.Error())
}
err = validateAmount(lpd.MaxAmountB)
if err != nil {
return NewValidationError("MaxAmountB", err.Error())
}
err = validateAmount(lpd.MinPrice)
if err != nil {
return NewValidationError("MinPrice", err.Error())
}
err = validateAmount(lpd.MaxPrice)
if err != nil {
return NewValidationError("MaxPrice", err.Error())
}
return nil
}
// GetSourceAccount returns the source account of the operation, or nil if not
// set.
func (lpd *LiquidityPoolDeposit) GetSourceAccount() string {
return lpd.SourceAccount
}