ussd/internal/utils/vouchers.go

185 lines
4.9 KiB
Go

package utils
import (
"fmt"
"strings"
"context"
"git.grassecon.net/urdt/ussd/internal/storage"
)
// VoucherMetadata helps organize voucher data fields
type VoucherMetadata struct {
Symbol string
Balance string
Decimal string
Address string
}
// ProcessVouchers converts holdings into formatted strings
func ProcessVouchers(holdings []struct {
ContractAddress string `json:"contractAddress"`
TokenSymbol string `json:"tokenSymbol"`
TokenDecimals string `json:"tokenDecimals"`
Balance string `json:"balance"`
}) VoucherMetadata {
var data VoucherMetadata
var symbols, balances, decimals, addresses []string
for i, h := range holdings {
symbols = append(symbols, fmt.Sprintf("%d:%s", i+1, h.TokenSymbol))
balances = append(balances, fmt.Sprintf("%d:%s", i+1, h.Balance))
decimals = append(decimals, fmt.Sprintf("%d:%s", i+1, h.TokenDecimals))
addresses = append(addresses, fmt.Sprintf("%d:%s", i+1, h.ContractAddress))
}
data.Symbol = strings.Join(symbols, "\n")
data.Balance = strings.Join(balances, "\n")
data.Decimal = strings.Join(decimals, "\n")
data.Address = strings.Join(addresses, "\n")
return data
}
// GetVoucherData retrieves and matches voucher data
func GetVoucherData(ctx context.Context, db storage.PrefixDb, input string) (*VoucherMetadata, error) {
keys := []string{"sym", "bal", "deci", "addr"}
data := make(map[string]string)
for _, key := range keys {
value, err := db.Get(ctx, []byte(key))
if err != nil {
return nil, fmt.Errorf("failed to get %s: %v", key, err)
}
data[key] = string(value)
}
symbol, balance, decimal, address := MatchVoucher(input,
data["sym"],
data["bal"],
data["deci"],
data["addr"])
if symbol == "" {
return nil, nil
}
return &VoucherMetadata{
Symbol: symbol,
Balance: balance,
Decimal: decimal,
Address: address,
}, nil
}
// MatchVoucher finds the matching voucher symbol, balance, decimals and contract address based on the input.
func MatchVoucher(input, symbols, balances, decimals, addresses string) (symbol, balance, decimal, address string) {
symList := strings.Split(symbols, "\n")
balList := strings.Split(balances, "\n")
decList := strings.Split(decimals, "\n")
addrList := strings.Split(addresses, "\n")
for i, sym := range symList {
parts := strings.SplitN(sym, ":", 2)
if len(parts) != 2 {
continue
}
if input == parts[0] || strings.EqualFold(input, parts[1]) {
symbol = parts[1]
if i < len(balList) {
balance = strings.SplitN(balList[i], ":", 2)[1]
}
if i < len(decList) {
decimal = strings.SplitN(decList[i], ":", 2)[1]
}
if i < len(addrList) {
address = strings.SplitN(addrList[i], ":", 2)[1]
}
break
}
}
return
}
// StoreTemporaryVoucher saves voucher metadata as temporary entries in the DataStore.
func StoreTemporaryVoucher(ctx context.Context, store DataStore, sessionId string, data *VoucherMetadata) error {
entries := map[DataTyp][]byte{
DATA_TEMPORARY_SYM: []byte(data.Symbol),
DATA_TEMPORARY_BAL: []byte(data.Balance),
DATA_TEMPORARY_DECIMAL: []byte(data.Decimal),
DATA_TEMPORARY_ADDRESS: []byte(data.Address),
}
for key, value := range entries {
if err := store.WriteEntry(ctx, sessionId, key, value); err != nil {
return err
}
}
return nil
}
// GetTemporaryVoucherData retrieves temporary voucher metadata from the DataStore.
func GetTemporaryVoucherData(ctx context.Context, store DataStore, sessionId string) (*VoucherMetadata, error) {
keys := []DataTyp{
DATA_TEMPORARY_SYM,
DATA_TEMPORARY_BAL,
DATA_TEMPORARY_DECIMAL,
DATA_TEMPORARY_ADDRESS,
}
data := &VoucherMetadata{}
values := make([][]byte, len(keys))
for i, key := range keys {
value, err := store.ReadEntry(ctx, sessionId, key)
if err != nil {
return nil, err
}
values[i] = value
}
data.Symbol = string(values[0])
data.Balance = string(values[1])
data.Decimal = string(values[2])
data.Address = string(values[3])
return data, nil
}
// UpdateVoucherData sets the active voucher data and clears the temporary voucher data in the DataStore.
func UpdateVoucherData(ctx context.Context, store DataStore, sessionId string, data *VoucherMetadata) error {
// Active voucher data entries
activeEntries := map[DataTyp][]byte{
DATA_ACTIVE_SYM: []byte(data.Symbol),
DATA_ACTIVE_BAL: []byte(data.Balance),
DATA_ACTIVE_DECIMAL: []byte(data.Decimal),
DATA_ACTIVE_ADDRESS: []byte(data.Address),
}
// Clear temporary voucher data entries
tempEntries := map[DataTyp][]byte{
DATA_TEMPORARY_SYM: []byte(""),
DATA_TEMPORARY_BAL: []byte(""),
DATA_TEMPORARY_DECIMAL: []byte(""),
DATA_TEMPORARY_ADDRESS: []byte(""),
}
// Write active data
for key, value := range activeEntries {
if err := store.WriteEntry(ctx, sessionId, key, value); err != nil {
return err
}
}
// Clear temporary data
for key, value := range tempEntries {
if err := store.WriteEntry(ctx, sessionId, key, value); err != nil {
return err
}
}
return nil
}