forked from stellar/go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
path_payment_strict_send.go
160 lines (138 loc) · 4.56 KB
/
path_payment_strict_send.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
156
157
158
159
160
package txnbuild
import (
"github.com/stellar/go/amount"
"github.com/stellar/go/support/errors"
"github.com/stellar/go/xdr"
)
// PathPaymentStrictSend represents the Stellar path_payment_strict_send operation. See
// https://developers.stellar.org/docs/start/list-of-operations/
type PathPaymentStrictSend struct {
SendAsset Asset
SendAmount string
Destination string
DestAsset Asset
DestMin string
Path []Asset
SourceAccount string
}
// BuildXDR for Payment returns a fully configured XDR Operation.
func (pp *PathPaymentStrictSend) BuildXDR() (xdr.Operation, error) {
// Set XDR send asset
if pp.SendAsset == nil {
return xdr.Operation{}, errors.New("you must specify an asset to send for payment")
}
xdrSendAsset, err := pp.SendAsset.ToXDR()
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to set asset type")
}
// Set XDR dest min
xdrDestMin, err := amount.Parse(pp.DestMin)
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to parse minimum amount to receive")
}
// Set XDR destination
var xdrDestination xdr.MuxedAccount
err = xdrDestination.SetAddress(pp.Destination)
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to set destination address")
}
// Set XDR destination asset
if pp.DestAsset == nil {
return xdr.Operation{}, errors.New("you must specify an asset for destination account to receive")
}
xdrDestAsset, err := pp.DestAsset.ToXDR()
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to set asset type")
}
// Set XDR destination amount
xdrSendAmount, err := amount.Parse(pp.SendAmount)
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to parse amount of asset source account sends")
}
// Set XDR path
var xdrPath []xdr.Asset
var xdrPathAsset xdr.Asset
for _, asset := range pp.Path {
xdrPathAsset, err = asset.ToXDR()
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to set asset type")
}
xdrPath = append(xdrPath, xdrPathAsset)
}
opType := xdr.OperationTypePathPaymentStrictSend
xdrOp := xdr.PathPaymentStrictSendOp{
SendAsset: xdrSendAsset,
SendAmount: xdrSendAmount,
Destination: xdrDestination,
DestAsset: xdrDestAsset,
DestMin: xdrDestMin,
Path: xdrPath,
}
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, pp.SourceAccount)
return op, nil
}
// FromXDR for PathPaymentStrictSend initialises the txnbuild struct from the corresponding xdr Operation.
func (pp *PathPaymentStrictSend) FromXDR(xdrOp xdr.Operation) error {
result, ok := xdrOp.Body.GetPathPaymentStrictSendOp()
if !ok {
return errors.New("error parsing path_payment operation from xdr")
}
pp.SourceAccount = accountFromXDR(xdrOp.SourceAccount)
pp.Destination = result.Destination.Address()
pp.SendAmount = amount.String(result.SendAmount)
pp.DestMin = amount.String(result.DestMin)
destAsset, err := assetFromXDR(result.DestAsset)
if err != nil {
return errors.Wrap(err, "error parsing dest_asset in path_payment operation")
}
pp.DestAsset = destAsset
sendAsset, err := assetFromXDR(result.SendAsset)
if err != nil {
return errors.Wrap(err, "error parsing send_asset in path_payment operation")
}
pp.SendAsset = sendAsset
pp.Path = []Asset{}
for _, p := range result.Path {
pathAsset, err := assetFromXDR(p)
if err != nil {
return errors.Wrap(err, "error parsing paths in path_payment operation")
}
pp.Path = append(pp.Path, pathAsset)
}
return nil
}
// Validate for PathPaymentStrictSend validates the required struct fields. It returns an error if any
// of the fields are invalid. Otherwise, it returns nil.
func (pp *PathPaymentStrictSend) Validate() error {
_, err := xdr.AddressToMuxedAccount(pp.Destination)
if err != nil {
return NewValidationError("Destination", err.Error())
}
err = validateStellarAsset(pp.SendAsset)
if err != nil {
return NewValidationError("SendAsset", err.Error())
}
err = validateStellarAsset(pp.DestAsset)
if err != nil {
return NewValidationError("DestAsset", err.Error())
}
err = validateAmount(pp.SendAmount)
if err != nil {
return NewValidationError("SendAmount", err.Error())
}
err = validateAmount(pp.DestMin)
if err != nil {
return NewValidationError("DestMin", err.Error())
}
return nil
}
// GetSourceAccount returns the source account of the operation, or the empty string if not
// set.
func (pp *PathPaymentStrictSend) GetSourceAccount() string {
return pp.SourceAccount
}