Convert floats to int64.
Following the example of bitcoind and the bitcoin wiki, provide a function to convert floats (which are returned by the json-rpc server) to int64 (which is the normal representation for most values involving bitcoins).
This commit is contained in:
parent
39cef5e76a
commit
86f848ddd4
3 changed files with 67 additions and 2 deletions
33
jsonapi.go
33
jsonapi.go
|
@ -742,3 +742,36 @@ func IsValidIdType(id interface{}) bool {
|
|||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// JSONToAmount Safely converts a floating point value to an int.
|
||||
// Clearly not all floating point numbers can be converted to ints (there
|
||||
// is no one-to-one mapping, but bitcoin's json api returns most numbers as
|
||||
// floats which are not safe to use when handling money. Since bitcoins can
|
||||
// only be divided in a limited way, this methods works for the amounts returned
|
||||
// by the json api. It is not for general use.
|
||||
// This follows the method described at:
|
||||
// https://en.bitcoin.it/wiki/Proper_Money_Handling_%28JSON-RPC%29
|
||||
func JSONToAmount(jsonAmount float64) (int64, error) {
|
||||
var amount int64
|
||||
var err error
|
||||
if jsonAmount > 1.797693134862315708145274237317043567981e+300 {
|
||||
err := fmt.Errorf("Error %d is too large to convert", jsonAmount)
|
||||
return amount, err
|
||||
}
|
||||
if jsonAmount < -1.797693134862315708145274237317043567981e+300 {
|
||||
err := fmt.Errorf("Error %d is too small to convert", jsonAmount)
|
||||
return amount, err
|
||||
}
|
||||
tempVal := 1e8 * jsonAmount
|
||||
// So we round properly. float won't == 0 and if it did, that
|
||||
// would be converted fine anyway.
|
||||
if tempVal < 0 {
|
||||
tempVal = tempVal - 0.5
|
||||
}
|
||||
if tempVal > 0 {
|
||||
tempVal = tempVal + 0.5
|
||||
}
|
||||
// Then just rely on the integer truncating
|
||||
amount = int64(tempVal)
|
||||
return amount, err
|
||||
}
|
||||
|
|
|
@ -256,7 +256,7 @@ var idtests = []struct {
|
|||
}
|
||||
|
||||
// TestIsValidIdType tests that IsValidIdType allows (and disallows the correct
|
||||
// types.
|
||||
// types).
|
||||
func TestIsValidIdType(t *testing.T) {
|
||||
for _, tt := range idtests {
|
||||
res := btcjson.IsValidIdType(tt.testId[0])
|
||||
|
@ -266,3 +266,34 @@ func TestIsValidIdType(t *testing.T) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
var floattests = []struct {
|
||||
in float64
|
||||
out int64
|
||||
pass bool
|
||||
}{
|
||||
{1.0, 100000000, true},
|
||||
{-1.0, -100000000, true},
|
||||
{0.0, 0, true},
|
||||
{0.00000001, 1, true},
|
||||
{-0.00000001, -1, true},
|
||||
{-1.0e307, 0, false},
|
||||
{1.0e307, 0, false},
|
||||
}
|
||||
|
||||
// TestJSONtoAmount tests that JSONtoAmount returns the proper values.
|
||||
func TestJSONtoAmount(t *testing.T) {
|
||||
for _, tt := range floattests {
|
||||
res, err := btcjson.JSONToAmount(tt.in)
|
||||
if tt.pass {
|
||||
if res != tt.out || err != nil {
|
||||
t.Errorf("Should not fail: ", tt.in)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Errorf("Should not pass: ", tt.in)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
github.com/conformal/btcjson/jsonapi.go CreateMessage 100.00% (310/310)
|
||||
github.com/conformal/btcjson/jsonapi.go JSONToAmount 100.00% (15/15)
|
||||
github.com/conformal/btcjson/jsonfxns.go jsonRpcSend 100.00% (7/7)
|
||||
github.com/conformal/btcjson/jsonfxns.go MarshallAndSend 100.00% (7/7)
|
||||
github.com/conformal/btcjson/jsonfxns.go GetRaw 100.00% (6/6)
|
||||
|
@ -7,5 +8,5 @@ github.com/conformal/btcjson/jsonapi.go jsonWithArgs 100.00% (5/5)
|
|||
github.com/conformal/btcjson/jsonapi.go IsValidIdType 100.00% (3/3)
|
||||
github.com/conformal/btcjson/jsonapi.go RpcCommand 66.67% (18/27)
|
||||
github.com/conformal/btcjson/jsonapi.go readResultCmd 40.00% (20/50)
|
||||
github.com/conformal/btcjson --------------- 90.60% (376/415)
|
||||
github.com/conformal/btcjson --------------- 90.93% (391/430)
|
||||
|
||||
|
|
Loading…
Reference in a new issue