forked from stellar/go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
liquidity_pool_deposit.go
141 lines (121 loc) · 4.17 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
//lint:file-ignore U1001 Ignore all unused code, staticcheck doesn't understand testify/suite
package txnbuild
import (
"github.com/stellar/go/amount"
"github.com/stellar/go/support/errors"
"github.com/stellar/go/xdr"
)
// LiquidityPoolDeposit represents the Stellar liquidity pool deposit operation. See
// https://developers.stellar.org/docs/start/list-of-operations/
type LiquidityPoolDeposit struct {
SourceAccount string
LiquidityPoolID LiquidityPoolId
MaxAmountA string
MaxAmountB string
MinPrice xdr.Price
MaxPrice xdr.Price
}
// 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 xdr.Price,
) (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() (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'")
}
xdrOp := xdr.LiquidityPoolDepositOp{
LiquidityPoolId: xdrLiquidityPoolId,
MaxAmountA: xdrMaxAmountA,
MaxAmountB: xdrMaxAmountB,
MinPrice: lpd.MinPrice,
MaxPrice: lpd.MaxPrice,
}
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}
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) 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)
lpd.MaxAmountA = amount.String(result.MaxAmountA)
lpd.MaxAmountB = amount.String(result.MaxAmountB)
if result.MinPrice != (xdr.Price{}) {
lpd.MinPrice = result.MinPrice
}
if result.MaxPrice != (xdr.Price{}) {
lpd.MaxPrice = result.MaxPrice
}
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() 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 = validatePrice(lpd.MinPrice)
if err != nil {
return NewValidationError("MinPrice", err.Error())
}
err = validatePrice(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
}