diff --git a/chain/types/bigint_test.go b/chain/types/bigint_test.go index 43e5633b2..60130277e 100644 --- a/chain/types/bigint_test.go +++ b/chain/types/bigint_test.go @@ -43,7 +43,7 @@ func TestBigIntSerializationRoundTrip(t *testing.T) { func TestFilRoundTrip(t *testing.T) { testValues := []string{ - "0", "1", "1.001", "100.10001", "101100", "5000.01", "5000", + "0 FIL", "1 FIL", "1.001 FIL", "100.10001 FIL", "101100 FIL", "5000.01 FIL", "5000 FIL", } for _, v := range testValues { diff --git a/chain/types/fil.go b/chain/types/fil.go index 527078e0f..1d912d9c0 100644 --- a/chain/types/fil.go +++ b/chain/types/fil.go @@ -13,9 +13,9 @@ type FIL BigInt func (f FIL) String() string { r := new(big.Rat).SetFrac(f.Int, big.NewInt(int64(build.FilecoinPrecision))) if r.Sign() == 0 { - return "0" + return "0 FIL" } - return strings.TrimRight(strings.TrimRight(r.FloatString(18), "0"), ".") + return strings.TrimRight(strings.TrimRight(r.FloatString(18), "0"), ".") + " FIL" } func (f FIL) Format(s fmt.State, ch rune) { @@ -28,14 +28,35 @@ func (f FIL) Format(s fmt.State, ch rune) { } func ParseFIL(s string) (FIL, error) { + suffix := strings.TrimLeft(s, ".1234567890") + s = s[:len(s)-len(suffix)] + var attofil bool + if suffix != "" { + norm := strings.ToLower(strings.TrimSpace(suffix)) + switch norm { + case "", "fil": + case "attofil", "afil": + attofil = true + default: + return FIL{}, fmt.Errorf("unrecognized suffix: %q", suffix) + } + } + r, ok := new(big.Rat).SetString(s) if !ok { return FIL{}, fmt.Errorf("failed to parse %q as a decimal number", s) } - r = r.Mul(r, big.NewRat(int64(build.FilecoinPrecision), 1)) + if !attofil { + r = r.Mul(r, big.NewRat(int64(build.FilecoinPrecision), 1)) + } + if !r.IsInt() { - return FIL{}, fmt.Errorf("invalid FIL value: %q", s) + var pref string + if attofil { + pref = "atto" + } + return FIL{}, fmt.Errorf("invalid %sFIL value: %q", pref, s) } return FIL{r.Num()}, nil