Skip to content

Commit cca2f9d

Browse files
authored
Merge PR #2506: types: Dec.MarshalJSON now marshals as a normal decimal string
2 parents 57277d1 + 1a463eb commit cca2f9d

File tree

3 files changed

+72
-43
lines changed

3 files changed

+72
-43
lines changed

PENDING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ BREAKING CHANGES
8181
* [x/stake] \#2412 Added an unbonding validator queue to EndBlock to automatically update validator.Status when finished Unbonding
8282
* [x/stake] \#2500 Block conflicting redelegations until we add an index
8383
* [x/params] Global Paramstore refactored
84+
* [types] \#2506 sdk.Dec MarshalJSON now marshals as a normal Decimal, with 10 digits of decimal precision
8485
* [x/stake] \#2508 Utilize Tendermint power for validator power key
8586
* [x/stake] \#2531 Remove all inflation logic
8687
* [x/mint] \#2531 Add minting module and inflation logic

types/decimal.go

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -248,29 +248,33 @@ func (d Dec) QuoInt(i Int) Dec {
248248
}
249249

250250
func (d Dec) String() string {
251-
str := d.ToLeftPaddedWithDecimals(Precision)
252-
placement := len(str) - Precision
253-
if placement < 0 {
254-
panic("too few decimal digits")
251+
bz, err := d.Int.MarshalText()
252+
if err != nil {
253+
return ""
254+
}
255+
var bzWDec []byte
256+
inputSize := len(bz)
257+
// TODO: Remove trailing zeros
258+
// case 1, purely decimal
259+
if inputSize <= 10 {
260+
bzWDec = make([]byte, 12)
261+
// 0. prefix
262+
bzWDec[0] = byte('0')
263+
bzWDec[1] = byte('.')
264+
// set relevant digits to 0
265+
for i := 0; i < 10-inputSize; i++ {
266+
bzWDec[i+2] = byte('0')
267+
}
268+
// set last few digits
269+
copy(bzWDec[2+(10-inputSize):], bz)
270+
} else {
271+
// inputSize + 1 to account for the decimal point that is being added
272+
bzWDec = make([]byte, inputSize+1)
273+
copy(bzWDec, bz[:inputSize-10])
274+
bzWDec[inputSize-10] = byte('.')
275+
copy(bzWDec[inputSize-9:], bz[inputSize-10:])
255276
}
256-
return str[:placement] + "." + str[placement:]
257-
}
258-
259-
// TODO panic if negative or if totalDigits < len(initStr)???
260-
// evaluate as an integer and return left padded string
261-
func (d Dec) ToLeftPaddedWithDecimals(totalDigits int8) string {
262-
intStr := d.Int.String()
263-
fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s`
264-
return fmt.Sprintf(fcode, intStr)
265-
}
266-
267-
// TODO panic if negative or if totalDigits < len(initStr)???
268-
// evaluate as an integer and return left padded string
269-
func (d Dec) ToLeftPadded(totalDigits int8) string {
270-
chopped := chopPrecisionAndRoundNonMutative(d.Int)
271-
intStr := chopped.String()
272-
fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s`
273-
return fmt.Sprintf(fcode, intStr)
277+
return string(bzWDec)
274278
}
275279

276280
// ____
@@ -407,17 +411,13 @@ func (d *Dec) UnmarshalAmino(text string) (err error) {
407411
return nil
408412
}
409413

410-
// MarshalJSON defines custom encoding scheme
414+
// MarshalJSON marshals the decimal
411415
func (d Dec) MarshalJSON() ([]byte, error) {
412416
if d.Int == nil {
413417
return nilJSON, nil
414418
}
415419

416-
bz, err := d.Int.MarshalText()
417-
if err != nil {
418-
return nil, err
419-
}
420-
return json.Marshal(string(bz))
420+
return json.Marshal(d.String())
421421
}
422422

423423
// UnmarshalJSON defines custom decoding scheme
@@ -431,7 +431,13 @@ func (d *Dec) UnmarshalJSON(bz []byte) error {
431431
if err != nil {
432432
return err
433433
}
434-
return d.Int.UnmarshalText([]byte(text))
434+
// TODO: Reuse dec allocation
435+
newDec, err := NewDecFromStr(text)
436+
if err != nil {
437+
return err
438+
}
439+
d.Int = newDec.Int
440+
return nil
435441
}
436442

437443
//___________________________________________________________________________________

types/decimal_test.go

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"math/big"
55
"testing"
66

7+
"github.com/stretchr/testify/assert"
8+
79
"github.com/cosmos/cosmos-sdk/codec"
810
"github.com/stretchr/testify/require"
911
)
@@ -228,26 +230,46 @@ func TestTruncate(t *testing.T) {
228230
}
229231
}
230232

231-
func TestToLeftPadded(t *testing.T) {
233+
var cdc = codec.New()
234+
235+
func TestDecMarshalJSON(t *testing.T) {
236+
decimal := func(i int64) Dec {
237+
d := NewDec(0)
238+
d.Int = new(big.Int).SetInt64(i)
239+
return d
240+
}
232241
tests := []struct {
233-
dec Dec
234-
digits int8
235-
exp string
242+
name string
243+
d Dec
244+
want string
245+
wantErr bool // if wantErr = false, will also attempt unmarshaling
236246
}{
237-
{mustNewDecFromStr(t, "33.3"), 8, "00000033"},
238-
{mustNewDecFromStr(t, "50"), 8, "00000050"},
239-
{mustNewDecFromStr(t, "333"), 8, "00000333"},
240-
{mustNewDecFromStr(t, "333"), 12, "000000000333"},
241-
{mustNewDecFromStr(t, "0.3333"), 8, "00000000"},
247+
{"zero", decimal(0), "\"0.0000000000\"", false},
248+
{"one", decimal(1), "\"0.0000000001\"", false},
249+
{"ten", decimal(10), "\"0.0000000010\"", false},
250+
{"12340", decimal(12340), "\"0.0000012340\"", false},
251+
{"zeroInt", NewDec(0), "\"0.0000000000\"", false},
252+
{"oneInt", NewDec(1), "\"1.0000000000\"", false},
253+
{"tenInt", NewDec(10), "\"10.0000000000\"", false},
254+
{"12340Int", NewDec(12340), "\"12340.0000000000\"", false},
242255
}
243-
for tcIndex, tc := range tests {
244-
res := tc.dec.ToLeftPadded(tc.digits)
245-
require.Equal(t, tc.exp, res, "incorrect left padding, tc %d", tcIndex)
256+
for _, tt := range tests {
257+
t.Run(tt.name, func(t *testing.T) {
258+
got, err := tt.d.MarshalJSON()
259+
if (err != nil) != tt.wantErr {
260+
t.Errorf("Dec.MarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
261+
return
262+
}
263+
if !tt.wantErr {
264+
assert.Equal(t, tt.want, string(got), "incorrect marshalled value")
265+
unmarshalledDec := NewDec(0)
266+
unmarshalledDec.UnmarshalJSON(got)
267+
assert.Equal(t, tt.d, unmarshalledDec, "incorrect unmarshalled value")
268+
}
269+
})
246270
}
247271
}
248272

249-
var cdc = codec.New()
250-
251273
func TestZeroDeserializationJSON(t *testing.T) {
252274
d := Dec{new(big.Int)}
253275
err := cdc.UnmarshalJSON([]byte(`"0"`), &d)

0 commit comments

Comments
 (0)