From 12213724244c15e9bede7a07d1b667cd903e4137 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 26 Feb 2025 13:07:11 +0300 Subject: [PATCH 01/33] use latest ussd-data-service package --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index a75e399..898e661 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 github.com/alecthomas/assert/v2 v2.2.2 github.com/gofrs/uuid v4.4.0+incompatible - github.com/grassrootseconomics/ussd-data-service v1.2.0-beta + github.com/grassrootseconomics/ussd-data-service v1.4.0-beta github.com/jackc/pgx/v5 v5.7.1 github.com/peteole/testdata-loader v0.3.0 github.com/stretchr/testify v1.9.0 diff --git a/go.sum b/go.sum index 1cd58c7..bec01de 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,8 @@ github.com/grassrootseconomics/eth-custodial v1.3.0-beta h1:twrMBhl89GqDUL9PlkzQ github.com/grassrootseconomics/eth-custodial v1.3.0-beta/go.mod h1:7uhRcdnJplX4t6GKCEFkbeDhhjlcaGJeJqevbcvGLZo= github.com/grassrootseconomics/ussd-data-service v1.2.0-beta h1:fn1gwbWIwHVEBtUC2zi5OqTlfI/5gU1SMk0fgGixIXk= github.com/grassrootseconomics/ussd-data-service v1.2.0-beta/go.mod h1:omfI0QtUwIdpu9gMcUqLMCG8O1XWjqJGBx1qUMiGWC0= +github.com/grassrootseconomics/ussd-data-service v1.4.0-beta h1:4fMd/3h2ZIhRg4GdHQmRw5FfD3MpJvFNNJQo+Q27f5M= +github.com/grassrootseconomics/ussd-data-service v1.4.0-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= -- 2.45.2 From c5dbe966c447a4216bc990f43b2706cbd7eed997 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 26 Feb 2025 13:08:00 +0300 Subject: [PATCH 02/33] added flag_incorrect_pool flag --- services/registration/pp.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/registration/pp.csv b/services/registration/pp.csv index aa1eb05..03c61dd 100644 --- a/services/registration/pp.csv +++ b/services/registration/pp.csv @@ -29,4 +29,4 @@ flag,flag_location_set,35,this is set when the location of the profile is set flag,flag_offerings_set,36,this is set when the offerings of the profile is set flag,flag_back_set,37,this is set when it is a back navigation flag,flag_account_blocked,38,this is set when an account has been blocked after the allowed incorrect PIN attempts have been exceeded - +flag,flag_incorrect_pool,39,this is set when the user selects an invalid pool -- 2.45.2 From 566503956d0ef96e7a1ddf7625007c7d50e4a5ed Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 26 Feb 2025 13:09:29 +0300 Subject: [PATCH 03/33] added pool_swap menu nodes --- handlers/local.go | 3 +++ services/registration/main.vis | 6 ++++-- services/registration/pool_swap | 2 ++ services/registration/pool_swap.vis | 8 ++++++++ services/registration/pool_swap_swa | 2 ++ services/registration/swap_from_list | 2 ++ services/registration/swap_from_list.vis | 7 +++++++ services/registration/swap_from_list_swa | 2 ++ services/registration/swap_to_list | 2 ++ services/registration/swap_to_list.vis | 7 +++++++ services/registration/swap_to_list_swa | 2 ++ 11 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 services/registration/pool_swap create mode 100644 services/registration/pool_swap.vis create mode 100644 services/registration/pool_swap_swa create mode 100644 services/registration/swap_from_list create mode 100644 services/registration/swap_from_list.vis create mode 100644 services/registration/swap_from_list_swa create mode 100644 services/registration/swap_to_list create mode 100644 services/registration/swap_to_list.vis create mode 100644 services/registration/swap_to_list_swa diff --git a/handlers/local.go b/handlers/local.go index 7d66c7d..d4b7eeb 100644 --- a/handlers/local.go +++ b/handlers/local.go @@ -124,6 +124,9 @@ func (ls *LocalHandlerService) GetHandler(accountService remote.AccountService) ls.DbRs.AddLocalFunc("set_back", appHandlers.SetBack) ls.DbRs.AddLocalFunc("show_blocked_account", appHandlers.ShowBlockedAccount) ls.DbRs.AddLocalFunc("clear_temporary_value", appHandlers.ClearTemporaryValue) + ls.DbRs.AddLocalFunc("get_pools", appHandlers.GetPools) + ls.DbRs.AddLocalFunc("swap_from_list", appHandlers.LoadSwapFromList) + ls.DbRs.AddLocalFunc("swap_to_list", appHandlers.LoadSwapToList) ls.first = appHandlers.Init return appHandlers, nil diff --git a/services/registration/main.vis b/services/registration/main.vis index 5996c97..d80acc9 100644 --- a/services/registration/main.vis +++ b/services/registration/main.vis @@ -9,13 +9,15 @@ RELOAD check_balance CATCH api_failure flag_api_call_error 1 MAP check_balance MOUT send 1 -MOUT vouchers 2 +MOUT swap 2 +MOUT vouchers 3 MOUT account 3 MOUT help 4 MOUT quit 9 HALT INCMP send 1 -INCMP my_vouchers 2 +INCMP pool_swap 2 +INCMP my_vouchers 3 INCMP my_account 3 INCMP help 4 INCMP quit 9 diff --git a/services/registration/pool_swap b/services/registration/pool_swap new file mode 100644 index 0000000..21d0739 --- /dev/null +++ b/services/registration/pool_swap @@ -0,0 +1,2 @@ +Enter number or pool symbol to swap from: +{{.get_pools}} \ No newline at end of file diff --git a/services/registration/pool_swap.vis b/services/registration/pool_swap.vis new file mode 100644 index 0000000..dd98b0d --- /dev/null +++ b/services/registration/pool_swap.vis @@ -0,0 +1,8 @@ +LOAD get_pools 100 +MAP get_pools +MOUT back 0 +MOUT quit 99 +HALT +INCMP _ 0 +INCMP quit 99 +INCMP swap_from_list * diff --git a/services/registration/pool_swap_swa b/services/registration/pool_swap_swa new file mode 100644 index 0000000..e12dc90 --- /dev/null +++ b/services/registration/pool_swap_swa @@ -0,0 +1,2 @@ +Chagua bwawa la sarafu la kubadilishana: +{{.get_pools}} \ No newline at end of file diff --git a/services/registration/swap_from_list b/services/registration/swap_from_list new file mode 100644 index 0000000..e0cc3d2 --- /dev/null +++ b/services/registration/swap_from_list @@ -0,0 +1,2 @@ +Select number or symbol to swap FROM: +{{.swap_from_list}} \ No newline at end of file diff --git a/services/registration/swap_from_list.vis b/services/registration/swap_from_list.vis new file mode 100644 index 0000000..e316e6e --- /dev/null +++ b/services/registration/swap_from_list.vis @@ -0,0 +1,7 @@ +LOAD swap_from_list 0 +CATCH _ flag_incorrect_pool 1 +MAP swap_from_list +MOUT back 0 +HALT +INCMP _ 0 +INCMP swap_to_list * diff --git a/services/registration/swap_from_list_swa b/services/registration/swap_from_list_swa new file mode 100644 index 0000000..ef716fd --- /dev/null +++ b/services/registration/swap_from_list_swa @@ -0,0 +1,2 @@ +Chagua nambari au ishara ya sarafu kubadilisha KUTOKA: +{{.swap_from_list}} \ No newline at end of file diff --git a/services/registration/swap_to_list b/services/registration/swap_to_list new file mode 100644 index 0000000..86f56c3 --- /dev/null +++ b/services/registration/swap_to_list @@ -0,0 +1,2 @@ +Select number or symbol to swap TO: +{{.swap_to_list}} \ No newline at end of file diff --git a/services/registration/swap_to_list.vis b/services/registration/swap_to_list.vis new file mode 100644 index 0000000..e420a69 --- /dev/null +++ b/services/registration/swap_to_list.vis @@ -0,0 +1,7 @@ +LOAD swap_to_list 0 +CATCH _ flag_incorrect_voucher 1 +MAP swap_to_list +MOUT back 0 +HALT +INCMP _ 0 +INCMP swap_limit * diff --git a/services/registration/swap_to_list_swa b/services/registration/swap_to_list_swa new file mode 100644 index 0000000..42da7d3 --- /dev/null +++ b/services/registration/swap_to_list_swa @@ -0,0 +1,2 @@ +Chagua nambari au ishara ya sarafu kubadilisha KWENDA: +{{.swap_to_list}} \ No newline at end of file -- 2.45.2 From e8978413a5bfe294801108ba95a97054f4cb3311 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 26 Feb 2025 13:10:15 +0300 Subject: [PATCH 04/33] added pool db processing --- store/db/db.go | 9 +++++++++ store/pools.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 store/pools.go diff --git a/store/db/db.go b/store/db/db.go index 10f360a..923d0b7 100644 --- a/store/db/db.go +++ b/store/db/db.go @@ -101,6 +101,15 @@ const ( DATA_TRANSACTIONS = 1024 + iota ) +const ( + // List of voucher symbols in the top pools context. + DATA_POOL_NAMES = 2048 + iota + // List of symbols in the top pools context. + DATA_POOL_SYMBOLS + // List of contact addresses in the top pools context + DATA_POOL_ADDRESSES +) + var ( logg = logging.NewVanilla().WithDomain("urdt-common") ) diff --git a/store/pools.go b/store/pools.go new file mode 100644 index 0000000..f21ee30 --- /dev/null +++ b/store/pools.go @@ -0,0 +1,33 @@ +package store + +import ( + "fmt" + "strings" + + dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" +) + +// PoolsMetadata helps organize data fields +type PoolsMetadata struct { + PoolNames string + PoolSymbols string + PoolContractAdrresses string +} + +// ProcessPools converts pools into formatted strings +func ProcessPools(pools []dataserviceapi.PoolDetails) PoolsMetadata { + var data PoolsMetadata + var poolNames, poolSymbols, poolContractAdrresses []string + + for i, p := range pools { + poolNames = append(poolNames, fmt.Sprintf("%d:%s", i+1, p.PoolName)) + poolSymbols = append(poolSymbols, fmt.Sprintf("%d:%s", i+1, p.PoolSymbol)) + poolContractAdrresses = append(poolContractAdrresses, fmt.Sprintf("%d:%s", i+1, p.PoolContractAdrress)) + } + + data.PoolNames = strings.Join(poolNames, "\n") + data.PoolSymbols = strings.Join(poolSymbols, "\n") + data.PoolContractAdrresses = strings.Join(poolContractAdrresses, "\n") + + return data +} -- 2.45.2 From cb1d129edad054beebc7ca447794a782939f9a82 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Tue, 4 Mar 2025 21:18:25 +0300 Subject: [PATCH 05/33] added swap db keys --- store/db/db.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/store/db/db.go b/store/db/db.go index 923d0b7..50a09cd 100644 --- a/store/db/db.go +++ b/store/db/db.go @@ -63,6 +63,24 @@ const ( DATA_INITIAL_LANGUAGE_CODE //Fully qualified account alias string DATA_ACCOUNT_ALIAS + // Holds the active pool contract address for the swap + DATA_ACTIVE_POOL_ADDRESS + // Currently active swap from symbol for the swap + DATA_ACTIVE_SWAP_FROM_SYM + // Currently active swap from decimal count for the swap + DATA_ACTIVE_SWAP_FROM_DECIMAL + // Holds the active swap from contract address for the swap + DATA_ACTIVE_SWAP_FROM_ADDRESS + // Currently active swap from to for the swap + DATA_ACTIVE_SWAP_TO_SYM + // Currently active swap to decimal count for the swap + DATA_ACTIVE_SWAP_TO_DECIMAL + // Holds the active pool contract address for the swap + DATA_ACTIVE_SWAP_TO_ADDRESS + // Holds the max swap amount for the swap + DATA_ACTIVE_SWAP_MAX_AMOUNT + // Holds the active swap amount for the swap + DATA_ACTIVE_SWAP_AMOUNT ) const ( @@ -108,6 +126,22 @@ const ( DATA_POOL_SYMBOLS // List of contact addresses in the top pools context DATA_POOL_ADDRESSES + // List of swap from voucher symbols in the user context. + DATA_POOL_FROM_SYMBOLS + // List of swap from balances for vouchers valid in the pools context. + DATA_POOL_FROM_BALANCES + // List of swap from decimal counts for vouchers valid in the pools context. + DATA_POOL_FROM_DECIMALS + // List of swap from EVM addresses for vouchers valid in the pools context. + DATA_POOL_FROM_ADDRESSES + // List of swap to voucher symbols in the user context. + DATA_POOL_TO_SYMBOLS + // List of swap to balances for vouchers valid in the pools context. + DATA_POOL_TO_BALANCES + // List of swap to decimal counts for vouchers valid in the pools context. + DATA_POOL_TO_DECIMALS + // List of swap to EVM addresses for vouchers valid in the pools context. + DATA_POOL_TO_ADDRESSES ) var ( -- 2.45.2 From ee07bf11f850ac79a7f04c375fcdbb6b0acded75 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Tue, 4 Mar 2025 21:20:05 +0300 Subject: [PATCH 06/33] added helper functions to process the swap to and swap from voucher data --- store/swap_from_vouchers.go | 65 +++++++++++++++++++++++++++++++++++++ store/swap_to_vouchers.go | 65 +++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 store/swap_from_vouchers.go create mode 100644 store/swap_to_vouchers.go diff --git a/store/swap_from_vouchers.go b/store/swap_from_vouchers.go new file mode 100644 index 0000000..f15962a --- /dev/null +++ b/store/swap_from_vouchers.go @@ -0,0 +1,65 @@ +package store + +import ( + "context" + "fmt" + storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" + dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" +) + +// GetSwapFromVoucherData retrieves and matches swap from voucher data +func GetSwapFromVoucherData(ctx context.Context, db storedb.PrefixDb, input string) (*dataserviceapi.TokenHoldings, error) { + keys := []storedb.DataTyp{ + storedb.DATA_POOL_FROM_SYMBOLS, + storedb.DATA_POOL_FROM_BALANCES, + storedb.DATA_POOL_FROM_DECIMALS, + storedb.DATA_POOL_FROM_ADDRESSES, + } + data := make(map[storedb.DataTyp]string) + + for _, key := range keys { + value, err := db.Get(ctx, storedb.ToBytes(key)) + if err != nil { + return nil, fmt.Errorf("failed to get prefix key %x: %v", storedb.ToBytes(key), err) + } + data[key] = string(value) + } + + symbol, balance, decimal, address := MatchVoucher(input, + data[storedb.DATA_POOL_FROM_SYMBOLS], + data[storedb.DATA_POOL_FROM_BALANCES], + data[storedb.DATA_POOL_FROM_DECIMALS], + data[storedb.DATA_POOL_FROM_ADDRESSES], + ) + + if symbol == "" { + return nil, nil + } + + return &dataserviceapi.TokenHoldings{ + TokenSymbol: string(symbol), + Balance: string(balance), + TokenDecimals: string(decimal), + ContractAddress: string(address), + }, nil +} + +// UpdateSwapFromVoucherData updates the active swap to voucher data in the DataStore. +func UpdateSwapFromVoucherData(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { + logg.TraceCtxf(ctx, "dtal", "data", data) + // Active swap from voucher data entries + activeEntries := map[storedb.DataTyp][]byte{ + storedb.DATA_ACTIVE_SWAP_FROM_SYM: []byte(data.TokenSymbol), + storedb.DATA_ACTIVE_SWAP_FROM_DECIMAL: []byte(data.TokenDecimals), + storedb.DATA_ACTIVE_SWAP_FROM_ADDRESS: []byte(data.ContractAddress), + } + + // Write active data + for key, value := range activeEntries { + if err := store.WriteEntry(ctx, sessionId, key, value); err != nil { + return err + } + } + + return nil +} diff --git a/store/swap_to_vouchers.go b/store/swap_to_vouchers.go new file mode 100644 index 0000000..f74deac --- /dev/null +++ b/store/swap_to_vouchers.go @@ -0,0 +1,65 @@ +package store + +import ( + "context" + "fmt" + storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" + dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" +) + +// GetSwapToVoucherData retrieves and matches voucher data +func GetSwapToVoucherData(ctx context.Context, db storedb.PrefixDb, input string) (*dataserviceapi.TokenHoldings, error) { + keys := []storedb.DataTyp{ + storedb.DATA_POOL_TO_SYMBOLS, + storedb.DATA_POOL_TO_BALANCES, + storedb.DATA_POOL_TO_DECIMALS, + storedb.DATA_POOL_TO_ADDRESSES, + } + data := make(map[storedb.DataTyp]string) + + for _, key := range keys { + value, err := db.Get(ctx, storedb.ToBytes(key)) + if err != nil { + return nil, fmt.Errorf("failed to get prefix key %x: %v", storedb.ToBytes(key), err) + } + data[key] = string(value) + } + + symbol, balance, decimal, address := MatchVoucher(input, + data[storedb.DATA_POOL_TO_SYMBOLS], + data[storedb.DATA_POOL_TO_BALANCES], + data[storedb.DATA_POOL_TO_DECIMALS], + data[storedb.DATA_POOL_TO_ADDRESSES], + ) + + if symbol == "" { + return nil, nil + } + + return &dataserviceapi.TokenHoldings{ + TokenSymbol: string(symbol), + Balance: string(balance), + TokenDecimals: string(decimal), + ContractAddress: string(address), + }, nil +} + +// UpdateSwapToVoucherData updates the active swap to voucher data in the DataStore. +func UpdateSwapToVoucherData(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { + logg.TraceCtxf(ctx, "dtal", "data", data) + // Active swap to voucher data entries + activeEntries := map[storedb.DataTyp][]byte{ + storedb.DATA_ACTIVE_SWAP_TO_SYM: []byte(data.TokenSymbol), + storedb.DATA_ACTIVE_SWAP_TO_DECIMAL: []byte(data.TokenDecimals), + storedb.DATA_ACTIVE_SWAP_TO_ADDRESS: []byte(data.ContractAddress), + } + + // Write active data + for key, value := range activeEntries { + if err := store.WriteEntry(ctx, sessionId, key, value); err != nil { + return err + } + } + + return nil +} -- 2.45.2 From a1f0e4dcfed1bdbca12f4dba53fce5f062a26c43 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Tue, 4 Mar 2025 21:21:02 +0300 Subject: [PATCH 07/33] added functions to process the pool data and match based on the provided input --- store/pools.go | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/store/pools.go b/store/pools.go index f21ee30..39e3966 100644 --- a/store/pools.go +++ b/store/pools.go @@ -1,9 +1,11 @@ package store import ( + "context" "fmt" "strings" + storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" ) @@ -31,3 +33,61 @@ func ProcessPools(pools []dataserviceapi.PoolDetails) PoolsMetadata { return data } + +// GetPoolData retrieves and matches pool data +// if no match is found, it fetches the API with the symbol +func GetPoolData(ctx context.Context, db storedb.PrefixDb, input string) (*dataserviceapi.PoolDetails, error) { + keys := []storedb.DataTyp{ + storedb.DATA_POOL_NAMES, + storedb.DATA_POOL_SYMBOLS, + storedb.DATA_POOL_ADDRESSES, + } + data := make(map[storedb.DataTyp]string) + + for _, key := range keys { + value, err := db.Get(ctx, storedb.ToBytes(key)) + if err != nil { + return nil, fmt.Errorf("failed to get prefix key %x: %v", storedb.ToBytes(key), err) + } + data[key] = string(value) + } + + name, symbol, address := MatchPool(input, + data[storedb.DATA_POOL_NAMES], + data[storedb.DATA_POOL_SYMBOLS], + data[storedb.DATA_POOL_ADDRESSES], + ) + + if symbol == "" { + return nil, nil + } + + return &dataserviceapi.PoolDetails{ + PoolName: string(name), + PoolSymbol: string(symbol), + PoolContractAdrress: string(address), + }, nil +} + +// MatchPool finds the matching pool name, symbol and pool contract address based on the input. +func MatchPool(input, names, symbols, addresses string) (name, symbol, address string) { + nameList := strings.Split(names, "\n") + symList := strings.Split(symbols, "\n") + addrList := strings.Split(addresses, "\n") + + for i, sym := range symList { + parts := strings.SplitN(sym, ":", 2) + + if input == parts[0] || strings.EqualFold(input, parts[1]) { + symbol = parts[1] + if i < len(nameList) { + name = strings.SplitN(nameList[i], ":", 2)[1] + } + if i < len(addrList) { + address = strings.SplitN(addrList[i], ":", 2)[1] + } + break + } + } + return +} -- 2.45.2 From 2a2d43c279592b48fb33787e06b822cf0700b84f Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Tue, 4 Mar 2025 21:21:40 +0300 Subject: [PATCH 08/33] added the swap limit vis files --- services/registration/swap_limit | 1 + services/registration/swap_limit.vis | 7 +++++++ services/registration/swap_limit_swa | 1 + 3 files changed, 9 insertions(+) create mode 100644 services/registration/swap_limit create mode 100644 services/registration/swap_limit.vis create mode 100644 services/registration/swap_limit_swa diff --git a/services/registration/swap_limit b/services/registration/swap_limit new file mode 100644 index 0000000..4c9797c --- /dev/null +++ b/services/registration/swap_limit @@ -0,0 +1 @@ +{{.swap_max_limit}} \ No newline at end of file diff --git a/services/registration/swap_limit.vis b/services/registration/swap_limit.vis new file mode 100644 index 0000000..fe116ce --- /dev/null +++ b/services/registration/swap_limit.vis @@ -0,0 +1,7 @@ +LOAD swap_max_limit 0 +CATCH _ flag_incorrect_voucher 1 +MAP swap_max_limit +MOUT back 0 +HALT +INCMP _ 0 +INCMP swap_preview * diff --git a/services/registration/swap_limit_swa b/services/registration/swap_limit_swa new file mode 100644 index 0000000..4c9797c --- /dev/null +++ b/services/registration/swap_limit_swa @@ -0,0 +1 @@ +{{.swap_max_limit}} \ No newline at end of file -- 2.45.2 From 3e9a67b34e279ee97b8838452a23fb853ac15894 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Tue, 4 Mar 2025 21:21:59 +0300 Subject: [PATCH 09/33] added the swap preview vis files --- services/registration/swap_preview | 3 +++ services/registration/swap_preview.vis | 11 +++++++++++ services/registration/swap_preview_swa | 3 +++ 3 files changed, 17 insertions(+) create mode 100644 services/registration/swap_preview create mode 100644 services/registration/swap_preview.vis create mode 100644 services/registration/swap_preview_swa diff --git a/services/registration/swap_preview b/services/registration/swap_preview new file mode 100644 index 0000000..fb008e4 --- /dev/null +++ b/services/registration/swap_preview @@ -0,0 +1,3 @@ +{{.swap_preview}} + +Please enter your PIN to confirm: \ No newline at end of file diff --git a/services/registration/swap_preview.vis b/services/registration/swap_preview.vis new file mode 100644 index 0000000..606913a --- /dev/null +++ b/services/registration/swap_preview.vis @@ -0,0 +1,11 @@ +LOAD swap_preview 0 +MAP swap_preview +MOUT back 0 +MOUT quit 9 +LOAD authorize_account 6 +HALT +RELOAD authorize_account +CATCH incorrect_pin flag_incorrect_pin 1 +INCMP _ 0 +INCMP quit 9 +INCMP swap_initiated * diff --git a/services/registration/swap_preview_swa b/services/registration/swap_preview_swa new file mode 100644 index 0000000..4c6d567 --- /dev/null +++ b/services/registration/swap_preview_swa @@ -0,0 +1,3 @@ +{{.swap_preview}} + +Tafadhali weka PIN yako kudhibitisha: \ No newline at end of file -- 2.45.2 From 28eefb619704e0d2053487d4dc589e49b8734e97 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 5 Mar 2025 16:36:37 +0300 Subject: [PATCH 10/33] make the ReadStringEntry func accessible --- store/tokens.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/store/tokens.go b/store/tokens.go index 7c3ad0c..a7770c7 100644 --- a/store/tokens.go +++ b/store/tokens.go @@ -64,7 +64,7 @@ func ReadTransactionData(ctx context.Context, store DataStore, sessionId string) return data, errors.New("invalid struct field: " + fieldName) } - value, err := readStringEntry(ctx, store, sessionId, key) + value, err := ReadStringEntry(ctx, store, sessionId, key) if err != nil { return data, err } @@ -74,7 +74,7 @@ func ReadTransactionData(ctx context.Context, store DataStore, sessionId string) return data, nil } -func readStringEntry(ctx context.Context, store DataStore, sessionId string, key storedb.DataTyp) (string, error) { +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 -- 2.45.2 From a21186bd593ba5004447ce4c4288e00f97bf6156 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 5 Mar 2025 17:00:44 +0300 Subject: [PATCH 11/33] use a single swap.go file for swap helper functions --- store/swap.go | 207 ++++++++++++++++++++++++++++++++++++ store/swap_from_vouchers.go | 65 ----------- store/swap_to_vouchers.go | 65 ----------- 3 files changed, 207 insertions(+), 130 deletions(-) create mode 100644 store/swap.go delete mode 100644 store/swap_from_vouchers.go delete mode 100644 store/swap_to_vouchers.go diff --git a/store/swap.go b/store/swap.go new file mode 100644 index 0000000..49fb561 --- /dev/null +++ b/store/swap.go @@ -0,0 +1,207 @@ +package store + +import ( + "context" + "errors" + "fmt" + "reflect" + + storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" + dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" +) + +type SwapData struct { + PublicKey string + ActivePoolAddress string + ActiveSwapFromSym string + ActiveSwapFromDecimal string + ActiveSwapFromAddress string + ActiveSwapToSym string + ActiveSwapToAddress string +} + +type SwapPreviewData struct { + PublicKey string + ActiveSwapMaxAmount string + ActiveSwapFromDecimal string + ActivePoolAddress string + ActiveSwapFromAddress string + ActiveSwapFromSym string + ActiveSwapToAddress string + ActiveSwapToSym string + ActiveSwapToDecimal string +} + +func ReadSwapData(ctx context.Context, store DataStore, sessionId string) (SwapData, error) { + data := SwapData{} + fieldToKey := map[string]storedb.DataTyp{ + "PublicKey": storedb.DATA_PUBLIC_KEY, + "ActivePoolAddress": storedb.DATA_ACTIVE_POOL_ADDRESS, + "ActiveSwapFromSym": storedb.DATA_ACTIVE_SWAP_FROM_SYM, + "ActiveSwapFromDecimal": storedb.DATA_ACTIVE_SWAP_FROM_DECIMAL, + "ActiveSwapFromAddress": storedb.DATA_ACTIVE_SWAP_FROM_ADDRESS, + "ActiveSwapToSym": storedb.DATA_ACTIVE_SWAP_TO_SYM, + "ActiveSwapToAddress": storedb.DATA_ACTIVE_SWAP_TO_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 ReadSwapPreviewData(ctx context.Context, store DataStore, sessionId string) (SwapPreviewData, error) { + data := SwapPreviewData{} + fieldToKey := map[string]storedb.DataTyp{ + "PublicKey": storedb.DATA_PUBLIC_KEY, + "ActiveSwapMaxAmount": storedb.DATA_ACTIVE_SWAP_MAX_AMOUNT, + "ActiveSwapFromDecimal": storedb.DATA_ACTIVE_SWAP_FROM_DECIMAL, + "ActivePoolAddress": storedb.DATA_ACTIVE_POOL_ADDRESS, + "ActiveSwapFromAddress": storedb.DATA_ACTIVE_SWAP_FROM_ADDRESS, + "ActiveSwapFromSym": storedb.DATA_ACTIVE_SWAP_FROM_SYM, + "ActiveSwapToAddress": storedb.DATA_ACTIVE_SWAP_TO_ADDRESS, + "ActiveSwapToSym": storedb.DATA_ACTIVE_SWAP_TO_SYM, + "ActiveSwapToDecimal": storedb.DATA_ACTIVE_SWAP_TO_DECIMAL, + } + + 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 +} + +// GetSwapFromVoucherData retrieves and matches swap from voucher data +func GetSwapFromVoucherData(ctx context.Context, db storedb.PrefixDb, input string) (*dataserviceapi.TokenHoldings, error) { + keys := []storedb.DataTyp{ + storedb.DATA_POOL_FROM_SYMBOLS, + storedb.DATA_POOL_FROM_BALANCES, + storedb.DATA_POOL_FROM_DECIMALS, + storedb.DATA_POOL_FROM_ADDRESSES, + } + data := make(map[storedb.DataTyp]string) + + for _, key := range keys { + value, err := db.Get(ctx, storedb.ToBytes(key)) + if err != nil { + return nil, fmt.Errorf("failed to get prefix key %x: %v", storedb.ToBytes(key), err) + } + data[key] = string(value) + } + + symbol, balance, decimal, address := MatchVoucher(input, + data[storedb.DATA_POOL_FROM_SYMBOLS], + data[storedb.DATA_POOL_FROM_BALANCES], + data[storedb.DATA_POOL_FROM_DECIMALS], + data[storedb.DATA_POOL_FROM_ADDRESSES], + ) + + if symbol == "" { + return nil, nil + } + + return &dataserviceapi.TokenHoldings{ + TokenSymbol: string(symbol), + Balance: string(balance), + TokenDecimals: string(decimal), + ContractAddress: string(address), + }, nil +} + +// UpdateSwapFromVoucherData updates the active swap to voucher data in the DataStore. +func UpdateSwapFromVoucherData(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { + logg.TraceCtxf(ctx, "dtal", "data", data) + // Active swap from voucher data entries + activeEntries := map[storedb.DataTyp][]byte{ + storedb.DATA_ACTIVE_SWAP_FROM_SYM: []byte(data.TokenSymbol), + storedb.DATA_ACTIVE_SWAP_FROM_DECIMAL: []byte(data.TokenDecimals), + storedb.DATA_ACTIVE_SWAP_FROM_ADDRESS: []byte(data.ContractAddress), + } + + // Write active data + for key, value := range activeEntries { + if err := store.WriteEntry(ctx, sessionId, key, value); err != nil { + return err + } + } + + return nil +} + +// GetSwapToVoucherData retrieves and matches voucher data +func GetSwapToVoucherData(ctx context.Context, db storedb.PrefixDb, input string) (*dataserviceapi.TokenHoldings, error) { + keys := []storedb.DataTyp{ + storedb.DATA_POOL_TO_SYMBOLS, + storedb.DATA_POOL_TO_BALANCES, + storedb.DATA_POOL_TO_DECIMALS, + storedb.DATA_POOL_TO_ADDRESSES, + } + data := make(map[storedb.DataTyp]string) + + for _, key := range keys { + value, err := db.Get(ctx, storedb.ToBytes(key)) + if err != nil { + return nil, fmt.Errorf("failed to get prefix key %x: %v", storedb.ToBytes(key), err) + } + data[key] = string(value) + } + + symbol, balance, decimal, address := MatchVoucher(input, + data[storedb.DATA_POOL_TO_SYMBOLS], + data[storedb.DATA_POOL_TO_BALANCES], + data[storedb.DATA_POOL_TO_DECIMALS], + data[storedb.DATA_POOL_TO_ADDRESSES], + ) + + if symbol == "" { + return nil, nil + } + + return &dataserviceapi.TokenHoldings{ + TokenSymbol: string(symbol), + Balance: string(balance), + TokenDecimals: string(decimal), + ContractAddress: string(address), + }, nil +} + +// UpdateSwapToVoucherData updates the active swap to voucher data in the DataStore. +func UpdateSwapToVoucherData(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { + logg.TraceCtxf(ctx, "dtal", "data", data) + // Active swap to voucher data entries + activeEntries := map[storedb.DataTyp][]byte{ + storedb.DATA_ACTIVE_SWAP_TO_SYM: []byte(data.TokenSymbol), + storedb.DATA_ACTIVE_SWAP_TO_DECIMAL: []byte(data.TokenDecimals), + storedb.DATA_ACTIVE_SWAP_TO_ADDRESS: []byte(data.ContractAddress), + } + + // Write active data + for key, value := range activeEntries { + if err := store.WriteEntry(ctx, sessionId, key, value); err != nil { + return err + } + } + + return nil +} diff --git a/store/swap_from_vouchers.go b/store/swap_from_vouchers.go deleted file mode 100644 index f15962a..0000000 --- a/store/swap_from_vouchers.go +++ /dev/null @@ -1,65 +0,0 @@ -package store - -import ( - "context" - "fmt" - storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" - dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" -) - -// GetSwapFromVoucherData retrieves and matches swap from voucher data -func GetSwapFromVoucherData(ctx context.Context, db storedb.PrefixDb, input string) (*dataserviceapi.TokenHoldings, error) { - keys := []storedb.DataTyp{ - storedb.DATA_POOL_FROM_SYMBOLS, - storedb.DATA_POOL_FROM_BALANCES, - storedb.DATA_POOL_FROM_DECIMALS, - storedb.DATA_POOL_FROM_ADDRESSES, - } - data := make(map[storedb.DataTyp]string) - - for _, key := range keys { - value, err := db.Get(ctx, storedb.ToBytes(key)) - if err != nil { - return nil, fmt.Errorf("failed to get prefix key %x: %v", storedb.ToBytes(key), err) - } - data[key] = string(value) - } - - symbol, balance, decimal, address := MatchVoucher(input, - data[storedb.DATA_POOL_FROM_SYMBOLS], - data[storedb.DATA_POOL_FROM_BALANCES], - data[storedb.DATA_POOL_FROM_DECIMALS], - data[storedb.DATA_POOL_FROM_ADDRESSES], - ) - - if symbol == "" { - return nil, nil - } - - return &dataserviceapi.TokenHoldings{ - TokenSymbol: string(symbol), - Balance: string(balance), - TokenDecimals: string(decimal), - ContractAddress: string(address), - }, nil -} - -// UpdateSwapFromVoucherData updates the active swap to voucher data in the DataStore. -func UpdateSwapFromVoucherData(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { - logg.TraceCtxf(ctx, "dtal", "data", data) - // Active swap from voucher data entries - activeEntries := map[storedb.DataTyp][]byte{ - storedb.DATA_ACTIVE_SWAP_FROM_SYM: []byte(data.TokenSymbol), - storedb.DATA_ACTIVE_SWAP_FROM_DECIMAL: []byte(data.TokenDecimals), - storedb.DATA_ACTIVE_SWAP_FROM_ADDRESS: []byte(data.ContractAddress), - } - - // Write active data - for key, value := range activeEntries { - if err := store.WriteEntry(ctx, sessionId, key, value); err != nil { - return err - } - } - - return nil -} diff --git a/store/swap_to_vouchers.go b/store/swap_to_vouchers.go deleted file mode 100644 index f74deac..0000000 --- a/store/swap_to_vouchers.go +++ /dev/null @@ -1,65 +0,0 @@ -package store - -import ( - "context" - "fmt" - storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" - dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" -) - -// GetSwapToVoucherData retrieves and matches voucher data -func GetSwapToVoucherData(ctx context.Context, db storedb.PrefixDb, input string) (*dataserviceapi.TokenHoldings, error) { - keys := []storedb.DataTyp{ - storedb.DATA_POOL_TO_SYMBOLS, - storedb.DATA_POOL_TO_BALANCES, - storedb.DATA_POOL_TO_DECIMALS, - storedb.DATA_POOL_TO_ADDRESSES, - } - data := make(map[storedb.DataTyp]string) - - for _, key := range keys { - value, err := db.Get(ctx, storedb.ToBytes(key)) - if err != nil { - return nil, fmt.Errorf("failed to get prefix key %x: %v", storedb.ToBytes(key), err) - } - data[key] = string(value) - } - - symbol, balance, decimal, address := MatchVoucher(input, - data[storedb.DATA_POOL_TO_SYMBOLS], - data[storedb.DATA_POOL_TO_BALANCES], - data[storedb.DATA_POOL_TO_DECIMALS], - data[storedb.DATA_POOL_TO_ADDRESSES], - ) - - if symbol == "" { - return nil, nil - } - - return &dataserviceapi.TokenHoldings{ - TokenSymbol: string(symbol), - Balance: string(balance), - TokenDecimals: string(decimal), - ContractAddress: string(address), - }, nil -} - -// UpdateSwapToVoucherData updates the active swap to voucher data in the DataStore. -func UpdateSwapToVoucherData(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { - logg.TraceCtxf(ctx, "dtal", "data", data) - // Active swap to voucher data entries - activeEntries := map[storedb.DataTyp][]byte{ - storedb.DATA_ACTIVE_SWAP_TO_SYM: []byte(data.TokenSymbol), - storedb.DATA_ACTIVE_SWAP_TO_DECIMAL: []byte(data.TokenDecimals), - storedb.DATA_ACTIVE_SWAP_TO_ADDRESS: []byte(data.ContractAddress), - } - - // Write active data - for key, value := range activeEntries { - if err := store.WriteEntry(ctx, sessionId, key, value); err != nil { - return err - } - } - - return nil -} -- 2.45.2 From 21922e2b628c02f4902e82d8578845272fe66889 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 6 Mar 2025 09:22:53 +0300 Subject: [PATCH 12/33] added translation for the swap request confirmation --- services/registration/locale/swa/default.po | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/registration/locale/swa/default.po b/services/registration/locale/swa/default.po index 6155063..8f10e7d 100644 --- a/services/registration/locale/swa/default.po +++ b/services/registration/locale/swa/default.po @@ -30,3 +30,6 @@ msgstr "Salio la Kikundi: 0.00" msgid "Symbol: %s\nBalance: %s" msgstr "Sarafu: %s\nSalio: %s" + +msgid "Your request has been sent. You will receive an SMS when your %s %s has been swapped for %s." +msgstr "Ombi lako limetumwa. Utapokea SMS wakati %s %s yako itakapobadilishwa kuwa %s." -- 2.45.2 From c36798493015bf1af606225a11bd777913019a85 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 6 Mar 2025 09:23:28 +0300 Subject: [PATCH 13/33] move the catch for flag_account_authorized to the swap_preview node --- services/registration/swap_preview.vis | 1 + 1 file changed, 1 insertion(+) diff --git a/services/registration/swap_preview.vis b/services/registration/swap_preview.vis index 606913a..901de26 100644 --- a/services/registration/swap_preview.vis +++ b/services/registration/swap_preview.vis @@ -6,6 +6,7 @@ LOAD authorize_account 6 HALT RELOAD authorize_account CATCH incorrect_pin flag_incorrect_pin 1 +CATCH . flag_account_authorized 0 INCMP _ 0 INCMP quit 9 INCMP swap_initiated * -- 2.45.2 From 6642fc0137a5ca79974fa83ed05248363206f454 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 6 Mar 2025 09:23:53 +0300 Subject: [PATCH 14/33] added the swap_initiated vis node --- services/registration/swap_initiated.vis | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 services/registration/swap_initiated.vis diff --git a/services/registration/swap_initiated.vis b/services/registration/swap_initiated.vis new file mode 100644 index 0000000..69ffc6d --- /dev/null +++ b/services/registration/swap_initiated.vis @@ -0,0 +1,3 @@ +LOAD reset_incorrect 6 +LOAD initiate_swap 0 +HALT -- 2.45.2 From d6047827a4b52446a5d65e55e7690b2f635a463e Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 6 Mar 2025 09:24:48 +0300 Subject: [PATCH 15/33] link swap related functions --- handlers/local.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/handlers/local.go b/handlers/local.go index d4b7eeb..50d6489 100644 --- a/handlers/local.go +++ b/handlers/local.go @@ -127,6 +127,9 @@ func (ls *LocalHandlerService) GetHandler(accountService remote.AccountService) ls.DbRs.AddLocalFunc("get_pools", appHandlers.GetPools) ls.DbRs.AddLocalFunc("swap_from_list", appHandlers.LoadSwapFromList) ls.DbRs.AddLocalFunc("swap_to_list", appHandlers.LoadSwapToList) + ls.DbRs.AddLocalFunc("swap_max_limit", appHandlers.SwapMaxLimit) + ls.DbRs.AddLocalFunc("swap_preview", appHandlers.SwapPreview) + ls.DbRs.AddLocalFunc("initiate_swap", appHandlers.InitiateSwap) ls.first = appHandlers.Init return appHandlers, nil -- 2.45.2 From baff75da50729ba91bfbeaede2cfd4ea01d4f089 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 6 Mar 2025 09:25:55 +0300 Subject: [PATCH 16/33] Add swap functionality using dummy data --- handlers/application/menuhandler.go | 461 ++++++++++++++++++++++++++++ 1 file changed, 461 insertions(+) diff --git a/handlers/application/menuhandler.go b/handlers/application/menuhandler.go index b4cbd7b..b18025d 100644 --- a/handlers/application/menuhandler.go +++ b/handlers/application/menuhandler.go @@ -2412,3 +2412,464 @@ func (h *MenuHandlers) ClearTemporaryValue(ctx context.Context, sym string, inpu } return res, nil } + +// GetPools fetches a list of 5 top pools +func (h *MenuHandlers) GetPools(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + + userStore := h.userdataStore + _, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) + if err != nil { + logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", storedb.DATA_PUBLIC_KEY, "error", err) + return res, err + } + + topPools := []dataserviceapi.PoolDetails{ + { + PoolName: "Kenya ROLA Pool", + PoolSymbol: "ROLA", + PoolContractAdrress: "0x48a953cA5cf5298bc6f6Af3C608351f537AAcb9e", + LimiterAddress: "", + VoucherRegistry: "", + }, + { + PoolName: "Nairobi ROLA Pool", + PoolSymbol: "NAIROBI", + PoolContractAdrress: "0xB0660Ac1Ee3d32ea35bc728D7CA1705Fa5A37528", + LimiterAddress: "", + VoucherRegistry: "", + }, + { + PoolName: "Friends of Kiriba Ecosystem", + PoolSymbol: "FRIENDS", + PoolContractAdrress: "0xC4848263821FA02baB2181910A2eFb9CECb2c21C", + LimiterAddress: "", + VoucherRegistry: "", + }, + { + PoolName: "Resilient Community Waqfs", + PoolSymbol: "REZILIENS", + PoolContractAdrress: "0x1e40951d7a28147D8B4A554C60c42766C92e2Fc6", + LimiterAddress: "", + VoucherRegistry: "", + }, + { + PoolName: "GrE Tech", + PoolSymbol: "GRET", + PoolContractAdrress: "0xb7B9d0A264eD1a8E2418571B7AC5933C79C9c2B8", + LimiterAddress: "", + VoucherRegistry: "", + }, + } + + // Return if there are no pools + if len(topPools) == 0 { + return res, nil + } + + data := store.ProcessPools(topPools) + + // Store all Pool data + dataMap := map[storedb.DataTyp]string{ + storedb.DATA_POOL_NAMES: data.PoolNames, + storedb.DATA_POOL_SYMBOLS: data.PoolSymbols, + storedb.DATA_POOL_ADDRESSES: data.PoolContractAdrresses, + } + + for key, value := range dataMap { + if err := h.prefixDb.Put(ctx, []byte(storedb.ToBytes(key)), []byte(value)); err != nil { + return res, nil + } + } + + res.Content = h.ReplaceSeparatorFunc(data.PoolSymbols) + + return res, nil +} + +// LoadSwapFromList gets all the possible tokens a user can select to swap from +func (h *MenuHandlers) LoadSwapFromList(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + + userStore := h.userdataStore + + flag_incorrect_pool, _ := h.flagManager.GetFlag("flag_incorrect_pool") + + inputStr := string(input) + if inputStr == "0" { + res.FlagReset = append(res.FlagReset, flag_incorrect_pool) + return res, nil + } + + poolData, err := store.GetPoolData(ctx, h.prefixDb, inputStr) + if err != nil { + return res, fmt.Errorf("failed to retrieve pool data: %v", err) + } + + if poolData == nil { + // no match found. Call the API + poolResp := dataserviceapi.PoolDetails{ + PoolName: "DevTest", + PoolSymbol: "DEVT", + PoolContractAdrress: "0x145F87d6198dEDD45C614FFD8b70E9a2fCCc5cc9", + LimiterAddress: "", + VoucherRegistry: "", + } + + if (poolResp == dataserviceapi.PoolDetails{}) { + // If the API does not return the data, set the flag + res.FlagSet = append(res.FlagSet, flag_incorrect_pool) + return res, nil + } + + poolData = &poolResp + } + + activePoolAddress := poolData.PoolContractAdrress + + // set the active pool contract address + err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_POOL_ADDRESS, []byte(activePoolAddress)) + if err != nil { + logg.ErrorCtxf(ctx, "failed to write active PoolContractAdrress entry with", "key", storedb.DATA_ACTIVE_POOL_ADDRESS, "value", activePoolAddress, "error", err) + return res, err + } + + res.FlagReset = append(res.FlagReset, flag_incorrect_pool) + + // call the api using the pool symbol to get a list of SwapfromSymbolsData + swapFromList := []dataserviceapi.TokenHoldings{ + { + ContractAddress: "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", + TokenSymbol: "AMANI", + TokenDecimals: "6", + Balance: "", + }, + { + ContractAddress: "0xF0C3C7581b8b96B59a97daEc8Bd48247cE078674", + TokenSymbol: "AMUA", + TokenDecimals: "6", + Balance: "", + }, + { + ContractAddress: "0x371455a30fc62736145Bd8429Fcc6481186f235F", + TokenSymbol: "BAHARI", + TokenDecimals: "6", + Balance: "", + }, + { + ContractAddress: "0x7cA6113b59c24a880F382C7E12d609a6Eb05246b", + TokenSymbol: "BANGLA", + TokenDecimals: "6", + Balance: "", + }, + } + + // Return if there are no vouchers + if len(swapFromList) == 0 { + res.FlagSet = append(res.FlagSet, flag_incorrect_pool) + return res, nil + } + + data := store.ProcessVouchers(swapFromList) + + // Store all from list voucher data + dataMap := map[storedb.DataTyp]string{ + storedb.DATA_POOL_FROM_SYMBOLS: data.Symbols, + storedb.DATA_POOL_FROM_BALANCES: data.Balances, + storedb.DATA_POOL_FROM_DECIMALS: data.Decimals, + storedb.DATA_POOL_FROM_ADDRESSES: data.Addresses, + } + + for key, value := range dataMap { + if err := h.prefixDb.Put(ctx, []byte(storedb.ToBytes(key)), []byte(value)); err != nil { + return res, nil + } + } + + res.Content = h.ReplaceSeparatorFunc(data.Symbols) + + return res, nil +} + +// LoadSwapFromList returns a list of possible vouchers to swap to +func (h *MenuHandlers) LoadSwapToList(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + + // get the public key + + flag_incorrect_voucher, _ := h.flagManager.GetFlag("flag_incorrect_voucher") + + inputStr := string(input) + if inputStr == "0" { + return res, nil + } + + metadata, err := store.GetSwapFromVoucherData(ctx, h.prefixDb, inputStr) + if err != nil { + return res, fmt.Errorf("failed to retrieve swap from voucher data: %v", err) + } + + if metadata == nil { + res.FlagSet = append(res.FlagSet, flag_incorrect_voucher) + return res, nil + } + + // Store the active swap from data + if err := store.UpdateSwapFromVoucherData(ctx, h.userdataStore, sessionId, metadata); err != nil { + logg.ErrorCtxf(ctx, "failed on UpdateSwapFromVoucherData", "error", err) + return res, err + } + + res.FlagReset = append(res.FlagReset, flag_incorrect_voucher) + + // call the api using the public key to get a list of SwapToSymbolsData + swapToList := []dataserviceapi.TokenHoldings{ + { + ContractAddress: "0x765DE816845861e75A25fCA122bb6898B8B1282a", + TokenSymbol: "cUSD", + TokenDecimals: "18", + Balance: "", + }, + } + + // Return if there are no vouchers + if len(swapToList) == 0 { + return res, nil + } + + data := store.ProcessVouchers(swapToList) + + // Store all to list voucher data + dataMap := map[storedb.DataTyp]string{ + storedb.DATA_POOL_TO_SYMBOLS: data.Symbols, + storedb.DATA_POOL_TO_BALANCES: data.Balances, + storedb.DATA_POOL_TO_DECIMALS: data.Decimals, + storedb.DATA_POOL_TO_ADDRESSES: data.Addresses, + } + + for key, value := range dataMap { + if err := h.prefixDb.Put(ctx, []byte(storedb.ToBytes(key)), []byte(value)); err != nil { + return res, nil + } + } + + res.Content = h.ReplaceSeparatorFunc(data.Symbols) + + return res, nil +} + +// SwapMaxLimit returns the max FROM token +// check if max/tokenDecimals > 0.1 for UX purposes and to prevent swapping of dust values +func (h *MenuHandlers) SwapMaxLimit(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + + inputStr := string(input) + if inputStr == "0" { + return res, nil + } + + flag_incorrect_voucher, _ := h.flagManager.GetFlag("flag_incorrect_voucher") + + metadata, err := store.GetSwapToVoucherData(ctx, h.prefixDb, inputStr) + if err != nil { + return res, fmt.Errorf("failed to retrieve swap to voucher data: %v", err) + } + if metadata == nil { + res.FlagSet = append(res.FlagSet, flag_incorrect_voucher) + return res, nil + } + + userStore := h.userdataStore + + // Store the active swap_to data + if err := store.UpdateSwapToVoucherData(ctx, userStore, sessionId, metadata); err != nil { + logg.ErrorCtxf(ctx, "failed on UpdateSwapToVoucherData", "error", err) + return res, err + } + + res.FlagReset = append(res.FlagReset, flag_incorrect_voucher) + + swapData, err := store.ReadSwapData(ctx, userStore, sessionId) + if err != nil { + return res, err + } + + // call the API + // /pool/:pool/limit/:from/:to/:address + + // Scale down the amount + maxAmountStr := store.ScaleDownBalance("1339482", swapData.ActiveSwapFromDecimal) + if err != nil { + return res, err + } + + maxAmount, err := strconv.ParseFloat(maxAmountStr, 64) + if err != nil { + logg.ErrorCtxf(ctx, "failed to parse maxAmountStr as float", "value", maxAmountStr, "error", err) + return res, err + } + + if maxAmount < 0.1 { + // return with low amount flag + return res, nil + } + + // Format to 2 decimal places + maxStr := fmt.Sprintf("%.2f", maxAmount) + err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_SWAP_MAX_AMOUNT, []byte(maxStr)) + if err != nil { + logg.ErrorCtxf(ctx, "failed to write swap max amount entry with", "key", storedb.DATA_ACTIVE_SWAP_MAX_AMOUNT, "value", maxStr, "error", err) + return res, err + } + + res.Content = fmt.Sprintf( + "Maximum: %s\n\nEnter amount of %s to swap for %s:", + maxStr, swapData.ActiveSwapFromSym, swapData.ActiveSwapToSym, + ) + + return res, nil +} + +// SwapPreview displays the swap preview and estimates +func (h *MenuHandlers) SwapPreview(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + + inputStr := string(input) + if inputStr == "0" { + return res, nil + } + + flag_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount") + + userStore := h.userdataStore + + swapData, err := store.ReadSwapPreviewData(ctx, userStore, sessionId) + if err != nil { + return res, err + } + + maxValue, err := strconv.ParseFloat(swapData.ActiveSwapMaxAmount, 64) + if err != nil { + logg.ErrorCtxf(ctx, "Failed to convert the swapMaxAmount to a float", "error", err) + return res, err + } + + inputAmount, err := strconv.ParseFloat(inputStr, 64) + if err != nil || inputAmount > maxValue { + res.FlagSet = append(res.FlagSet, flag_invalid_amount) + res.Content = inputStr + return res, nil + } + + finalAmountStr, err := store.ParseAndScaleAmount(inputStr, swapData.ActiveSwapFromDecimal) + if err != nil { + return res, err + } + + err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_SWAP_AMOUNT, []byte(finalAmountStr)) + if err != nil { + logg.ErrorCtxf(ctx, "failed to write swap amount entry with", "key", storedb.DATA_ACTIVE_SWAP_AMOUNT, "value", finalAmountStr, "error", err) + return res, err + } + + // /pool/quote/:amount/:publicKey/:fromAddr/:poolAddr/:toAddr + + // call the API to get the quote + + // Scale down the quoted amount + quoteAmountStr := store.ScaleDownBalance("1339482", swapData.ActiveSwapToDecimal) + qouteAmount, err := strconv.ParseFloat(quoteAmountStr, 64) + if err != nil { + logg.ErrorCtxf(ctx, "failed to parse quoteAmountStr as float", "value", quoteAmountStr, "error", err) + return res, err + } + + // Format to 2 decimal places + qouteStr := fmt.Sprintf("%.2f", qouteAmount) + + res.Content = fmt.Sprintf( + "You will swap:\n%s %s for %s %s:", + inputStr, swapData.ActiveSwapFromSym, qouteStr, swapData.ActiveSwapToSym, + ) + + return res, nil +} + +// InitiateSwap calls the poolSwap and returns a confirmation based on the result. +func (h *MenuHandlers) InitiateSwap(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + var err error + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + + fmt.Println("running InitiateSwap") + + flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized") + + code := codeFromCtx(ctx) + l := gotext.NewLocale(translationDir, code) + l.AddDomain("default") + + userStore := h.userdataStore + + swapData, err := store.ReadSwapPreviewData(ctx, userStore, sessionId) + if err != nil { + return res, err + } + + swapAmount, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_SWAP_AMOUNT) + if err != nil { + logg.ErrorCtxf(ctx, "failed to read swapAmount entry with", "key", storedb.DATA_ACTIVE_SWAP_AMOUNT, "error", err) + return res, err + } + + swapAmountStr := string(swapAmount) + + // /pool/quote/:amount/:publicKey/:fromAddr/:poolAddr/:toAddr + + // Call poolSwap + + // r, err := h.accountService.poolSwap(ctx, swapAmountStr, swapData.PublicKey, swapData.ActiveSwapFromAddress, swapData.ActivePoolAddress, swapData.ActiveSwapToAddress) + // if err != nil { + // flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") + // res.FlagSet = append(res.FlagSet, flag_api_error) + // res.Content = l.Get("Your request failed. Please try again later.") + // logg.ErrorCtxf(ctx, "failed on poolSwap", "error", err) + // return res, nil + // } + + // trackingId := r.TrackingId + // logg.InfoCtxf(ctx, "poolSwap", "trackingId", trackingId) + + res.Content = l.Get( + "Your request has been sent. You will receive an SMS when your %s %s has been swapped for %s.", + swapAmountStr, + swapData.ActiveSwapFromSym, + swapData.ActiveSwapToSym, + ) + + res.FlagReset = append(res.FlagReset, flag_account_authorized) + return res, nil +} -- 2.45.2 From 2a46de9a6f391f477e1f8c0e7d1b50e2c06713b2 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 6 Mar 2025 18:57:24 +0300 Subject: [PATCH 17/33] Use the latest sarafu-api changes with pool swap functionality --- go.mod | 2 +- go.sum | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 898e661..58ef77b 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.4 require ( git.defalsify.org/vise.git v0.2.3-0.20250205173834-d1f6647211ac git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d - git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250206112944-31eb30de0f69 + git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250306151434-35f24b518375 git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244 git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 github.com/alecthomas/assert/v2 v2.2.2 diff --git a/go.sum b/go.sum index bec01de..b475d31 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,10 @@ git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d/go.mod h1:wgQJZGIS6QuNLHqDhcsvehsbn5PvgV7aziRebMnJi60= git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250206112944-31eb30de0f69 h1:cbBpm9uNJak58MpFpNXJuvgCmz+A8kquXr9har4expg= git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250206112944-31eb30de0f69/go.mod h1:gOn89ipaDcDvmQXRMQYKUqcw/sJcwVOPVt2eC6Geip8= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250224114958-1f3ac220d126 h1:fXL9uXt8yiu5ImJnwiHoLsq8T2TJ6+8qa97pCt+gHxA= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250224114958-1f3ac220d126/go.mod h1:gOn89ipaDcDvmQXRMQYKUqcw/sJcwVOPVt2eC6Geip8= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250306151434-35f24b518375 h1:VilYLeBFXxOSgs+AD9B1+Mu+VJZHiSWACY5xF1x3xBE= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250306151434-35f24b518375/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244 h1:BXotWSKg04U97sf/xeWJuUTSVgKk2aEK+5BtBrnafXQ= git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244/go.mod h1:6B6ByxXOiRY0NR7K02Bf3fEu7z+2c/6q8PFVNjC5G8w= git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 h1:DjJlBSz0S13acft5XZDWk7ZYnzElym0xLMYEVgyNJ+E= -- 2.45.2 From 16380dbe49dceb1028d773188e4c5f6908263dc1 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 6 Mar 2025 18:58:25 +0300 Subject: [PATCH 18/33] Use the GetPoolSwapQuote and PoolSwap functions for live data --- handlers/application/menuhandler.go | 43 ++++++++++++++++------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/handlers/application/menuhandler.go b/handlers/application/menuhandler.go index b18025d..fcb7e80 100644 --- a/handlers/application/menuhandler.go +++ b/handlers/application/menuhandler.go @@ -2761,6 +2761,10 @@ func (h *MenuHandlers) SwapPreview(ctx context.Context, sym string, input []byte flag_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount") + code := codeFromCtx(ctx) + l := gotext.NewLocale(translationDir, code) + l.AddDomain("default") + userStore := h.userdataStore swapData, err := store.ReadSwapPreviewData(ctx, userStore, sessionId) @@ -2792,12 +2796,18 @@ func (h *MenuHandlers) SwapPreview(ctx context.Context, sym string, input []byte return res, err } - // /pool/quote/:amount/:publicKey/:fromAddr/:poolAddr/:toAddr - // call the API to get the quote + r, err := h.accountService.GetPoolSwapQuote(ctx, finalAmountStr, swapData.PublicKey, swapData.ActiveSwapFromAddress, swapData.ActivePoolAddress, swapData.ActiveSwapToAddress) + if err != nil { + flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") + res.FlagSet = append(res.FlagSet, flag_api_error) + res.Content = l.Get("Your request failed. Please try again later.") + logg.ErrorCtxf(ctx, "failed on poolSwap", "error", err) + return res, nil + } // Scale down the quoted amount - quoteAmountStr := store.ScaleDownBalance("1339482", swapData.ActiveSwapToDecimal) + quoteAmountStr := store.ScaleDownBalance(r.OutValue, swapData.ActiveSwapToDecimal) qouteAmount, err := strconv.ParseFloat(quoteAmountStr, 64) if err != nil { logg.ErrorCtxf(ctx, "failed to parse quoteAmountStr as float", "value", quoteAmountStr, "error", err) @@ -2824,8 +2834,6 @@ func (h *MenuHandlers) InitiateSwap(ctx context.Context, sym string, input []byt return res, fmt.Errorf("missing session") } - fmt.Println("running InitiateSwap") - flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized") code := codeFromCtx(ctx) @@ -2847,21 +2855,18 @@ func (h *MenuHandlers) InitiateSwap(ctx context.Context, sym string, input []byt swapAmountStr := string(swapAmount) - // /pool/quote/:amount/:publicKey/:fromAddr/:poolAddr/:toAddr + // Call the poolSwap API + r, err := h.accountService.PoolSwap(ctx, swapAmountStr, swapData.PublicKey, swapData.ActiveSwapFromAddress, swapData.ActivePoolAddress, swapData.ActiveSwapToAddress) + if err != nil { + flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") + res.FlagSet = append(res.FlagSet, flag_api_error) + res.Content = l.Get("Your request failed. Please try again later.") + logg.ErrorCtxf(ctx, "failed on poolSwap", "error", err) + return res, nil + } - // Call poolSwap - - // r, err := h.accountService.poolSwap(ctx, swapAmountStr, swapData.PublicKey, swapData.ActiveSwapFromAddress, swapData.ActivePoolAddress, swapData.ActiveSwapToAddress) - // if err != nil { - // flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") - // res.FlagSet = append(res.FlagSet, flag_api_error) - // res.Content = l.Get("Your request failed. Please try again later.") - // logg.ErrorCtxf(ctx, "failed on poolSwap", "error", err) - // return res, nil - // } - - // trackingId := r.TrackingId - // logg.InfoCtxf(ctx, "poolSwap", "trackingId", trackingId) + trackingId := r.TrackingId + logg.InfoCtxf(ctx, "poolSwap", "trackingId", trackingId) res.Content = l.Get( "Your request has been sent. You will receive an SMS when your %s %s has been swapped for %s.", -- 2.45.2 From 450cba07c7175452e20fddcbfec7eeb9b645add6 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 10 Mar 2025 16:45:04 +0300 Subject: [PATCH 19/33] Use the latest sarafu-api --- go.mod | 2 +- go.sum | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 58ef77b..619b916 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.4 require ( git.defalsify.org/vise.git v0.2.3-0.20250205173834-d1f6647211ac git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d - git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250306151434-35f24b518375 + git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310133937-ba8d2a19c2ed git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244 git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 github.com/alecthomas/assert/v2 v2.2.2 diff --git a/go.sum b/go.sum index b475d31..aa18650 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,14 @@ git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250224114958- git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250224114958-1f3ac220d126/go.mod h1:gOn89ipaDcDvmQXRMQYKUqcw/sJcwVOPVt2eC6Geip8= git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250306151434-35f24b518375 h1:VilYLeBFXxOSgs+AD9B1+Mu+VJZHiSWACY5xF1x3xBE= git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250306151434-35f24b518375/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250307051649-4783e2dcb319 h1:Qg6ttFJ4zjF67PERvLcXJ4/bXUTdCaRJ96RFRmQZ4xc= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250307051649-4783e2dcb319/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310110330-a04f7ee66c35 h1:JeRpSf+/NTFTl3lhiSkHO54NIoK6KrXmyqawfiuKc0Y= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310110330-a04f7ee66c35/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310111703-e3b6c25792c2 h1:QhiSpx3ndgQeR/CAynLdiOR+wNEJJDFWMKE2CHmp8n8= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310111703-e3b6c25792c2/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310133937-ba8d2a19c2ed h1:r5w89jInk9wwJZ4kMmE8ENPV7chxORJWIfxsPmnAQwY= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310133937-ba8d2a19c2ed/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244 h1:BXotWSKg04U97sf/xeWJuUTSVgKk2aEK+5BtBrnafXQ= git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244/go.mod h1:6B6ByxXOiRY0NR7K02Bf3fEu7z+2c/6q8PFVNjC5G8w= git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 h1:DjJlBSz0S13acft5XZDWk7ZYnzElym0xLMYEVgyNJ+E= -- 2.45.2 From 69ea52d91c3738b2646ca182d5716fa3df5764eb Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 10 Mar 2025 16:48:19 +0300 Subject: [PATCH 20/33] use data fetched from sarafu-api --- handlers/application/menuhandler.go | 99 ++++++++--------------------- 1 file changed, 27 insertions(+), 72 deletions(-) diff --git a/handlers/application/menuhandler.go b/handlers/application/menuhandler.go index fcb7e80..2aca166 100644 --- a/handlers/application/menuhandler.go +++ b/handlers/application/menuhandler.go @@ -2422,48 +2422,19 @@ func (h *MenuHandlers) GetPools(ctx context.Context, sym string, input []byte) ( } userStore := h.userdataStore - _, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) + publicKey, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) if err != nil { logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", storedb.DATA_PUBLIC_KEY, "error", err) return res, err } - topPools := []dataserviceapi.PoolDetails{ - { - PoolName: "Kenya ROLA Pool", - PoolSymbol: "ROLA", - PoolContractAdrress: "0x48a953cA5cf5298bc6f6Af3C608351f537AAcb9e", - LimiterAddress: "", - VoucherRegistry: "", - }, - { - PoolName: "Nairobi ROLA Pool", - PoolSymbol: "NAIROBI", - PoolContractAdrress: "0xB0660Ac1Ee3d32ea35bc728D7CA1705Fa5A37528", - LimiterAddress: "", - VoucherRegistry: "", - }, - { - PoolName: "Friends of Kiriba Ecosystem", - PoolSymbol: "FRIENDS", - PoolContractAdrress: "0xC4848263821FA02baB2181910A2eFb9CECb2c21C", - LimiterAddress: "", - VoucherRegistry: "", - }, - { - PoolName: "Resilient Community Waqfs", - PoolSymbol: "REZILIENS", - PoolContractAdrress: "0x1e40951d7a28147D8B4A554C60c42766C92e2Fc6", - LimiterAddress: "", - VoucherRegistry: "", - }, - { - PoolName: "GrE Tech", - PoolSymbol: "GRET", - PoolContractAdrress: "0xb7B9d0A264eD1a8E2418571B7AC5933C79C9c2B8", - LimiterAddress: "", - VoucherRegistry: "", - }, + flag_api_error, _ := h.flagManager.GetFlag("flag_api_error") + + topPools, err := h.accountService.FetchTopPools(ctx, string(publicKey)) + if err != nil { + res.FlagSet = append(res.FlagSet, flag_api_error) + logg.ErrorCtxf(ctx, "failed on FetchTransactions", "error", err) + return res, err } // Return if there are no pools @@ -2500,8 +2471,8 @@ func (h *MenuHandlers) LoadSwapFromList(ctx context.Context, sym string, input [ } userStore := h.userdataStore - flag_incorrect_pool, _ := h.flagManager.GetFlag("flag_incorrect_pool") + flag_api_error, _ := h.flagManager.GetFlag("flag_api_error") inputStr := string(input) if inputStr == "0" { @@ -2545,31 +2516,11 @@ func (h *MenuHandlers) LoadSwapFromList(ctx context.Context, sym string, input [ res.FlagReset = append(res.FlagReset, flag_incorrect_pool) // call the api using the pool symbol to get a list of SwapfromSymbolsData - swapFromList := []dataserviceapi.TokenHoldings{ - { - ContractAddress: "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", - TokenSymbol: "AMANI", - TokenDecimals: "6", - Balance: "", - }, - { - ContractAddress: "0xF0C3C7581b8b96B59a97daEc8Bd48247cE078674", - TokenSymbol: "AMUA", - TokenDecimals: "6", - Balance: "", - }, - { - ContractAddress: "0x371455a30fc62736145Bd8429Fcc6481186f235F", - TokenSymbol: "BAHARI", - TokenDecimals: "6", - Balance: "", - }, - { - ContractAddress: "0x7cA6113b59c24a880F382C7E12d609a6Eb05246b", - TokenSymbol: "BANGLA", - TokenDecimals: "6", - Balance: "", - }, + swapFromList, err := h.accountService.GetPoolSwappableFromVouchers(ctx, activePoolAddress) + if err != nil { + res.FlagSet = append(res.FlagSet, flag_api_error) + logg.ErrorCtxf(ctx, "failed on FetchTransactions", "error", err) + return res, err } // Return if there are no vouchers @@ -2607,9 +2558,15 @@ func (h *MenuHandlers) LoadSwapToList(ctx context.Context, sym string, input []b return res, fmt.Errorf("missing session") } - // get the public key + userStore := h.userdataStore + publicKey, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) + if err != nil { + logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", storedb.DATA_PUBLIC_KEY, "error", err) + return res, err + } flag_incorrect_voucher, _ := h.flagManager.GetFlag("flag_incorrect_voucher") + flag_api_error, _ := h.flagManager.GetFlag("flag_api_error") inputStr := string(input) if inputStr == "0" { @@ -2627,7 +2584,7 @@ func (h *MenuHandlers) LoadSwapToList(ctx context.Context, sym string, input []b } // Store the active swap from data - if err := store.UpdateSwapFromVoucherData(ctx, h.userdataStore, sessionId, metadata); err != nil { + if err := store.UpdateSwapFromVoucherData(ctx, userStore, sessionId, metadata); err != nil { logg.ErrorCtxf(ctx, "failed on UpdateSwapFromVoucherData", "error", err) return res, err } @@ -2635,13 +2592,11 @@ func (h *MenuHandlers) LoadSwapToList(ctx context.Context, sym string, input []b res.FlagReset = append(res.FlagReset, flag_incorrect_voucher) // call the api using the public key to get a list of SwapToSymbolsData - swapToList := []dataserviceapi.TokenHoldings{ - { - ContractAddress: "0x765DE816845861e75A25fCA122bb6898B8B1282a", - TokenSymbol: "cUSD", - TokenDecimals: "18", - Balance: "", - }, + swapToList, err := h.accountService.GetPoolSwappableVouchers(ctx, string(publicKey)) + if err != nil { + res.FlagSet = append(res.FlagSet, flag_api_error) + logg.ErrorCtxf(ctx, "failed on FetchTransactions", "error", err) + return res, err } // Return if there are no vouchers -- 2.45.2 From 46d5c2f035d93ecdbb7525caa973a94280fb3661 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 10 Mar 2025 17:16:44 +0300 Subject: [PATCH 21/33] pass the correct arguments to the swap functions --- go.mod | 2 +- go.sum | 2 ++ handlers/application/menuhandler.go | 35 +++++++++++++++-------------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 619b916..6d3b131 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.4 require ( git.defalsify.org/vise.git v0.2.3-0.20250205173834-d1f6647211ac git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d - git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310133937-ba8d2a19c2ed + git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310141205-3b39b86d0987 git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244 git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 github.com/alecthomas/assert/v2 v2.2.2 diff --git a/go.sum b/go.sum index aa18650..7276b8b 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310111703- git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310111703-e3b6c25792c2/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310133937-ba8d2a19c2ed h1:r5w89jInk9wwJZ4kMmE8ENPV7chxORJWIfxsPmnAQwY= git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310133937-ba8d2a19c2ed/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310141205-3b39b86d0987 h1:HXFD3Pabi1H4tuKVZUjyqsYoI8JrhJrH0NXeVuB2buo= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310141205-3b39b86d0987/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244 h1:BXotWSKg04U97sf/xeWJuUTSVgKk2aEK+5BtBrnafXQ= git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244/go.mod h1:6B6ByxXOiRY0NR7K02Bf3fEu7z+2c/6q8PFVNjC5G8w= git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 h1:DjJlBSz0S13acft5XZDWk7ZYnzElym0xLMYEVgyNJ+E= diff --git a/handlers/application/menuhandler.go b/handlers/application/menuhandler.go index 2aca166..bc620f5 100644 --- a/handlers/application/menuhandler.go +++ b/handlers/application/menuhandler.go @@ -2416,21 +2416,10 @@ func (h *MenuHandlers) ClearTemporaryValue(ctx context.Context, sym string, inpu // GetPools fetches a list of 5 top pools func (h *MenuHandlers) GetPools(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result - sessionId, ok := ctx.Value("SessionId").(string) - if !ok { - return res, fmt.Errorf("missing session") - } - - userStore := h.userdataStore - publicKey, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) - if err != nil { - logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", storedb.DATA_PUBLIC_KEY, "error", err) - return res, err - } - flag_api_error, _ := h.flagManager.GetFlag("flag_api_error") - topPools, err := h.accountService.FetchTopPools(ctx, string(publicKey)) + // call the api to get a list of top 5 pools sorted by swaps + topPools, err := h.accountService.FetchTopPools(ctx) if err != nil { res.FlagSet = append(res.FlagSet, flag_api_error) logg.ErrorCtxf(ctx, "failed on FetchTransactions", "error", err) @@ -2471,6 +2460,12 @@ func (h *MenuHandlers) LoadSwapFromList(ctx context.Context, sym string, input [ } userStore := h.userdataStore + publicKey, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) + if err != nil { + logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", storedb.DATA_PUBLIC_KEY, "error", err) + return res, err + } + flag_incorrect_pool, _ := h.flagManager.GetFlag("flag_incorrect_pool") flag_api_error, _ := h.flagManager.GetFlag("flag_api_error") @@ -2515,8 +2510,8 @@ func (h *MenuHandlers) LoadSwapFromList(ctx context.Context, sym string, input [ res.FlagReset = append(res.FlagReset, flag_incorrect_pool) - // call the api using the pool symbol to get a list of SwapfromSymbolsData - swapFromList, err := h.accountService.GetPoolSwappableFromVouchers(ctx, activePoolAddress) + // call the api using the activePoolAddress and publicKey to get a list of SwapfromSymbolsData + swapFromList, err := h.accountService.GetPoolSwappableFromVouchers(ctx, activePoolAddress, string(publicKey)) if err != nil { res.FlagSet = append(res.FlagSet, flag_api_error) logg.ErrorCtxf(ctx, "failed on FetchTransactions", "error", err) @@ -2591,8 +2586,14 @@ func (h *MenuHandlers) LoadSwapToList(ctx context.Context, sym string, input []b res.FlagReset = append(res.FlagReset, flag_incorrect_voucher) - // call the api using the public key to get a list of SwapToSymbolsData - swapToList, err := h.accountService.GetPoolSwappableVouchers(ctx, string(publicKey)) + activePoolAddress, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_POOL_ADDRESS) + if err != nil { + logg.ErrorCtxf(ctx, "failed to read activePoolAddress entry with", "key", storedb.DATA_ACTIVE_POOL_ADDRESS, "error", err) + return res, err + } + + // call the api using the activePoolAddress and publicKey to get a list of SwapToSymbolsData + swapToList, err := h.accountService.GetPoolSwappableVouchers(ctx, string(activePoolAddress), string(publicKey)) if err != nil { res.FlagSet = append(res.FlagSet, flag_api_error) logg.ErrorCtxf(ctx, "failed on FetchTransactions", "error", err) -- 2.45.2 From d13d24f03230966c01782890331a72626ab4140d Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 12 Mar 2025 10:44:09 +0300 Subject: [PATCH 22/33] Update the conflicting input numbers on main.vis --- services/registration/main.vis | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/registration/main.vis b/services/registration/main.vis index d80acc9..69f8b00 100644 --- a/services/registration/main.vis +++ b/services/registration/main.vis @@ -11,14 +11,14 @@ MAP check_balance MOUT send 1 MOUT swap 2 MOUT vouchers 3 -MOUT account 3 -MOUT help 4 +MOUT account 4 +MOUT help 5 MOUT quit 9 HALT INCMP send 1 INCMP pool_swap 2 INCMP my_vouchers 3 -INCMP my_account 3 -INCMP help 4 +INCMP my_account 4 +INCMP help 5 INCMP quit 9 INCMP . * -- 2.45.2 From 6a91049ffb2a59fcd543670379e0dbebeaf161de Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 12 Mar 2025 10:45:38 +0300 Subject: [PATCH 23/33] Added a flag_low_swap_amount and vis files for when the swap max limit is less than 0.1 --- services/registration/low_swap_amount | 1 + services/registration/low_swap_amount.vis | 6 ++++++ services/registration/low_swap_amount_swa | 1 + services/registration/pp.csv | 1 + 4 files changed, 9 insertions(+) create mode 100644 services/registration/low_swap_amount create mode 100644 services/registration/low_swap_amount.vis create mode 100644 services/registration/low_swap_amount_swa diff --git a/services/registration/low_swap_amount b/services/registration/low_swap_amount new file mode 100644 index 0000000..d3e50f7 --- /dev/null +++ b/services/registration/low_swap_amount @@ -0,0 +1 @@ +Available amount {{.swap_max_limit}} is too low, please try again: \ No newline at end of file diff --git a/services/registration/low_swap_amount.vis b/services/registration/low_swap_amount.vis new file mode 100644 index 0000000..336ccde --- /dev/null +++ b/services/registration/low_swap_amount.vis @@ -0,0 +1,6 @@ +MAP swap_max_limit +MOUT retry 1 +MOUT quit 9 +HALT +INCMP _ 1 +INCMP quit 9 diff --git a/services/registration/low_swap_amount_swa b/services/registration/low_swap_amount_swa new file mode 100644 index 0000000..2d11dd9 --- /dev/null +++ b/services/registration/low_swap_amount_swa @@ -0,0 +1 @@ +Kiasi kinachopatikana {{.swap_max_limit}} ni cha chini sana, tafadhali jaribu tena: \ No newline at end of file diff --git a/services/registration/pp.csv b/services/registration/pp.csv index 03c61dd..17f8460 100644 --- a/services/registration/pp.csv +++ b/services/registration/pp.csv @@ -30,3 +30,4 @@ flag,flag_offerings_set,36,this is set when the offerings of the profile is set flag,flag_back_set,37,this is set when it is a back navigation flag,flag_account_blocked,38,this is set when an account has been blocked after the allowed incorrect PIN attempts have been exceeded flag,flag_incorrect_pool,39,this is set when the user selects an invalid pool +flag,flag_low_swap_amount,40,this is set when the swap max limit is less than 0.1 -- 2.45.2 From ec8dc2fb1d37a04bec256fcb10cbac672ad2c571 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 12 Mar 2025 10:46:11 +0300 Subject: [PATCH 24/33] Added a catch for the flag_low_swap_amount --- services/registration/swap_limit.vis | 3 +-- services/registration/swap_to_list.vis | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/services/registration/swap_limit.vis b/services/registration/swap_limit.vis index fe116ce..b96f1f5 100644 --- a/services/registration/swap_limit.vis +++ b/services/registration/swap_limit.vis @@ -1,5 +1,4 @@ -LOAD swap_max_limit 0 -CATCH _ flag_incorrect_voucher 1 +RELOAD swap_max_limit MAP swap_max_limit MOUT back 0 HALT diff --git a/services/registration/swap_to_list.vis b/services/registration/swap_to_list.vis index e420a69..de1836e 100644 --- a/services/registration/swap_to_list.vis +++ b/services/registration/swap_to_list.vis @@ -3,5 +3,9 @@ CATCH _ flag_incorrect_voucher 1 MAP swap_to_list MOUT back 0 HALT +LOAD swap_max_limit 64 +RELOAD swap_max_limit +CATCH . flag_incorrect_voucher 1 +CATCH low_swap_amount flag_low_swap_amount 1 INCMP _ 0 INCMP swap_limit * -- 2.45.2 From 8292f7633439a41e52d898ce8262caac5306f219 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 12 Mar 2025 10:46:45 +0300 Subject: [PATCH 25/33] Updated the sarafu-api package --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 6d3b131..fa397fe 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.4 require ( git.defalsify.org/vise.git v0.2.3-0.20250205173834-d1f6647211ac git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d - git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310141205-3b39b86d0987 + git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250311124651-3244c717cbee git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244 git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 github.com/alecthomas/assert/v2 v2.2.2 diff --git a/go.sum b/go.sum index 7276b8b..cf8c43c 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,8 @@ git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310133937- git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310133937-ba8d2a19c2ed/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310141205-3b39b86d0987 h1:HXFD3Pabi1H4tuKVZUjyqsYoI8JrhJrH0NXeVuB2buo= git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310141205-3b39b86d0987/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250311124651-3244c717cbee h1:YONuCBfzDlpeXsQMWRiBrRlSC0YHWUNuC5Sit43Ncww= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250311124651-3244c717cbee/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244 h1:BXotWSKg04U97sf/xeWJuUTSVgKk2aEK+5BtBrnafXQ= git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244/go.mod h1:6B6ByxXOiRY0NR7K02Bf3fEu7z+2c/6q8PFVNjC5G8w= git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 h1:DjJlBSz0S13acft5XZDWk7ZYnzElym0xLMYEVgyNJ+E= -- 2.45.2 From 1df102db9fb8a1d633c2367476517bbf67872998 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 12 Mar 2025 10:48:36 +0300 Subject: [PATCH 26/33] Updated the SwapMaxLimit func to use the GetSwapFromTokenMaxLimit and set a flag when the max limit is invalid --- handlers/application/menuhandler.go | 33 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/handlers/application/menuhandler.go b/handlers/application/menuhandler.go index bc620f5..8adeee7 100644 --- a/handlers/application/menuhandler.go +++ b/handlers/application/menuhandler.go @@ -2635,13 +2635,18 @@ func (h *MenuHandlers) SwapMaxLimit(ctx context.Context, sym string, input []byt return res, fmt.Errorf("missing session") } + flag_incorrect_voucher, _ := h.flagManager.GetFlag("flag_incorrect_voucher") + flag_api_error, _ := h.flagManager.GetFlag("flag_api_error") + flag_low_swap_amount, _ := h.flagManager.GetFlag("flag_low_swap_amount") + + res.FlagReset = append(res.FlagReset, flag_incorrect_voucher) + res.FlagReset = append(res.FlagSet, flag_low_swap_amount) + inputStr := string(input) if inputStr == "0" { return res, nil } - flag_incorrect_voucher, _ := h.flagManager.GetFlag("flag_incorrect_voucher") - metadata, err := store.GetSwapToVoucherData(ctx, h.prefixDb, inputStr) if err != nil { return res, fmt.Errorf("failed to retrieve swap to voucher data: %v", err) @@ -2659,35 +2664,41 @@ func (h *MenuHandlers) SwapMaxLimit(ctx context.Context, sym string, input []byt return res, err } - res.FlagReset = append(res.FlagReset, flag_incorrect_voucher) - swapData, err := store.ReadSwapData(ctx, userStore, sessionId) if err != nil { return res, err } - // call the API - // /pool/:pool/limit/:from/:to/:address + // call the api using the ActivePoolAddress, ActiveSwapFromAddress, ActiveSwapToAddress and PublicKey to get the swap max limit + r, err := h.accountService.GetSwapFromTokenMaxLimit(ctx, swapData.ActivePoolAddress, swapData.ActiveSwapFromAddress, swapData.ActiveSwapToAddress, swapData.PublicKey) + if err != nil { + res.FlagSet = append(res.FlagSet, flag_api_error) + logg.ErrorCtxf(ctx, "failed on FetchTransactions", "error", err) + return res, err + } // Scale down the amount - maxAmountStr := store.ScaleDownBalance("1339482", swapData.ActiveSwapFromDecimal) + maxAmountStr := store.ScaleDownBalance(r.Max, swapData.ActiveSwapFromDecimal) if err != nil { return res, err } - maxAmount, err := strconv.ParseFloat(maxAmountStr, 64) + maxAmountFloat, err := strconv.ParseFloat(maxAmountStr, 64) if err != nil { logg.ErrorCtxf(ctx, "failed to parse maxAmountStr as float", "value", maxAmountStr, "error", err) return res, err } - if maxAmount < 0.1 { + // Format to 2 decimal places + maxStr := fmt.Sprintf("%.2f", maxAmountFloat) + + if maxAmountFloat < 0.1 { // return with low amount flag + res.Content = maxStr + res.FlagSet = append(res.FlagSet, flag_low_swap_amount) return res, nil } - // Format to 2 decimal places - maxStr := fmt.Sprintf("%.2f", maxAmount) err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_SWAP_MAX_AMOUNT, []byte(maxStr)) if err != nil { logg.ErrorCtxf(ctx, "failed to write swap max amount entry with", "key", storedb.DATA_ACTIVE_SWAP_MAX_AMOUNT, "value", maxStr, "error", err) -- 2.45.2 From 2eef202a1a443221c1b7e20038e3cc2612675a4c Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 13 Mar 2025 09:30:57 +0300 Subject: [PATCH 27/33] Capitalize the Swap menu option --- services/registration/swap_menu | 1 + 1 file changed, 1 insertion(+) create mode 100644 services/registration/swap_menu diff --git a/services/registration/swap_menu b/services/registration/swap_menu new file mode 100644 index 0000000..a5daabf --- /dev/null +++ b/services/registration/swap_menu @@ -0,0 +1 @@ +Swap \ No newline at end of file -- 2.45.2 From fd0c9cbc681f3598ffff7a8fdfa6354741aaff76 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 13 Mar 2025 10:17:16 +0300 Subject: [PATCH 28/33] Updated sarafu-api package --- go.mod | 2 +- go.sum | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index fa397fe..531e4b0 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.4 require ( git.defalsify.org/vise.git v0.2.3-0.20250205173834-d1f6647211ac git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d - git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250311124651-3244c717cbee + git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250313071411-ba43610ff00b git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244 git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 github.com/alecthomas/assert/v2 v2.2.2 diff --git a/go.sum b/go.sum index cf8c43c..b29d7a1 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,10 @@ git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310141205- git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310141205-3b39b86d0987/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250311124651-3244c717cbee h1:YONuCBfzDlpeXsQMWRiBrRlSC0YHWUNuC5Sit43Ncww= git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250311124651-3244c717cbee/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250313070549-3c2889ac72f0 h1:AMa2VmeRrmHz87+RtH9sJGTGnlYXqkhJG1tX/vgQAx0= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250313070549-3c2889ac72f0/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250313071411-ba43610ff00b h1:+j02QfOVYvPteaIpL/3KQ6taQnoI7TFkcH23iBUhoZg= +git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250313071411-ba43610ff00b/go.mod h1:K/TPgZ4OhPHBQq2X0ab3JZs4YjiexzSURZcfHLs9Pf4= git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244 h1:BXotWSKg04U97sf/xeWJuUTSVgKk2aEK+5BtBrnafXQ= git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244/go.mod h1:6B6ByxXOiRY0NR7K02Bf3fEu7z+2c/6q8PFVNjC5G8w= git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 h1:DjJlBSz0S13acft5XZDWk7ZYnzElym0xLMYEVgyNJ+E= -- 2.45.2 From 9729a6442b7c80803c35b9391fdd8da7dbf33b9a Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 13 Mar 2025 13:05:51 +0300 Subject: [PATCH 29/33] Added TestReadSwapData --- store/swap_test.go | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 store/swap_test.go diff --git a/store/swap_test.go b/store/swap_test.go new file mode 100644 index 0000000..46ec631 --- /dev/null +++ b/store/swap_test.go @@ -0,0 +1,47 @@ +package store + +import ( + "testing" + + storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" + "github.com/alecthomas/assert/v2" +) + +func TestReadSwapData(t *testing.T) { + sessionId := "session123" + publicKey := "0X13242618721" + ctx, store := InitializeTestDb(t) + + // Test swap data + transactionData := map[storedb.DataTyp]string{ + storedb.DATA_PUBLIC_KEY: publicKey, + storedb.DATA_ACTIVE_POOL_ADDRESS: "0x48a953cA5cf5298bc6f6Af3C608351f537AAcb9e", + storedb.DATA_ACTIVE_SWAP_FROM_SYM: "AMANI", + storedb.DATA_ACTIVE_SWAP_FROM_DECIMAL: "6", + storedb.DATA_ACTIVE_SWAP_FROM_ADDRESS: "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", + storedb.DATA_ACTIVE_SWAP_TO_SYM: "cUSD", + storedb.DATA_ACTIVE_SWAP_TO_ADDRESS: "0x765DE816845861e75A25fCA122bb6898B8B1282a", + } + + // Store the data + for key, value := range transactionData { + if err := store.WriteEntry(ctx, sessionId, key, []byte(value)); err != nil { + t.Fatal(err) + } + } + + expectedResult := SwapData{ + PublicKey: "0X13242618721", + ActivePoolAddress: "0x48a953cA5cf5298bc6f6Af3C608351f537AAcb9e", + ActiveSwapFromSym: "AMANI", + ActiveSwapFromDecimal: "6", + ActiveSwapFromAddress: "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", + ActiveSwapToSym: "cUSD", + ActiveSwapToAddress: "0x765DE816845861e75A25fCA122bb6898B8B1282a", + } + + data, err := ReadSwapData(ctx, store, sessionId) + + assert.NoError(t, err) + assert.Equal(t, expectedResult, data) +} -- 2.45.2 From c407dd1702ffc229b9b68a3e66ecc831f48b5383 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 13 Mar 2025 13:10:58 +0300 Subject: [PATCH 30/33] Added TestReadSwapPreviewData --- store/swap_test.go | 47 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/store/swap_test.go b/store/swap_test.go index 46ec631..d2a92fc 100644 --- a/store/swap_test.go +++ b/store/swap_test.go @@ -13,7 +13,7 @@ func TestReadSwapData(t *testing.T) { ctx, store := InitializeTestDb(t) // Test swap data - transactionData := map[storedb.DataTyp]string{ + swapData := map[storedb.DataTyp]string{ storedb.DATA_PUBLIC_KEY: publicKey, storedb.DATA_ACTIVE_POOL_ADDRESS: "0x48a953cA5cf5298bc6f6Af3C608351f537AAcb9e", storedb.DATA_ACTIVE_SWAP_FROM_SYM: "AMANI", @@ -24,7 +24,7 @@ func TestReadSwapData(t *testing.T) { } // Store the data - for key, value := range transactionData { + for key, value := range swapData { if err := store.WriteEntry(ctx, sessionId, key, []byte(value)); err != nil { t.Fatal(err) } @@ -45,3 +45,46 @@ func TestReadSwapData(t *testing.T) { assert.NoError(t, err) assert.Equal(t, expectedResult, data) } + +func TestReadSwapPreviewData(t *testing.T) { + sessionId := "session123" + publicKey := "0X13242618721" + ctx, store := InitializeTestDb(t) + + // Test swap preview data + swapPreviewData := map[storedb.DataTyp]string{ + storedb.DATA_PUBLIC_KEY: publicKey, + storedb.DATA_ACTIVE_SWAP_MAX_AMOUNT: "1339482", + storedb.DATA_ACTIVE_SWAP_FROM_DECIMAL: "6", + storedb.DATA_ACTIVE_POOL_ADDRESS: "0x48a953cA5cf5298bc6f6Af3C608351f537AAcb9e", + storedb.DATA_ACTIVE_SWAP_FROM_ADDRESS: "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", + storedb.DATA_ACTIVE_SWAP_FROM_SYM: "AMANI", + storedb.DATA_ACTIVE_SWAP_TO_ADDRESS: "0x765DE816845861e75A25fCA122bb6898B8B1282a", + storedb.DATA_ACTIVE_SWAP_TO_SYM: "cUSD", + storedb.DATA_ACTIVE_SWAP_TO_DECIMAL: "18", + } + + // Store the data + for key, value := range swapPreviewData { + if err := store.WriteEntry(ctx, sessionId, key, []byte(value)); err != nil { + t.Fatal(err) + } + } + + expectedResult := SwapPreviewData{ + PublicKey: "0X13242618721", + ActiveSwapMaxAmount: "1339482", + ActiveSwapFromDecimal: "6", + ActivePoolAddress: "0x48a953cA5cf5298bc6f6Af3C608351f537AAcb9e", + ActiveSwapFromAddress: "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", + ActiveSwapFromSym: "AMANI", + ActiveSwapToAddress: "0x765DE816845861e75A25fCA122bb6898B8B1282a", + ActiveSwapToSym: "cUSD", + ActiveSwapToDecimal: "18", + } + + data, err := ReadSwapPreviewData(ctx, store, sessionId) + + assert.NoError(t, err) + assert.Equal(t, expectedResult, data) +} -- 2.45.2 From ab5299fae20e34b481547f8ebbe9e5a3227c93fa Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 13 Mar 2025 13:15:38 +0300 Subject: [PATCH 31/33] Added TestGetSwapFromVoucherData --- store/swap_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/store/swap_test.go b/store/swap_test.go index d2a92fc..f2e254d 100644 --- a/store/swap_test.go +++ b/store/swap_test.go @@ -1,8 +1,11 @@ package store import ( + "context" "testing" + visedb "git.defalsify.org/vise.git/db" + memdb "git.defalsify.org/vise.git/db/mem" storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" "github.com/alecthomas/assert/v2" ) @@ -88,3 +91,40 @@ func TestReadSwapPreviewData(t *testing.T) { assert.NoError(t, err) assert.Equal(t, expectedResult, data) } + +func TestGetSwapFromVoucherData(t *testing.T) { + ctx := context.Background() + + db := memdb.NewMemDb() + err := db.Connect(ctx, "") + if err != nil { + t.Fatal(err) + } + + prefix := storedb.ToBytes(visedb.DATATYPE_USERDATA) + spdb := storedb.NewSubPrefixDb(db, prefix) + + // Test pool swap data + mockData := map[storedb.DataTyp][]byte{ + storedb.DATA_POOL_FROM_SYMBOLS: []byte("1:AMANI\n2:AMUA"), + storedb.DATA_POOL_FROM_BALANCES: []byte("1:\n2:"), + storedb.DATA_POOL_FROM_DECIMALS: []byte("1:6\n2:4"), + storedb.DATA_POOL_FROM_ADDRESSES: []byte("1:0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe\n2:0xF0C3C7581b8b96B59a97daEc8Bd48247cE078674"), + } + + // Put the data + for key, value := range mockData { + err = spdb.Put(ctx, []byte(storedb.ToBytes(key)), []byte(value)) + if err != nil { + t.Fatal(err) + } + } + + result, err := GetSwapFromVoucherData(ctx, spdb, "1") + + assert.NoError(t, err) + assert.Equal(t, "AMANI", result.TokenSymbol) + assert.Equal(t, "", result.Balance) + assert.Equal(t, "6", result.TokenDecimals) + assert.Equal(t, "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", result.ContractAddress) +} -- 2.45.2 From 2ace3606bc4045998c4ad0524c595d9b386983bd Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 13 Mar 2025 13:19:58 +0300 Subject: [PATCH 32/33] Added TestUpdateSwapFromVoucherData --- store/swap_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/store/swap_test.go b/store/swap_test.go index f2e254d..5e29df1 100644 --- a/store/swap_test.go +++ b/store/swap_test.go @@ -8,6 +8,8 @@ import ( memdb "git.defalsify.org/vise.git/db/mem" storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" "github.com/alecthomas/assert/v2" + dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" + "github.com/stretchr/testify/require" ) func TestReadSwapData(t *testing.T) { @@ -128,3 +130,40 @@ func TestGetSwapFromVoucherData(t *testing.T) { assert.Equal(t, "6", result.TokenDecimals) assert.Equal(t, "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", result.ContractAddress) } + +func TestUpdateSwapFromVoucherData(t *testing.T) { + ctx, store := InitializeTestDb(t) + sessionId := "session123" + + // New swap from voucher data + newData := &dataserviceapi.TokenHoldings{ + TokenSymbol: "AMANI", + TokenDecimals: "6", + ContractAddress: "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", + } + + // Old temporary data + tempData := &dataserviceapi.TokenHoldings{ + TokenSymbol: "OLD", + TokenDecimals: "8", + ContractAddress: "0xold", + } + require.NoError(t, StoreTemporaryVoucher(ctx, store, sessionId, tempData)) + + // Execute update + err := UpdateSwapFromVoucherData(ctx, store, sessionId, newData) + require.NoError(t, err) + + // Verify active swap from data was stored correctly + activeEntries := map[storedb.DataTyp][]byte{ + storedb.DATA_ACTIVE_SWAP_FROM_SYM: []byte(newData.TokenSymbol), + storedb.DATA_ACTIVE_SWAP_FROM_DECIMAL: []byte(newData.TokenDecimals), + storedb.DATA_ACTIVE_SWAP_FROM_ADDRESS: []byte(newData.ContractAddress), + } + + for key, expectedValue := range activeEntries { + storedValue, err := store.ReadEntry(ctx, sessionId, key) + require.NoError(t, err) + require.Equal(t, expectedValue, storedValue, "Active swap from data mismatch for key %v", key) + } +} \ No newline at end of file -- 2.45.2 From 724d11b4db06c9835b6449e2017f668157ebb4ba Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 13 Mar 2025 17:09:00 +0300 Subject: [PATCH 33/33] Added TestGetSwapToVoucherData --- store/swap_test.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/store/swap_test.go b/store/swap_test.go index 5e29df1..ee96066 100644 --- a/store/swap_test.go +++ b/store/swap_test.go @@ -166,4 +166,41 @@ func TestUpdateSwapFromVoucherData(t *testing.T) { require.NoError(t, err) require.Equal(t, expectedValue, storedValue, "Active swap from data mismatch for key %v", key) } +} + +func TestGetSwapToVoucherData(t *testing.T) { + ctx := context.Background() + + db := memdb.NewMemDb() + err := db.Connect(ctx, "") + if err != nil { + t.Fatal(err) + } + + prefix := storedb.ToBytes(visedb.DATATYPE_USERDATA) + spdb := storedb.NewSubPrefixDb(db, prefix) + + // Test pool swap data + mockData := map[storedb.DataTyp][]byte{ + storedb.DATA_POOL_TO_SYMBOLS: []byte("1:cUSD\n2:AMUA"), + storedb.DATA_POOL_TO_BALANCES: []byte("1:\n2:"), + storedb.DATA_POOL_TO_DECIMALS: []byte("1:6\n2:4"), + storedb.DATA_POOL_TO_ADDRESSES: []byte("1:0xc7B78Ac9ACB9E025C8234621\n2:0xF0C3C7581b8b96B59a97daEc8Bd48247cE078674"), + } + + // Put the data + for key, value := range mockData { + err = spdb.Put(ctx, []byte(storedb.ToBytes(key)), []byte(value)) + if err != nil { + t.Fatal(err) + } + } + + result, err := GetSwapToVoucherData(ctx, spdb, "1") + + assert.NoError(t, err) + assert.Equal(t, "cUSD", result.TokenSymbol) + assert.Equal(t, "", result.Balance) + assert.Equal(t, "6", result.TokenDecimals) + assert.Equal(t, "0xc7B78Ac9ACB9E025C8234621", result.ContractAddress) } \ No newline at end of file -- 2.45.2