sarafu-vise/store/tokens.go
2025-10-29 10:55:42 +03:00

113 lines
2.8 KiB
Go

package store
import (
"context"
"errors"
"fmt"
"math/big"
"reflect"
"strconv"
"strings"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
)
type TransactionData struct {
TemporaryValue string
ActiveSym string
Amount string
PublicKey string
Recipient string
ActiveDecimal string
ActiveAddress string
}
// TruncateDecimalString safely truncates (not rounds) a number string to the specified decimal places
func TruncateDecimalString(input string, decimalPlaces int) (string, error) {
if _, err := strconv.ParseFloat(input, 64); err != nil {
return "", fmt.Errorf("invalid input")
}
// Split input into integer and fractional parts
parts := strings.SplitN(input, ".", 2)
intPart := parts[0]
var fracPart string
if len(parts) == 2 {
fracPart = parts[1]
}
// Truncate or pad fractional part
if len(fracPart) > decimalPlaces {
fracPart = fracPart[:decimalPlaces]
} else {
fracPart = fracPart + strings.Repeat("0", decimalPlaces-len(fracPart))
}
// Handle zero decimal places
if decimalPlaces == 0 {
return intPart, nil
}
return fmt.Sprintf("%s.%s", intPart, fracPart), nil
}
func ParseAndScaleAmount(storedAmount, activeDecimal string) (string, error) {
// Parse token decimal
tokenDecimal, err := strconv.Atoi(activeDecimal)
if err != nil {
return "", err
}
// Parse amount
amount, _, err := big.ParseFloat(storedAmount, 10, 0, big.ToZero)
if err != nil {
return "", err
}
// Scale the amount
multiplier := new(big.Float).SetInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(tokenDecimal)), nil))
finalAmount := new(big.Float).Mul(amount, multiplier)
// Return finalAmount as a string with 0 decimal places (rounded)
return finalAmount.Text('f', 0), nil
}
func ReadTransactionData(ctx context.Context, store DataStore, sessionId string) (TransactionData, error) {
data := TransactionData{}
fieldToKey := map[string]storedb.DataTyp{
"TemporaryValue": storedb.DATA_TEMPORARY_VALUE,
"ActiveSym": storedb.DATA_ACTIVE_SYM,
"Amount": storedb.DATA_AMOUNT,
"PublicKey": storedb.DATA_PUBLIC_KEY,
"Recipient": storedb.DATA_RECIPIENT,
"ActiveDecimal": storedb.DATA_ACTIVE_DECIMAL,
"ActiveAddress": storedb.DATA_ACTIVE_ADDRESS,
}
v := reflect.ValueOf(&data).Elem()
for fieldName, key := range fieldToKey {
field := v.FieldByName(fieldName)
if !field.IsValid() || !field.CanSet() {
return data, errors.New("invalid struct field: " + fieldName)
}
value, err := ReadStringEntry(ctx, store, sessionId, key)
if err != nil {
return data, err
}
field.SetString(value)
}
return data, nil
}
func ReadStringEntry(ctx context.Context, store DataStore, sessionId string, key storedb.DataTyp) (string, error) {
entry, err := store.ReadEntry(ctx, sessionId, key)
if err != nil {
return "", err
}
return string(entry), nil
}