I have some question for walletupdate of nakama interface

hello everyone, i have a question,When i use WalletUpdate of nakama interface, i save float64 into database, And i use “strconv.ParseFloat(fmt.Sprintf(”%.2f", value), 64)" to covert value keep 2 digits at the decimal point, But i found something like this :
image

and wallet_ledger record like this:

Your code looks correct:

value := 38480.820000000001
s, err := strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
fmt.Println(s)
fmt.Println(err)

which prints out

38480.82
<nil>

Are you sure this isn’t a stale value from previous generation of your code? Can you wipe your records/database and try again?

Thanks your answer, I’ll try again.

Hello,This situation still occurs.
When I use WalletUpdate to record game result
as this:


I got wallet in users as this:
{“expeGold”: 10000, “gameGold”: 5070.699999999999, “safeboxGameGold”: 10}

add image
image

If i use WalletUpdate.
I found 4970.8+99.9 = 5070.699999999 instead of 5070.7

Can you paste your entire function code, including the Nakama hook definition (init_module) function please?

func WalletCoinOut(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, gameType int, userID string, gameGold float64, expeGold float64, score int64, oldGameGold float64, newGameGold float64) error {

gameGold = Decimal(gameGold)
expeGold = Decimal(expeGold)
oldGameGold = Decimal(oldGameGold)
newGameGold = Decimal(newGameGold)

changeset := make(map[string]interface{})
metadata := make(map[string]interface{})
if gameGold > 0 {
	changeset["gameGold"] = gameGold
	metadata["goldType"] = 0             
	metadata["payType"] = 0              
	metadata["income"] = gameGold       
	metadata["expenditure"] = 0          
	metadata["beforeGold"] = oldGameGold 
	metadata["afterGold"] = newGameGold  
	metadata["reportType"] = 1           
}
err := nk.WalletUpdate(ctx, userID, changeset, metadata, true)

return nil

}

func Decimal(value float64) float64 {
reValue, _ := strconv.ParseFloat(fmt.Sprintf(“%.2f”, value), 64)

return reValue
}
func WalletCoinOut(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, gameType int, userID string, gameGold float64, expeGold float64, score int64, oldGameGold float64, newGameGold float64) error {

gameGold = Decimal(gameGold)
expeGold = Decimal(expeGold)
oldGameGold = Decimal(oldGameGold)
newGameGold = Decimal(newGameGold)

changeset := make(map[string]interface{})
metadata := make(map[string]interface{})

changeset[“gameGold”] = gameGold
metadata[“goldType”] = 0
metadata[“payType”] = 0
metadata[“income”] = gameGold
metadata[“expenditure”] = 0
metadata[“beforeGold”] = oldGameGold
metadata[“afterGold”] = newGameGold
metadata[“reportType”] = 1

err := nk.WalletUpdate(ctx, userID, changeset, metadata, true)

return nil
}

What you’re seeing is floating point rounding errors. Since the wallet is stored as JSON and Go’s standard numeric type for JSON encoding/decoding is float64, you’ll see this pop up if you don’t either work around it or compensate.

A good rule of thumb is to avoid storing decimals wherever possible. For example if you want to store a money amount of $1.73 store it in the wallet as whole cents (ie. 173 instead of 1.73) and make sure transactions do not use fractions of cents. You can then handle conversion to dollars.cents at display time.

2 Likes