-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathamount.go
More file actions
97 lines (86 loc) · 4.31 KB
/
amount.go
File metadata and controls
97 lines (86 loc) · 4.31 KB
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
package processes
import (
"fmt"
"math/big"
sdkmath "cosmossdk.io/math"
"github.com/pkg/errors"
rippledata "github.com/rubblelabs/ripple/data"
)
const (
// XRPLAmountPrec is precision we use to covert float to float string for the amount representation.
// That value is value which corelates with the min/max sending precision.
XRPLAmountPrec = 16
// XRPLIssuedCurrencyDecimals is XRPL decimals used on the coreum.
XRPLIssuedCurrencyDecimals = 15
// XRPIssuer is XRP issuer address used to generate XRP token representation on coreum side. This is done to unify
// representation for all XRPL originated tokens.
XRPIssuer = "rrrrrrrrrrrrrrrrrrrrrho"
// XRPCurrency is XRP currency name used on the coreum.
XRPCurrency = "XRP"
)
// ConvertXRPLOriginatedTokenXRPLAmountToCoreumAmount converts the XRPL native token amount from XRPL to coreum amount
// based on the currency type.
func ConvertXRPLOriginatedTokenXRPLAmountToCoreumAmount(xrplAmount rippledata.Amount) (sdkmath.Int, error) {
if xrplAmount.Value == nil {
return sdkmath.ZeroInt(), nil
}
xrplRatAmount := xrplAmount.Value.Rat()
// native amount is represented as int value
if xrplAmount.IsNative() {
return sdkmath.NewIntFromBigInt(xrplRatAmount.Num()), nil
}
// not XRP value is repressed as value multiplied by 1e15
tenPowerDec := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(int64(XRPLIssuedCurrencyDecimals)), nil)
binIntAmount := big.NewInt(0).Quo(big.NewInt(0).Mul(tenPowerDec, xrplRatAmount.Num()), xrplRatAmount.Denom())
if binIntAmount.BitLen() > sdkmath.MaxBitLen {
return sdkmath.Int{}, errors.New("failed to convert big.Int to sdkmath.Int, out of bound")
}
return sdkmath.NewIntFromBigInt(binIntAmount), nil
}
// ConvertXRPLOriginatedTokenCoreumAmountToXRPLAmount converts the XRPL originated token amount from coreum to XRPL amount
// based on the currency type.
func ConvertXRPLOriginatedTokenCoreumAmountToXRPLAmount(coreumAmount sdkmath.Int, issuerString, currencyString string) (rippledata.Amount, error) {
if isXRPToken(issuerString, currencyString) {
// format with exponent
amountString := big.NewFloat(0).SetInt(coreumAmount.BigInt()).Text('g', XRPLAmountPrec)
// we don't use the decimals for the XRP values since the `NewValue` function will do it automatically
xrplValue, err := rippledata.NewValue(amountString, true)
if err != nil {
return rippledata.Amount{}, errors.Wrapf(err, "failed to convert amount string to ripple.Value, amount stirng: %s", amountString)
}
return rippledata.Amount{
Value: xrplValue,
}, nil
}
return convertCoreumAmountToXRPLAmountWithDecimals(coreumAmount, XRPLIssuedCurrencyDecimals, issuerString, currencyString)
}
// ConvertCoreumOriginatedTokenCoreumAmountToXRPLAmount converts the coreum originated token amount to XRPL amount based on decimals.
func ConvertCoreumOriginatedTokenCoreumAmountToXRPLAmount(coreumAmount sdkmath.Int, decimals uint32, issuerString, currencyString string) (rippledata.Amount, error) {
return convertCoreumAmountToXRPLAmountWithDecimals(coreumAmount, decimals, issuerString, currencyString)
}
func convertCoreumAmountToXRPLAmountWithDecimals(coreumAmount sdkmath.Int, decimals uint32, issuerString, currencyString string) (rippledata.Amount, error) {
tenPowerDec := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(int64(decimals)), nil)
floatAmount := big.NewFloat(0).SetRat(big.NewRat(0, 1).SetFrac(coreumAmount.BigInt(), tenPowerDec))
// format with exponent
amountString := fmt.Sprintf("%s/%s/%s", floatAmount.Text('g', XRPLAmountPrec), currencyString, issuerString)
xrplValue, err := rippledata.NewValue(amountString, false)
if err != nil {
return rippledata.Amount{}, errors.Wrapf(err, "failed to convert amount string to ripple.Value, amount stirng: %s", amountString)
}
currency, err := rippledata.NewCurrency(currencyString)
if err != nil {
return rippledata.Amount{}, errors.Wrapf(err, "failed to convert currency to ripple.Currency, currency: %s", currencyString)
}
issuer, err := rippledata.NewAccountFromAddress(issuerString)
if err != nil {
return rippledata.Amount{}, errors.Wrapf(err, "failed to convert issuer to ripple.Account, issuer: %s", issuerString)
}
return rippledata.Amount{
Value: xrplValue,
Currency: currency,
Issuer: *issuer,
}, nil
}
func isXRPToken(issuer, currency string) bool {
return issuer == XRPIssuer && currency == XRPCurrency
}