forked from stellar/go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
asset.go
225 lines (184 loc) · 6.62 KB
/
asset.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
package txnbuild
import (
"bytes"
"github.com/stellar/go/support/errors"
"github.com/stellar/go/xdr"
)
// AssetType represents the type of a Stellar asset.
type AssetType xdr.AssetType
// AssetTypeNative, AssetTypeCreditAlphanum4, AssetTypeCreditAlphanum12 enumerate the different
// types of asset on the Stellar network.
const (
AssetTypeNative AssetType = AssetType(xdr.AssetTypeAssetTypeNative)
AssetTypeCreditAlphanum4 AssetType = AssetType(xdr.AssetTypeAssetTypeCreditAlphanum4)
AssetTypeCreditAlphanum12 AssetType = AssetType(xdr.AssetTypeAssetTypeCreditAlphanum12)
AssetTypePoolShare AssetType = AssetType(xdr.AssetTypeAssetTypePoolShare)
)
// Breaks out some stuff common to all assets
type BasicAsset interface {
GetType() (AssetType, error)
IsNative() bool
GetCode() string
GetIssuer() string
// Conversions to the 3 asset types
ToAsset() (Asset, error)
MustToAsset() Asset
ToChangeTrustAsset() (ChangeTrustAsset, error)
MustToChangeTrustAsset() ChangeTrustAsset
ToTrustLineAsset() (TrustLineAsset, error)
MustToTrustLineAsset() TrustLineAsset
}
// Asset represents a Stellar asset.
type Asset interface {
BasicAsset
LessThan(other Asset) bool
ToXDR() (xdr.Asset, error)
}
// NativeAsset represents the native XLM asset.
type NativeAsset struct{}
// GetType for NativeAsset returns the enum type of the asset.
func (na NativeAsset) GetType() (AssetType, error) {
return AssetTypeNative, nil
}
// IsNative for NativeAsset returns true (this is an XLM asset).
func (na NativeAsset) IsNative() bool { return true }
// GetCode for NativeAsset returns an empty string (XLM doesn't have a code).
func (na NativeAsset) GetCode() string { return "" }
// GetIssuer for NativeAsset returns an empty string (XLM doesn't have an issuer).
func (na NativeAsset) GetIssuer() string { return "" }
// LessThan returns true if this asset sorts before some other asset.
func (na NativeAsset) LessThan(other Asset) bool { return true }
// ToXDR for NativeAsset produces a corresponding XDR asset.
func (na NativeAsset) ToXDR() (xdr.Asset, error) {
xdrAsset := xdr.Asset{}
err := xdrAsset.SetNative()
if err != nil {
return xdr.Asset{}, err
}
return xdrAsset, nil
}
// ToAsset for NativeAsset returns itself unchanged.
func (na NativeAsset) ToAsset() (Asset, error) {
return na, nil
}
// MustToAsset for NativeAsset returns itself unchanged.
func (na NativeAsset) MustToAsset() Asset {
return na
}
// ToChangeTrustAsset for NativeAsset produces a corresponding ChangeTrustAsset.
func (na NativeAsset) ToChangeTrustAsset() (ChangeTrustAsset, error) {
return ChangeTrustAssetWrapper{na}, nil
}
// MustToChangeTrustAsset for NativeAsset produces a corresponding ChangeTrustAsset.
func (na NativeAsset) MustToChangeTrustAsset() ChangeTrustAsset {
return ChangeTrustAssetWrapper{na}
}
// ToTrustLineAsset for NativeAsset produces a corresponding TrustLineAsset.
func (na NativeAsset) ToTrustLineAsset() (TrustLineAsset, error) {
return TrustLineAssetWrapper{na}, nil
}
// MustToTrustLineAsset for NativeAsset produces a corresponding TrustLineAsset.
func (na NativeAsset) MustToTrustLineAsset() TrustLineAsset {
return TrustLineAssetWrapper{na}
}
// CreditAsset represents non-XLM assets on the Stellar network.
type CreditAsset struct {
Code string
Issuer string
}
// GetType for CreditAsset returns the enum type of the asset, based on its code length.
func (ca CreditAsset) GetType() (AssetType, error) {
switch {
case len(ca.Code) >= 1 && len(ca.Code) <= 4:
return AssetTypeCreditAlphanum4, nil
case len(ca.Code) >= 5 && len(ca.Code) <= 12:
return AssetTypeCreditAlphanum12, nil
default:
return AssetTypeCreditAlphanum4, errors.New("asset code length must be between 1 and 12 characters")
}
}
// IsNative for CreditAsset returns false (this is not an XLM asset).
func (ca CreditAsset) IsNative() bool { return false }
// GetCode for CreditAsset returns the asset code.
func (ca CreditAsset) GetCode() string { return ca.Code }
// GetIssuer for CreditAsset returns the address of the issuing account.
func (ca CreditAsset) GetIssuer() string { return ca.Issuer }
// LessThan returns true if this asset sorts before some other asset.
func (ca CreditAsset) LessThan(other Asset) bool {
caXDR, err := ca.ToXDR()
if err != nil {
return false
}
otherXDR, err := other.ToXDR()
if err != nil {
return false
}
return caXDR.LessThan(otherXDR)
}
// ToXDR for CreditAsset produces a corresponding XDR asset.
func (ca CreditAsset) ToXDR() (xdr.Asset, error) {
xdrAsset := xdr.Asset{}
var issuer xdr.AccountId
err := issuer.SetAddress(ca.Issuer)
if err != nil {
return xdr.Asset{}, err
}
err = xdrAsset.SetCredit(ca.Code, issuer)
if err != nil {
return xdr.Asset{}, errors.Wrap(err, "asset code length must be between 1 and 12 characters")
}
return xdrAsset, nil
}
// ToAsset for CreditAsset returns itself unchanged.
func (ca CreditAsset) ToAsset() (Asset, error) {
return ca, nil
}
// MustToAsset for CreditAsset returns itself unchanged.
func (ca CreditAsset) MustToAsset() Asset {
return ca
}
// ToChangeTrustAsset for CreditAsset produces a corresponding XDR asset.
func (ca CreditAsset) ToChangeTrustAsset() (ChangeTrustAsset, error) {
return ChangeTrustAssetWrapper{ca}, nil
}
// MustToChangeTrustAsset for CreditAsset produces a corresponding XDR asset.
func (ca CreditAsset) MustToChangeTrustAsset() ChangeTrustAsset {
return ChangeTrustAssetWrapper{ca}
}
// ToTrustLineAsset for CreditAsset produces a corresponding XDR asset.
func (ca CreditAsset) ToTrustLineAsset() (TrustLineAsset, error) {
return TrustLineAssetWrapper{ca}, nil
}
// MustToTrustLineAsset for CreditAsset produces a corresponding XDR asset.
func (ca CreditAsset) MustToTrustLineAsset() TrustLineAsset {
return TrustLineAssetWrapper{ca}
}
// to do: consider exposing function or adding it to asset interface
func assetFromXDR(xAsset xdr.Asset) (Asset, error) {
switch xAsset.Type {
case xdr.AssetTypeAssetTypeNative:
return NativeAsset{}, nil
case xdr.AssetTypeAssetTypeCreditAlphanum4:
code := bytes.Trim(xAsset.AlphaNum4.AssetCode[:], "\x00")
return CreditAsset{
Code: string(code[:]),
Issuer: xAsset.AlphaNum4.Issuer.Address(),
}, nil
case xdr.AssetTypeAssetTypeCreditAlphanum12:
code := bytes.Trim(xAsset.AlphaNum12.AssetCode[:], "\x00")
return CreditAsset{
Code: string(code[:]),
Issuer: xAsset.AlphaNum12.Issuer.Address(),
}, nil
}
return nil, errors.New("invalid asset")
}
// MustAssetFromXDR constructs an Asset from its xdr representation.
// If the given asset xdr is invalid, MustAssetFromXDR will panic.
func MustAssetFromXDR(xAsset xdr.Asset) Asset {
asset, err := assetFromXDR(xAsset)
if err != nil {
panic(err)
}
return asset
}