Compare commits

..

29 Commits

Author SHA1 Message Date
26f6e9ea12
Updated the alias and balance functionality to match master 2025-07-14 09:45:55 +03:00
b43c1f6c8e
Merge branch 'master' into project-tidyup 2025-07-14 09:38:04 +03:00
754008f0c1
git ignore the user-data files 2025-07-04 13:56:46 +03:00
c8a705ff44
move voucher related tests 2025-07-03 17:57:24 +03:00
a55d254c4f
move transaction list related tests 2025-07-03 17:52:30 +03:00
92af428af4
move send node related tests 2025-07-03 17:44:55 +03:00
5e166fd680
move registration tests 2025-07-03 17:33:11 +03:00
5d38359b66
move profile tests 2025-07-03 17:31:05 +03:00
7c21b78332
move language tests 2025-07-03 17:22:06 +03:00
916026985f
move balance tests 2025-07-03 17:16:44 +03:00
57b0fcb55f
move authorization tests 2025-07-03 17:13:51 +03:00
baa7526df3
move account_status tests 2025-07-03 17:07:26 +03:00
f22f86a2fb
move PIN tests to pin_test.go 2025-07-03 17:02:36 +03:00
827debe020
added account_status.go for account status related functions 2025-07-03 16:55:57 +03:00
2b557b27cf
added authorization.go for authorization related functions 2025-07-03 16:52:59 +03:00
b9aae610db
added language.go for language related functions 2025-07-03 16:43:43 +03:00
8297f012f4
added balance.go for balance related functions 2025-07-03 16:39:44 +03:00
eafc0f69c7
added alias.go for alias related functions 2025-07-03 16:34:20 +03:00
6c962baa81
added pools.go for pool related functions 2025-07-03 16:20:59 +03:00
e6b97b9256
update the voucher functions to match master 2025-07-03 16:19:18 +03:00
4e8b4c1df6 Merge branch 'master' into project-tidyup 2025-07-03 16:08:08 +03:00
fea0befd9f
added profile.go for profile related functionality 2025-07-01 02:04:45 +03:00
857964f69a
added send.go for voucher transfers 2025-07-01 02:01:45 +03:00
164ce5ea5a
added upsell.go for inviting valid users 2025-07-01 01:59:20 +03:00
7b85451fd6
added vouchers.go 2025-07-01 01:57:32 +03:00
a6cd3d93b4
added transactions.go for transaction histories 2025-07-01 01:55:30 +03:00
9722df1149
added poolswap.go for pool swap functionality 2025-07-01 01:53:03 +03:00
a9e0aebdde
move PIN functionality to pin.go 2025-07-01 01:50:20 +03:00
098ea93439
move create account functionality to the registration.go file 2025-07-01 01:44:38 +03:00
12 changed files with 30 additions and 164 deletions

View File

@ -21,7 +21,7 @@ RUN make VISE_PATH=/build/go-vise -B
WORKDIR /build/sarafu-vise WORKDIR /build/sarafu-vise
RUN echo "Building on $BUILDPLATFORM, building for $TARGETPLATFORM" RUN echo "Building on $BUILDPLATFORM, building for $TARGETPLATFORM"
RUN go mod download RUN go mod download
RUN go build -tags logtrace,online -o sarafu-at -ldflags="-X main.build=${BUILD} -s -w" cmd/africastalking/main.go RUN go build -tags logdebug,online -o sarafu-at -ldflags="-X main.build=${BUILD} -s -w" cmd/africastalking/main.go
FROM debian:bookworm-slim FROM debian:bookworm-slim

View File

@ -83,7 +83,6 @@ func (h *MenuHandlers) CheckAccountCreated(ctx context.Context, sym string, inpu
// CheckBlockedStatus: // CheckBlockedStatus:
// 1. Checks whether the DATA_SELF_PIN_RESET is 1 and sets the flag_account_pin_reset // 1. Checks whether the DATA_SELF_PIN_RESET is 1 and sets the flag_account_pin_reset
// 2. resets the account blocked flag if the PIN attempts have been reset by an admin. // 2. resets the account blocked flag if the PIN attempts have been reset by an admin.
// 3. Sets key flags (language and PIN) if the data exists
func (h *MenuHandlers) CheckBlockedStatus(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *MenuHandlers) CheckBlockedStatus(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
store := h.userdataStore store := h.userdataStore
@ -91,30 +90,11 @@ func (h *MenuHandlers) CheckBlockedStatus(ctx context.Context, sym string, input
flag_account_blocked, _ := h.flagManager.GetFlag("flag_account_blocked") flag_account_blocked, _ := h.flagManager.GetFlag("flag_account_blocked")
flag_account_pin_reset, _ := h.flagManager.GetFlag("flag_account_pin_reset") flag_account_pin_reset, _ := h.flagManager.GetFlag("flag_account_pin_reset")
flag_pin_set, _ := h.flagManager.GetFlag("flag_pin_set")
flag_language_set, _ := h.flagManager.GetFlag("flag_language_set")
pinFlagSet := h.st.MatchFlag(flag_pin_set, true)
languageFlagSet := h.st.MatchFlag(flag_language_set, true)
sessionId, ok := ctx.Value("SessionId").(string) sessionId, ok := ctx.Value("SessionId").(string)
if !ok { if !ok {
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
// only check the data if the flag isn't set
if !pinFlagSet {
accountPin, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_ACCOUNT_PIN)
if len(accountPin) > 0 {
res.FlagSet = append(res.FlagSet, flag_pin_set)
}
}
if !languageFlagSet {
languageCode, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_SELECTED_LANGUAGE_CODE)
if len(languageCode) > 0 {
res.FlagSet = append(res.FlagSet, flag_language_set)
}
}
res.FlagReset = append(res.FlagReset, flag_account_pin_reset) res.FlagReset = append(res.FlagReset, flag_account_pin_reset)
selfPinReset, err := store.ReadEntry(ctx, sessionId, storedb.DATA_SELF_PIN_RESET) selfPinReset, err := store.ReadEntry(ctx, sessionId, storedb.DATA_SELF_PIN_RESET)

View File

@ -5,7 +5,6 @@ import (
"testing" "testing"
"git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/resource"
"git.defalsify.org/vise.git/state"
"git.grassecon.net/grassrootseconomics/sarafu-api/models" "git.grassecon.net/grassrootseconomics/sarafu-api/models"
"git.grassecon.net/grassrootseconomics/sarafu-api/testutil/mocks" "git.grassecon.net/grassrootseconomics/sarafu-api/testutil/mocks"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
@ -94,24 +93,16 @@ func TestCheckBlockedStatus(t *testing.T) {
} }
flag_account_blocked, _ := fm.GetFlag("flag_account_blocked") flag_account_blocked, _ := fm.GetFlag("flag_account_blocked")
flag_account_pin_reset, _ := fm.GetFlag("flag_account_pin_reset") flag_account_pin_reset, _ := fm.GetFlag("flag_account_pin_reset")
flag_pin_set, _ := fm.GetFlag("flag_pin_set")
flag_language_set, _ := fm.GetFlag("flag_language_set")
// Set the flag in the State
mockState := state.NewState(128)
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
flagManager: fm, flagManager: fm,
st: mockState,
} }
tests := []struct { tests := []struct {
name string name string
currentWrongPinAttempts string currentWrongPinAttempts string
expectedResult resource.Result expectedResult resource.Result
languageSet bool
PinSet bool
}{ }{
{ {
name: "Currently blocked account", name: "Currently blocked account",
@ -127,16 +118,6 @@ func TestCheckBlockedStatus(t *testing.T) {
FlagReset: []uint32{flag_account_pin_reset, flag_account_blocked}, FlagReset: []uint32{flag_account_pin_reset, flag_account_blocked},
}, },
}, },
{
name: "Valid account with reset language and PIN flags",
currentWrongPinAttempts: "0",
languageSet: true,
PinSet: true,
expectedResult: resource.Result{
FlagReset: []uint32{flag_account_pin_reset, flag_account_blocked},
FlagSet: []uint32{flag_pin_set, flag_language_set},
},
},
} }
for _, tt := range tests { for _, tt := range tests {
@ -145,18 +126,6 @@ func TestCheckBlockedStatus(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if tt.languageSet {
if err := store.WriteEntry(ctx, sessionId, storedb.DATA_SELECTED_LANGUAGE_CODE, []byte("eng")); err != nil {
t.Fatal(err)
}
}
if tt.PinSet {
if err := store.WriteEntry(ctx, sessionId, storedb.DATA_ACCOUNT_PIN, []byte("hasedPinValue")); err != nil {
t.Fatal(err)
}
}
res, err := h.CheckBlockedStatus(ctx, "", []byte("")) res, err := h.CheckBlockedStatus(ctx, "", []byte(""))
assert.NoError(t, err) assert.NoError(t, err)

View File

@ -9,7 +9,6 @@ import (
"git.grassecon.net/grassrootseconomics/sarafu-vise/config" "git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"git.grassecon.net/grassrootseconomics/sarafu-vise/store" "git.grassecon.net/grassrootseconomics/sarafu-vise/store"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api"
"gopkg.in/leonelquinteros/gotext.v1" "gopkg.in/leonelquinteros/gotext.v1"
) )
@ -37,26 +36,9 @@ func (h *MenuHandlers) GetPools(ctx context.Context, sym string, input []byte) (
return res, nil return res, nil
} }
activePoolSymStr := "" data := store.ProcessPools(topPools)
activePoolSym, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_POOL_SYM) // Store all Pool data
if err != nil {
activePoolSymStr = config.DefaultPoolSymbol()
} else {
activePoolSymStr = string(activePoolSym)
}
// Filter out the active pool from topPools
filteredPools := make([]dataserviceapi.PoolDetails, 0, len(topPools))
for _, p := range topPools {
if p.PoolSymbol != activePoolSymStr {
filteredPools = append(filteredPools, p)
}
}
data := store.ProcessPools(filteredPools)
// Store the filtered Pool data
dataMap := map[storedb.DataTyp]string{ dataMap := map[storedb.DataTyp]string{
storedb.DATA_POOL_NAMES: data.PoolNames, storedb.DATA_POOL_NAMES: data.PoolNames,
storedb.DATA_POOL_SYMBOLS: data.PoolSymbols, storedb.DATA_POOL_SYMBOLS: data.PoolSymbols,
@ -118,10 +100,6 @@ func (h *MenuHandlers) ViewPool(ctx context.Context, sym string, input []byte) (
flag_incorrect_pool, _ := h.flagManager.GetFlag("flag_incorrect_pool") flag_incorrect_pool, _ := h.flagManager.GetFlag("flag_incorrect_pool")
inputStr := string(input) inputStr := string(input)
if inputStr == "0" || inputStr == "99" || inputStr == "88" || inputStr == "98" {
res.FlagReset = append(res.FlagReset, flag_incorrect_pool)
return res, nil
}
poolData, err := store.GetPoolData(ctx, h.userdataStore, sessionId, inputStr) poolData, err := store.GetPoolData(ctx, h.userdataStore, sessionId, inputStr)
if err != nil { if err != nil {

View File

@ -10,7 +10,6 @@ import (
"git.grassecon.net/grassrootseconomics/sarafu-vise/config" "git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"git.grassecon.net/grassrootseconomics/sarafu-vise/store" "git.grassecon.net/grassrootseconomics/sarafu-vise/store"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api"
"gopkg.in/leonelquinteros/gotext.v1" "gopkg.in/leonelquinteros/gotext.v1"
) )
@ -122,16 +121,7 @@ func (h *MenuHandlers) LoadSwapToList(ctx context.Context, sym string, input []b
return res, nil return res, nil
} }
// Filter out the active voucher from swapToList data := store.ProcessVouchers(swapToList)
filteredSwapToList := make([]dataserviceapi.TokenHoldings, 0, len(swapToList))
for _, s := range swapToList {
if s.TokenSymbol != string(activeSym) {
filteredSwapToList = append(filteredSwapToList, s)
}
}
// Store filtered swap to list data (excluding the current active voucher)
data := store.ProcessVouchers(filteredSwapToList)
logg.InfoCtxf(ctx, "ProcessVouchers", "data", data) logg.InfoCtxf(ctx, "ProcessVouchers", "data", data)
@ -171,7 +161,7 @@ func (h *MenuHandlers) SwapMaxLimit(ctx context.Context, sym string, input []byt
res.FlagReset = append(res.FlagReset, flag_incorrect_voucher, flag_low_swap_amount) res.FlagReset = append(res.FlagReset, flag_incorrect_voucher, flag_low_swap_amount)
inputStr := string(input) inputStr := string(input)
if inputStr == "0" || inputStr == "99" || inputStr == "88" || inputStr == "98" { if inputStr == "0" {
return res, nil return res, nil
} }

View File

@ -51,9 +51,6 @@ func (h *MenuHandlers) ManageVouchers(ctx context.Context, sym string, input []b
res.FlagReset = append(res.FlagReset, flag_no_active_voucher) res.FlagReset = append(res.FlagReset, flag_no_active_voucher)
// add a variable to filter out the active voucher
activeSymStr := ""
// Check if user has an active voucher with proper error handling // Check if user has an active voucher with proper error handling
activeSym, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_SYM) activeSym, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_SYM)
if err != nil { if err != nil {
@ -65,8 +62,6 @@ func (h *MenuHandlers) ManageVouchers(ctx context.Context, sym string, input []b
defaultDec := firstVoucher.TokenDecimals defaultDec := firstVoucher.TokenDecimals
defaultAddr := firstVoucher.TokenAddress defaultAddr := firstVoucher.TokenAddress
activeSymStr = defaultSym
// Scale down the balance // Scale down the balance
scaledBalance := store.ScaleDownBalance(defaultBal, defaultDec) scaledBalance := store.ScaleDownBalance(defaultBal, defaultDec)
@ -94,8 +89,10 @@ func (h *MenuHandlers) ManageVouchers(ctx context.Context, sym string, input []b
return res, err return res, err
} }
} else { } else {
// Update active voucher balance
activeSymStr := string(activeSym)
// Find the matching voucher data // Find the matching voucher data
activeSymStr = string(activeSym)
var activeData *dataserviceapi.TokenHoldings var activeData *dataserviceapi.TokenHoldings
for _, voucher := range vouchersResp { for _, voucher := range vouchersResp {
if voucher.TokenSymbol == activeSymStr { if voucher.TokenSymbol == activeSymStr {
@ -105,10 +102,9 @@ func (h *MenuHandlers) ManageVouchers(ctx context.Context, sym string, input []b
} }
if activeData == nil { if activeData == nil {
logg.InfoCtxf(ctx, "activeSym not found in vouchers, setting the first voucher as the default", "activeSym", activeSymStr) logg.ErrorCtxf(ctx, "activeSym not found in vouchers, setting the first voucher as the default", "activeSym", activeSymStr)
firstVoucher := vouchersResp[0] firstVoucher := vouchersResp[0]
activeData = &firstVoucher activeData = &firstVoucher
activeSymStr = string(activeData.TokenSymbol)
} }
// Scale down the balance // Scale down the balance
@ -124,17 +120,8 @@ func (h *MenuHandlers) ManageVouchers(ctx context.Context, sym string, input []b
} }
} }
// Filter out the active voucher from vouchersResp // Store all voucher data
filteredVouchers := make([]dataserviceapi.TokenHoldings, 0, len(vouchersResp)) data := store.ProcessVouchers(vouchersResp)
for _, v := range vouchersResp {
if v.TokenSymbol != activeSymStr {
filteredVouchers = append(filteredVouchers, v)
}
}
// Store all voucher data (excluding the current active voucher)
data := store.ProcessVouchers(filteredVouchers)
dataMap := map[storedb.DataTyp]string{ dataMap := map[storedb.DataTyp]string{
storedb.DATA_VOUCHER_SYMBOLS: data.Symbols, storedb.DATA_VOUCHER_SYMBOLS: data.Symbols,
storedb.DATA_VOUCHER_BALANCES: data.Balances, storedb.DATA_VOUCHER_BALANCES: data.Balances,
@ -153,7 +140,7 @@ func (h *MenuHandlers) ManageVouchers(ctx context.Context, sym string, input []b
return res, nil return res, nil
} }
// GetVoucherList fetches the list of vouchers from the store and formats them. // GetVoucherList fetches the list of vouchers and formats them.
func (h *MenuHandlers) GetVoucherList(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *MenuHandlers) GetVoucherList(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
sessionId, ok := ctx.Value("SessionId").(string) sessionId, ok := ctx.Value("SessionId").(string)
@ -204,10 +191,6 @@ func (h *MenuHandlers) ViewVoucher(ctx context.Context, sym string, input []byte
flag_incorrect_voucher, _ := h.flagManager.GetFlag("flag_incorrect_voucher") flag_incorrect_voucher, _ := h.flagManager.GetFlag("flag_incorrect_voucher")
inputStr := string(input) inputStr := string(input)
if inputStr == "0" || inputStr == "99" || inputStr == "88" || inputStr == "98" {
res.FlagReset = append(res.FlagReset, flag_incorrect_voucher)
return res, nil
}
metadata, err := store.GetVoucherData(ctx, h.userdataStore, sessionId, inputStr) metadata, err := store.GetVoucherData(ctx, h.userdataStore, sessionId, inputStr)
if err != nil { if err != nil {
@ -224,16 +207,8 @@ func (h *MenuHandlers) ViewVoucher(ctx context.Context, sym string, input []byte
return res, err return res, err
} }
// Format the balance to 2 decimal places
formattedAmount, err := store.TruncateDecimalString(metadata.Balance, 2)
if err != nil {
logg.ErrorCtxf(ctx, "failed to TruncateDecimalString on ViewVoucher", "error", err)
res.FlagSet = append(res.FlagSet, flag_incorrect_voucher)
return res, nil
}
res.FlagReset = append(res.FlagReset, flag_incorrect_voucher) res.FlagReset = append(res.FlagReset, flag_incorrect_voucher)
res.Content = l.Get("Symbol: %s\nBalance: %s", metadata.TokenSymbol, formattedAmount) res.Content = l.Get("Symbol: %s\nBalance: %s", metadata.TokenSymbol, metadata.Balance)
return res, nil return res, nil
} }
@ -289,11 +264,8 @@ func (h *MenuHandlers) GetVoucherDetails(ctx context.Context, sym string, input
} }
res.FlagReset = append(res.FlagReset, flag_api_error) res.FlagReset = append(res.FlagReset, flag_api_error)
// sanitize invalid characters
symbol := strings.ReplaceAll(voucherData.TokenSymbol, "USD₮", "USDT")
res.Content = fmt.Sprintf( res.Content = fmt.Sprintf(
"Name: %s\nSymbol: %s\nProduct: %s\nLocation: %s", voucherData.TokenName, symbol, voucherData.TokenCommodity, voucherData.TokenLocation, "Name: %s\nSymbol: %s\nCommodity: %s\nLocation: %s", voucherData.TokenName, voucherData.TokenSymbol, voucherData.TokenCommodity, voucherData.TokenLocation,
) )
return res, nil return res, nil

View File

@ -73,8 +73,8 @@ func TestManageVouchers(t *testing.T) {
Balance: "100", Balance: "100",
}, },
}, },
expectedVoucherSymbols: []byte(""), expectedVoucherSymbols: []byte("1:TOKEN1"),
expectedUpdatedAddress: []byte(""), expectedUpdatedAddress: []byte("0x123"),
expectedResult: resource.Result{ expectedResult: resource.Result{
FlagReset: []uint32{flag_api_error, flag_no_active_voucher}, FlagReset: []uint32{flag_api_error, flag_no_active_voucher},
}, },
@ -86,7 +86,7 @@ func TestManageVouchers(t *testing.T) {
{TokenAddress: "0x41c188d63Qa", TokenSymbol: "MILO", TokenDecimals: "4", Balance: "200"}, {TokenAddress: "0x41c188d63Qa", TokenSymbol: "MILO", TokenDecimals: "4", Balance: "200"},
}, },
storedActiveVoucher: "SRF", storedActiveVoucher: "SRF",
expectedVoucherSymbols: []byte("1:MILO"), expectedVoucherSymbols: []byte("1:SRF\n2:MILO"),
expectedUpdatedAddress: []byte("0xd4c288865Ce"), expectedUpdatedAddress: []byte("0xd4c288865Ce"),
expectedResult: resource.Result{ expectedResult: resource.Result{
FlagReset: []uint32{flag_api_error, flag_no_active_voucher}, FlagReset: []uint32{flag_api_error, flag_no_active_voucher},
@ -272,7 +272,7 @@ func TestGetVoucherDetails(t *testing.T) {
TokenCommodity: "Farming", TokenCommodity: "Farming",
} }
expectedResult.Content = fmt.Sprintf( expectedResult.Content = fmt.Sprintf(
"Name: %s\nSymbol: %s\nProduct: %s\nLocation: %s", tokenDetails.TokenName, tokenDetails.TokenSymbol, tokenDetails.TokenCommodity, tokenDetails.TokenLocation, "Name: %s\nSymbol: %s\nCommodity: %s\nLocation: %s", tokenDetails.TokenName, tokenDetails.TokenSymbol, tokenDetails.TokenCommodity, tokenDetails.TokenLocation,
) )
mockAccountService.On("VoucherData", string(tokA_AAddress)).Return(tokenDetails, nil) mockAccountService.On("VoucherData", string(tokA_AAddress)).Return(tokenDetails, nil)
res, err := h.GetVoucherDetails(ctx, "SessionId", []byte("")) res, err := h.GetVoucherDetails(ctx, "SessionId", []byte(""))

View File

@ -9,16 +9,14 @@ MAP check_balance
MOUT send 1 MOUT send 1
MOUT swap 2 MOUT swap 2
MOUT vouchers 3 MOUT vouchers 3
MOUT select_pool 4 MOUT account 4
MOUT account 5 MOUT help 5
MOUT help 6
MOUT quit 9 MOUT quit 9
HALT HALT
INCMP send 1 INCMP send 1
INCMP swap_to_list 2 INCMP swap_to_list 2
INCMP my_vouchers 3 INCMP my_vouchers 3
INCMP select_pool 4 INCMP my_account 4
INCMP my_account 5 INCMP help 5
INCMP help 6
INCMP quit 9 INCMP quit 9
INCMP . * INCMP . *

View File

@ -2,9 +2,11 @@ LOAD reset_account_authorized 16
RELOAD reset_account_authorized RELOAD reset_account_authorized
MOUT select_voucher 1 MOUT select_voucher 1
MOUT voucher_details 2 MOUT voucher_details 2
MOUT select_pool 3
MOUT back 0 MOUT back 0
HALT HALT
INCMP _ 0 INCMP _ 0
INCMP select_voucher 1 INCMP select_voucher 1
INCMP voucher_details 2 INCMP voucher_details 2
INCMP select_pool 3
INCMP . * INCMP . *

View File

@ -4,17 +4,11 @@ RELOAD swap_to_list
MAP swap_to_list MAP swap_to_list
CATCH missing_voucher flag_incorrect_voucher 1 CATCH missing_voucher flag_incorrect_voucher 1
MOUT back 0 MOUT back 0
MOUT quit 99
MNEXT next 88
MPREV prev 98
HALT HALT
INCMP > 88
INCMP < 98
INCMP _ 0
INCMP quit 99
LOAD swap_max_limit 64 LOAD swap_max_limit 64
RELOAD swap_max_limit RELOAD swap_max_limit
CATCH api_failure flag_api_call_error 1 CATCH api_failure flag_api_call_error 1
CATCH . flag_incorrect_voucher 1 CATCH . flag_incorrect_voucher 1
CATCH low_swap_amount flag_low_swap_amount 1 CATCH low_swap_amount flag_low_swap_amount 1
INCMP _ 0
INCMP swap_limit * INCMP swap_limit *

View File

@ -15,11 +15,6 @@ var (
logg = logging.NewVanilla().WithDomain("vouchers").WithContextKey("SessionId") logg = logging.NewVanilla().WithDomain("vouchers").WithContextKey("SessionId")
) )
// symbolReplacements holds mappings of invalid symbols → valid ones
var symbolReplacements = map[string]string{
"USD₮": "USDT",
}
// VoucherMetadata helps organize data fields // VoucherMetadata helps organize data fields
type VoucherMetadata struct { type VoucherMetadata struct {
Symbols string Symbols string
@ -28,24 +23,13 @@ type VoucherMetadata struct {
Addresses string Addresses string
} }
// sanitizeSymbol replaces known invalid token symbols with normalized ones
func sanitizeSymbol(symbol string) string {
if replacement, ok := symbolReplacements[symbol]; ok {
return replacement
}
return symbol
}
// ProcessVouchers converts holdings into formatted strings // ProcessVouchers converts holdings into formatted strings
func ProcessVouchers(holdings []dataserviceapi.TokenHoldings) VoucherMetadata { func ProcessVouchers(holdings []dataserviceapi.TokenHoldings) VoucherMetadata {
var data VoucherMetadata var data VoucherMetadata
var symbols, balances, decimals, addresses []string var symbols, balances, decimals, addresses []string
for i, h := range holdings { for i, h := range holdings {
// normalize token symbol before use symbols = append(symbols, fmt.Sprintf("%d:%s", i+1, h.TokenSymbol))
cleanSymbol := sanitizeSymbol(h.TokenSymbol)
symbols = append(symbols, fmt.Sprintf("%d:%s", i+1, cleanSymbol))
// Scale down the balance // Scale down the balance
scaledBalance := ScaleDownBalance(h.Balance, h.TokenDecimals) scaledBalance := ScaleDownBalance(h.Balance, h.TokenDecimals)

View File

@ -61,14 +61,13 @@ func TestProcessVouchers(t *testing.T) {
holdings := []dataserviceapi.TokenHoldings{ holdings := []dataserviceapi.TokenHoldings{
{TokenAddress: "0xd4c288865Ce", TokenSymbol: "SRF", TokenDecimals: "6", Balance: "100000000"}, {TokenAddress: "0xd4c288865Ce", TokenSymbol: "SRF", TokenDecimals: "6", Balance: "100000000"},
{TokenAddress: "0x41c188d63Qa", TokenSymbol: "MILO", TokenDecimals: "4", Balance: "200000000"}, {TokenAddress: "0x41c188d63Qa", TokenSymbol: "MILO", TokenDecimals: "4", Balance: "200000000"},
{TokenAddress: "0x41c143d63Qa", TokenSymbol: "USD₮", TokenDecimals: "6", Balance: "300000000"},
} }
expectedResult := VoucherMetadata{ expectedResult := VoucherMetadata{
Symbols: "1:SRF\n2:MILO\n3:USDT", Symbols: "1:SRF\n2:MILO",
Balances: "1:100\n2:20000\n3:300", Balances: "1:100\n2:20000",
Decimals: "1:6\n2:4\n3:6", Decimals: "1:6\n2:4",
Addresses: "1:0xd4c288865Ce\n2:0x41c188d63Qa\n3:0x41c143d63Qa", Addresses: "1:0xd4c288865Ce\n2:0x41c188d63Qa",
} }
result := ProcessVouchers(holdings) result := ProcessVouchers(holdings)