mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-09-13 13:00:10 +00:00

* Fix off by small amounts in sent amount kaspa Floating point math causes inconsistencies when converting kas to sompi. Use a method that parses the amount as a string, the converts it to sompi then parse back to uint64 * Deal with SendAmount as strings all the way * Consistent config handling * Set variables directly from utils.KasToSompi Use = instead of := to ensure no shadowing * Fix validate amount regex * Use decimal places as defined by constants Also check if SompiPerKaspa is multiple of 10 * Minor updates for context clarity
69 lines
1.7 KiB
Go
69 lines
1.7 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// FormatKas takes the amount of sompis as uint64, and returns amount of KAS with 8 decimal places
|
|
func FormatKas(amount uint64) string {
|
|
res := " "
|
|
if amount > 0 {
|
|
res = fmt.Sprintf("%19.8f", float64(amount)/constants.SompiPerKaspa)
|
|
}
|
|
return res
|
|
}
|
|
|
|
// KasToSompi takes in a string representation of the Kas value to convert to Sompi
|
|
func KasToSompi(amount string) (uint64, error) {
|
|
err := validateKASAmountFormat(amount)
|
|
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// after validation, amount can only be either an int OR
|
|
// a float with an int component and decimal places
|
|
parts := strings.Split(amount, ".")
|
|
amountStr := ""
|
|
|
|
if constants.SompiPerKaspa%10 != 0 {
|
|
return 0, errors.Errorf("Unable to convert to sompi when SompiPerKaspa is not a multiple of 10")
|
|
}
|
|
|
|
decimalPlaces := int(math.Log10(constants.SompiPerKaspa))
|
|
decimalStr := ""
|
|
|
|
if len(parts) == 2 {
|
|
decimalStr = parts[1]
|
|
}
|
|
|
|
amountStr = fmt.Sprintf("%s%-*s", parts[0], decimalPlaces, decimalStr) // Padded with spaces at the end to fill for missing decimals: Sample "0.01234 "
|
|
amountStr = strings.ReplaceAll(amountStr, " ", "0") // Make the spaces be 0s. Sample "0.012340000"
|
|
|
|
convertedAmount, err := strconv.ParseUint(amountStr, 10, 64)
|
|
|
|
return convertedAmount, err
|
|
}
|
|
|
|
func validateKASAmountFormat(amount string) error {
|
|
// Check whether it's an integer, or a float with max 8 digits
|
|
match, err := regexp.MatchString("^([1-9]\\d{0,11}|0)(\\.\\d{0,8})?$", amount)
|
|
|
|
if !match {
|
|
return errors.Errorf("Invalid amount")
|
|
}
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|