Skip to content

Commit

Permalink
go/staking/api: Use go/common/prettyprint.FractionBase10()
Browse files Browse the repository at this point in the history
Make ConvertToTokenAmount() and PrettyPrintCommissionRatePercentage()
use the newly introduced FractionBase10 function.

Add tests for PrettyPrintCommissionRatePercentage() and move it to
go/staking/api/prettyprint.go.
  • Loading branch information
tjanez committed Jul 24, 2020
1 parent 6f9ed19 commit d825fd2
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 35 deletions.
18 changes: 3 additions & 15 deletions go/staking/api/commission.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"io"
"math/big"
"strconv"

"github.com/oasisprotocol/oasis-core/go/common/prettyprint"
"github.com/oasisprotocol/oasis-core/go/common/quantity"
Expand All @@ -28,17 +27,6 @@ var (
_ prettyprint.PrettyPrinter = (*CommissionSchedule)(nil)
)

// CommissionRatePercentage returns the string representing the commission rate
// in percentage for the given commission rate numerator.
func CommissionRatePercentage(rateNumerator quantity.Quantity) string {
rate := big.NewRat(rateNumerator.ToBigInt().Int64(), CommissionRateDenominator.ToBigInt().Int64())
// Multiply rate by 100 to convert it to percentage.
rate.Mul(rate, big.NewRat(100, 1))
// Return string representation of the rate that omits the trailing zeros.
rateFloat, _ := rate.Float64()
return strconv.FormatFloat(rateFloat, 'f', -1, 64)
}

// CommissionScheduleRules controls how commission schedule rates and rate
// bounds are allowed to be changed.
type CommissionScheduleRules struct {
Expand Down Expand Up @@ -66,7 +54,7 @@ type CommissionRateStep struct {
func (crs CommissionRateStep) PrettyPrint(ctx context.Context, prefix string, w io.Writer) {
fmt.Fprintf(w, "%s- Start: epoch %d\n", prefix, crs.Start)

fmt.Fprintf(w, "%s Rate: %s %%\n", prefix, CommissionRatePercentage(crs.Rate))
fmt.Fprintf(w, "%s Rate: %s\n", prefix, PrettyPrintCommissionRatePercentage(crs.Rate))
}

// PrettyType returns a representation of CommissionRateStep that can be used
Expand All @@ -91,8 +79,8 @@ type CommissionRateBoundStep struct {
func (crbs CommissionRateBoundStep) PrettyPrint(ctx context.Context, prefix string, w io.Writer) {
fmt.Fprintf(w, "%s- Start: epoch %d\n", prefix, crbs.Start)

fmt.Fprintf(w, "%s Minimum Rate: %s %%\n", prefix, CommissionRatePercentage(crbs.RateMin))
fmt.Fprintf(w, "%s Maximum Rate: %s %%\n", prefix, CommissionRatePercentage(crbs.RateMax))
fmt.Fprintf(w, "%s Minimum Rate: %s\n", prefix, PrettyPrintCommissionRatePercentage(crbs.RateMin))
fmt.Fprintf(w, "%s Maximum Rate: %s\n", prefix, PrettyPrintCommissionRatePercentage(crbs.RateMax))
}

// PrettyType returns a representation of CommissionRateBoundStep that can be
Expand Down
36 changes: 16 additions & 20 deletions go/staking/api/prettyprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import (
"context"
"fmt"
"io"
"math/big"
"strings"

"github.com/oasisprotocol/oasis-core/go/common/prettyprint"
"github.com/oasisprotocol/oasis-core/go/common/quantity"
)

Expand All @@ -29,24 +28,7 @@ func ConvertToTokenAmount(amount quantity.Quantity, tokenValueExponent uint8) (s
return "", ErrInvalidTokenValueExponent
}

divisor := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(tokenValueExponent)), nil)

// NOTE: We use DivMod() and manual string construction to avoid conversion
// to other types and support arbitrarily large amounts.
var quotient, remainder *big.Int
quotient, remainder = new(big.Int).DivMod(amount.ToBigInt(), divisor, new(big.Int))

// Prefix the remainder with the appropriate number of zeros.
remainderStr := fmt.Sprintf("%0*s", tokenValueExponent, remainder)
// Trim trailing zeros from the remainder.
remainderStr = strings.TrimRight(remainderStr, "0")
// Ensure remainder is not empty.
if remainderStr == "" {
remainderStr = "0"
}

// Combine quotient and remainder to a string representing the token amount.
return fmt.Sprintf("%s.%s", quotient, remainderStr), nil
return prettyprint.FractionBase10(amount, tokenValueExponent), nil
}

// PrettyPrintAmount writes a pretty-printed representation of the given amount
Expand Down Expand Up @@ -82,3 +64,17 @@ func PrettyPrintAmount(ctx context.Context, amount quantity.Quantity, w io.Write
fmt.Fprintf(w, "%s %s", symbol, tokenAmount)
}
}

// PrettyPrintCommissionRatePercentage returns the string representing the
// commission rate (bound) in percentage for the given commission rate (bound)
// numerator.
func PrettyPrintCommissionRatePercentage(rateNumerator quantity.Quantity) string {
// Handle invalid commission rate (bound) numerator.
if rateNumerator.Cmp(CommissionRateDenominator) > 0 {
return fmt.Sprintf("(invalid)")
}
// Reduce commission rate denominator's base-10 exponent by 2 to obtain the
// value in percentage.
denominatorExp := commissionRateDenominatorExponent - 2
return fmt.Sprintf("%s%%", prettyprint.FractionBase10(rateNumerator, denominatorExp))
}
22 changes: 22 additions & 0 deletions go/staking/api/prettyprint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,25 @@ func TestPrettyPrintAmount(t *testing.T) {
"pretty printing stake amount didn't return the expected result")
}
}

func TestPrettyPrintCommissionRatePercentage(t *testing.T) {
require := require.New(t)

for _, t := range []struct {
expectedRate string
rateNumerator *quantity.Quantity
}{
{"0.0%", quantity.NewFromUint64(0)},
{"50.0%", quantity.NewFromUint64(50_000)},
{"100.0%", quantity.NewFromUint64(100_000)},
{"20.2%", quantity.NewFromUint64(20_200)},
{"30.03%", quantity.NewFromUint64(30_030)},
{"12.345%", quantity.NewFromUint64(12_345)},
// Checks for invalid commission rate numerators.
{"(invalid)", quantity.NewFromUint64(100_001)},
{"(invalid)", quantity.NewFromUint64(123_456)},
} {
rate := PrettyPrintCommissionRatePercentage(*t.rateNumerator)
require.Equal(t.expectedRate, rate, "obtained pretty print didn't match expected value")
}
}

0 comments on commit d825fd2

Please sign in to comment.