From 3129e8210e848185701c328f1bf053e375d9b9ae Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 11 Dec 2024 19:25:38 +0300 Subject: [PATCH 01/20] Capitalize the transfer statement details --- common/transfer_statements.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/transfer_statements.go b/common/transfer_statements.go index 4e6f66b..243ef4c 100644 --- a/common/transfer_statements.go +++ b/common/transfer_statements.go @@ -84,18 +84,18 @@ func GetTransferData(ctx context.Context, db storage.PrefixDb, publicKey string, // Adjust for 0-based indexing i := index - 1 - transactionType := "received" - party := fmt.Sprintf("from: %s", strings.TrimSpace(senders[i])) + transactionType := "Received" + party := fmt.Sprintf("From: %s", strings.TrimSpace(senders[i])) if strings.TrimSpace(senders[i]) == publicKey { - transactionType = "sent" - party = fmt.Sprintf("to: %s", strings.TrimSpace(recipients[i])) + transactionType = "Sent" + party = fmt.Sprintf("To: %s", strings.TrimSpace(recipients[i])) } formattedDate := formatDate(strings.TrimSpace(dates[i])) // Build the full transaction detail detail := fmt.Sprintf( - "%s %s %s\n%s\ncontract address: %s\ntxhash: %s\ndate: %s", + "%s %s %s\n%s\nContract address: %s\nTxhash: %s\nDate: %s", transactionType, strings.TrimSpace(values[i]), strings.TrimSpace(syms[i]), From b1e4b63c6a3bd25998311aca149e08fa49ab7753 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 11 Dec 2024 19:28:53 +0300 Subject: [PATCH 02/20] Add a space after the colon for vouchers --- common/vouchers.go | 4 ++-- common/vouchers_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/vouchers.go b/common/vouchers.go index 6cff91d..790e3ca 100644 --- a/common/vouchers.go +++ b/common/vouchers.go @@ -24,7 +24,7 @@ func ProcessVouchers(holdings []dataserviceapi.TokenHoldings) VoucherMetadata { var symbols, balances, decimals, addresses []string for i, h := range holdings { - symbols = append(symbols, fmt.Sprintf("%d:%s", i+1, h.TokenSymbol)) + symbols = append(symbols, fmt.Sprintf("%d: %s", i+1, h.TokenSymbol)) // Scale down the balance scaledBalance := ScaleDownBalance(h.Balance, h.TokenDecimals) @@ -103,7 +103,7 @@ func MatchVoucher(input, symbols, balances, decimals, addresses string) (symbol, logg.Tracef("found", "symlist", symList, "syms", symbols, "input", input) for i, sym := range symList { - parts := strings.SplitN(sym, ":", 2) + parts := strings.SplitN(sym, ": ", 2) if input == parts[0] || strings.EqualFold(input, parts[1]) { symbol = parts[1] diff --git a/common/vouchers_test.go b/common/vouchers_test.go index ba6cd60..2ebb4a0 100644 --- a/common/vouchers_test.go +++ b/common/vouchers_test.go @@ -34,7 +34,7 @@ func InitializeTestDb(t *testing.T) (context.Context, *UserDataStore) { } func TestMatchVoucher(t *testing.T) { - symbols := "1:SRF\n2:MILO" + symbols := "1: SRF\n2: MILO" balances := "1:100\n2:200" decimals := "1:6\n2:4" addresses := "1:0xd4c288865Ce\n2:0x41c188d63Qa" @@ -65,7 +65,7 @@ func TestProcessVouchers(t *testing.T) { } expectedResult := VoucherMetadata{ - Symbols: "1:SRF\n2:MILO", + Symbols: "1: SRF\n2: MILO", Balances: "1:100\n2:20000", Decimals: "1:6\n2:4", Addresses: "1:0xd4c288865Ce\n2:0x41c188d63Qa", @@ -90,7 +90,7 @@ func TestGetVoucherData(t *testing.T) { // Test voucher data mockData := map[DataTyp][]byte{ - DATA_VOUCHER_SYMBOLS: []byte("1:SRF\n2:MILO"), + DATA_VOUCHER_SYMBOLS: []byte("1: SRF\n2: MILO"), DATA_VOUCHER_BALANCES: []byte("1:100\n2:200"), DATA_VOUCHER_DECIMALS: []byte("1:6\n2:4"), DATA_VOUCHER_ADDRESSES: []byte("1:0xd4c288865Ce\n2:0x41c188d63Qa"), From 6f3b30e2fe22ef20df038d5e0e99b0400a613bbb Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 11 Dec 2024 19:31:17 +0300 Subject: [PATCH 03/20] Capitalize statement details and add a space after the colon --- internal/handlers/ussd/menuhandler.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index c5356d0..f9d8728 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -1895,12 +1895,12 @@ func (h *Handlers) GetTransactionsList(ctx context.Context, sym string, input [] value := strings.TrimSpace(values[i]) date := strings.Split(strings.TrimSpace(dates[i]), " ")[0] - status := "received" + status := "Received" if sender == string(publicKey) { - status = "sent" + status = "Sent" } - formattedTransactions = append(formattedTransactions, fmt.Sprintf("%d:%s %s %s %s", i+1, status, value, sym, date)) + formattedTransactions = append(formattedTransactions, fmt.Sprintf("%d: %s %s %s %s", i+1, status, value, sym, date)) } res.Content = strings.Join(formattedTransactions, "\n") From 1a4ee0d3e1f322f296321f124b490ec14824a53c Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 11 Dec 2024 19:32:41 +0300 Subject: [PATCH 04/20] updated the description of the GetTransactionsList function --- internal/handlers/ussd/menuhandler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index f9d8728..5723bad 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -1846,7 +1846,7 @@ func (h *Handlers) CheckTransactions(ctx context.Context, sym string, input []by return res, nil } -// GetTransactionsList fetches the list of transactions and formats them +// GetTransactionsList reads the list of transactions from the db and formats them func (h *Handlers) GetTransactionsList(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result sessionId, ok := ctx.Value("SessionId").(string) From 2383e8ead3e9b97dc7d45f6667963a296b78edec Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 11 Dec 2024 19:35:04 +0300 Subject: [PATCH 05/20] updated failed menuhandler_test --- internal/handlers/ussd/menuhandler_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 25470e8..5cc3067 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -1961,7 +1961,7 @@ func TestCheckVouchers(t *testing.T) { {ContractAddress: "0x41c188d63Qa", TokenSymbol: "MILO", TokenDecimals: "4", Balance: "200"}, } - expectedSym := []byte("1:SRF\n2:MILO") + expectedSym := []byte("1: SRF\n2: MILO") mockAccountService.On("FetchVouchers", string(publicKey)).Return(mockVouchersResponse, nil) @@ -2024,7 +2024,7 @@ func TestViewVoucher(t *testing.T) { // Define mock voucher data mockData := map[common.DataTyp][]byte{ - common.DATA_VOUCHER_SYMBOLS: []byte("1:SRF\n2:MILO"), + common.DATA_VOUCHER_SYMBOLS: []byte("1: SRF\n2: MILO"), common.DATA_VOUCHER_BALANCES: []byte("1:100\n2:200"), common.DATA_VOUCHER_DECIMALS: []byte("1:6\n2:4"), common.DATA_VOUCHER_ADDRESSES: []byte("1:0xd4c288865Ce\n2:0x41c188d63Qa"), From e05f8e72917fc013fab3494757d8b0777a71c7c2 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 11 Dec 2024 19:46:52 +0300 Subject: [PATCH 06/20] update to the latest go-vise changes --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index d89f0f3..d6f620f 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module git.grassecon.net/urdt/ussd go 1.23.0 require ( - git.defalsify.org/vise.git v0.2.1-0.20241122120231-9e9ee5bdfa7a + git.defalsify.org/vise.git v0.2.1-0.20241209194740-26fc82a76ede github.com/alecthomas/assert/v2 v2.2.2 github.com/gofrs/uuid v4.4.0+incompatible github.com/grassrootseconomics/eth-custodial v1.3.0-beta diff --git a/go.sum b/go.sum index 5532c1c..e64d16f 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ git.defalsify.org/vise.git v0.2.1-0.20241122120231-9e9ee5bdfa7a h1:LvGKktk0kUnuRN3nF9r15D8OoV0sFaMmQr52kGq2gtE= git.defalsify.org/vise.git v0.2.1-0.20241122120231-9e9ee5bdfa7a/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck= +git.defalsify.org/vise.git v0.2.1-0.20241209194740-26fc82a76ede h1:BtooQZJDYEgeRKqv8RSxYSbW5jh0UIFJ6zRMEZZn0sc= +git.defalsify.org/vise.git v0.2.1-0.20241209194740-26fc82a76ede/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck= github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g= From 0d7f7aaca139aed0a6d2cf0e19082bd847805870 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 12 Dec 2024 21:09:48 +0300 Subject: [PATCH 07/20] use latest commits from go-vise --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index d6f620f..246c57d 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module git.grassecon.net/urdt/ussd go 1.23.0 require ( - git.defalsify.org/vise.git v0.2.1-0.20241209194740-26fc82a76ede + git.defalsify.org/vise.git v0.2.1-0.20241212130612-18a95521a7cf github.com/alecthomas/assert/v2 v2.2.2 github.com/gofrs/uuid v4.4.0+incompatible github.com/grassrootseconomics/eth-custodial v1.3.0-beta diff --git a/go.sum b/go.sum index e64d16f..a21aa2f 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ git.defalsify.org/vise.git v0.2.1-0.20241122120231-9e9ee5bdfa7a h1:LvGKktk0kUnuR git.defalsify.org/vise.git v0.2.1-0.20241122120231-9e9ee5bdfa7a/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck= git.defalsify.org/vise.git v0.2.1-0.20241209194740-26fc82a76ede h1:BtooQZJDYEgeRKqv8RSxYSbW5jh0UIFJ6zRMEZZn0sc= git.defalsify.org/vise.git v0.2.1-0.20241209194740-26fc82a76ede/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck= +git.defalsify.org/vise.git v0.2.1-0.20241212130612-18a95521a7cf h1:K58RcCiBZSmfU7zwg4nCHzY5ikw+wyfFoDU+4SXkarU= +git.defalsify.org/vise.git v0.2.1-0.20241212130612-18a95521a7cf/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck= github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g= From 6cc285d1e8e2184466cab608581cbc2be14be078 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 12 Dec 2024 21:12:25 +0300 Subject: [PATCH 08/20] add the custom separator to the menu --- cmd/africastalking/main.go | 9 ++++++--- cmd/async/main.go | 9 ++++++--- cmd/http/main.go | 9 ++++++--- cmd/main.go | 11 +++++++---- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/cmd/africastalking/main.go b/cmd/africastalking/main.go index 7d1caa8..f57f8f4 100644 --- a/cmd/africastalking/main.go +++ b/cmd/africastalking/main.go @@ -115,6 +115,7 @@ func main() { var engineDebug bool var host string var port uint + var separator string flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") flag.StringVar(&resourceDir, "resourcedir", path.Join("services", "registration"), "resource dir") flag.StringVar(&database, "db", "gdbm", "database to be used") @@ -122,6 +123,7 @@ func main() { flag.UintVar(&size, "s", 160, "max size of output") flag.StringVar(&host, "h", initializers.GetEnv("HOST", "127.0.0.1"), "http host") flag.UintVar(&port, "p", initializers.GetEnvUint("PORT", 7123), "http port") + flag.StringVar(&separator, "sep", ": ", "custom separator for the menu") flag.Parse() logg.Infof("start command", "build", build, "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size) @@ -131,9 +133,10 @@ func main() { pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ - Root: "root", - OutputSize: uint32(size), - FlagCount: uint32(128), + Root: "root", + OutputSize: uint32(size), + FlagCount: uint32(128), + MenuSeparator: separator, } if engineDebug { diff --git a/cmd/async/main.go b/cmd/async/main.go index e4c94b0..1fdc532 100644 --- a/cmd/async/main.go +++ b/cmd/async/main.go @@ -53,6 +53,7 @@ func main() { var engineDebug bool var host string var port uint + var separator string flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") flag.StringVar(&resourceDir, "resourcedir", path.Join("services", "registration"), "resource dir") @@ -61,6 +62,7 @@ func main() { flag.UintVar(&size, "s", 160, "max size of output") flag.StringVar(&host, "h", initializers.GetEnv("HOST", "127.0.0.1"), "http host") flag.UintVar(&port, "p", initializers.GetEnvUint("PORT", 7123), "http port") + flag.StringVar(&separator, "sep", ": ", "custom separator for the menu") flag.Parse() logg.Infof("start command", "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size, "sessionId", sessionId) @@ -70,9 +72,10 @@ func main() { pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ - Root: "root", - OutputSize: uint32(size), - FlagCount: uint32(128), + Root: "root", + OutputSize: uint32(size), + FlagCount: uint32(128), + MenuSeparator: separator, } if engineDebug { diff --git a/cmd/http/main.go b/cmd/http/main.go index 96e2688..aa7d00a 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -42,6 +42,7 @@ func main() { var engineDebug bool var host string var port uint + var separator string flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") flag.StringVar(&resourceDir, "resourcedir", path.Join("services", "registration"), "resource dir") flag.StringVar(&database, "db", "gdbm", "database to be used") @@ -49,6 +50,7 @@ func main() { flag.UintVar(&size, "s", 160, "max size of output") flag.StringVar(&host, "h", initializers.GetEnv("HOST", "127.0.0.1"), "http host") flag.UintVar(&port, "p", initializers.GetEnvUint("PORT", 7123), "http port") + flag.StringVar(&separator, "sep", ": ", "custom separator for the menu") flag.Parse() logg.Infof("start command", "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size) @@ -58,9 +60,10 @@ func main() { pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ - Root: "root", - OutputSize: uint32(size), - FlagCount: uint32(128), + Root: "root", + OutputSize: uint32(size), + FlagCount: uint32(128), + MenuSeparator: separator, } if engineDebug { diff --git a/cmd/main.go b/cmd/main.go index 9599eb7..aec6a14 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -34,11 +34,13 @@ func main() { var sessionId string var database string var engineDebug bool + var separator string flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&database, "db", "gdbm", "database to be used") flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") flag.BoolVar(&engineDebug, "d", false, "use engine debug output") flag.UintVar(&size, "s", 160, "max size of output") + flag.StringVar(&separator, "sep", ": ", "custom separator for the menu") flag.Parse() logg.Infof("start command", "dbdir", dbDir, "outputsize", size) @@ -49,10 +51,11 @@ func main() { pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ - Root: "root", - SessionId: sessionId, - OutputSize: uint32(size), - FlagCount: uint32(128), + Root: "root", + SessionId: sessionId, + OutputSize: uint32(size), + FlagCount: uint32(128), + MenuSeparator: separator, } resourceDir := scriptDir From f38ea59569404c8fa967f6d78279a2227f421a16 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Fri, 13 Dec 2024 01:10:46 +0300 Subject: [PATCH 09/20] set the separator as a config and not an arg --- cmd/africastalking/main.go | 4 +--- cmd/async/main.go | 4 +--- cmd/http/main.go | 4 +--- cmd/main.go | 4 +--- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/cmd/africastalking/main.go b/cmd/africastalking/main.go index f57f8f4..11d78b2 100644 --- a/cmd/africastalking/main.go +++ b/cmd/africastalking/main.go @@ -115,7 +115,6 @@ func main() { var engineDebug bool var host string var port uint - var separator string flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") flag.StringVar(&resourceDir, "resourcedir", path.Join("services", "registration"), "resource dir") flag.StringVar(&database, "db", "gdbm", "database to be used") @@ -123,7 +122,6 @@ func main() { flag.UintVar(&size, "s", 160, "max size of output") flag.StringVar(&host, "h", initializers.GetEnv("HOST", "127.0.0.1"), "http host") flag.UintVar(&port, "p", initializers.GetEnvUint("PORT", 7123), "http port") - flag.StringVar(&separator, "sep", ": ", "custom separator for the menu") flag.Parse() logg.Infof("start command", "build", build, "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size) @@ -136,7 +134,7 @@ func main() { Root: "root", OutputSize: uint32(size), FlagCount: uint32(128), - MenuSeparator: separator, + MenuSeparator: ": ", } if engineDebug { diff --git a/cmd/async/main.go b/cmd/async/main.go index 1fdc532..a5cac92 100644 --- a/cmd/async/main.go +++ b/cmd/async/main.go @@ -53,7 +53,6 @@ func main() { var engineDebug bool var host string var port uint - var separator string flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") flag.StringVar(&resourceDir, "resourcedir", path.Join("services", "registration"), "resource dir") @@ -62,7 +61,6 @@ func main() { flag.UintVar(&size, "s", 160, "max size of output") flag.StringVar(&host, "h", initializers.GetEnv("HOST", "127.0.0.1"), "http host") flag.UintVar(&port, "p", initializers.GetEnvUint("PORT", 7123), "http port") - flag.StringVar(&separator, "sep", ": ", "custom separator for the menu") flag.Parse() logg.Infof("start command", "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size, "sessionId", sessionId) @@ -75,7 +73,7 @@ func main() { Root: "root", OutputSize: uint32(size), FlagCount: uint32(128), - MenuSeparator: separator, + MenuSeparator: ": ", } if engineDebug { diff --git a/cmd/http/main.go b/cmd/http/main.go index aa7d00a..451d693 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -42,7 +42,6 @@ func main() { var engineDebug bool var host string var port uint - var separator string flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") flag.StringVar(&resourceDir, "resourcedir", path.Join("services", "registration"), "resource dir") flag.StringVar(&database, "db", "gdbm", "database to be used") @@ -50,7 +49,6 @@ func main() { flag.UintVar(&size, "s", 160, "max size of output") flag.StringVar(&host, "h", initializers.GetEnv("HOST", "127.0.0.1"), "http host") flag.UintVar(&port, "p", initializers.GetEnvUint("PORT", 7123), "http port") - flag.StringVar(&separator, "sep", ": ", "custom separator for the menu") flag.Parse() logg.Infof("start command", "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size) @@ -63,7 +61,7 @@ func main() { Root: "root", OutputSize: uint32(size), FlagCount: uint32(128), - MenuSeparator: separator, + MenuSeparator: ": ", } if engineDebug { diff --git a/cmd/main.go b/cmd/main.go index aec6a14..ddcf7a5 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -34,13 +34,11 @@ func main() { var sessionId string var database string var engineDebug bool - var separator string flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&database, "db", "gdbm", "database to be used") flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") flag.BoolVar(&engineDebug, "d", false, "use engine debug output") flag.UintVar(&size, "s", 160, "max size of output") - flag.StringVar(&separator, "sep", ": ", "custom separator for the menu") flag.Parse() logg.Infof("start command", "dbdir", dbDir, "outputsize", size) @@ -55,7 +53,7 @@ func main() { SessionId: sessionId, OutputSize: uint32(size), FlagCount: uint32(128), - MenuSeparator: separator, + MenuSeparator: ": ", } resourceDir := scriptDir From 64c1fe5276775e160bd5fe4e85cee3fed5d6329a Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Fri, 13 Dec 2024 11:38:10 +0300 Subject: [PATCH 10/20] set the separator as a var and add it to the context --- cmd/africastalking/main.go | 11 ++++++----- cmd/async/main.go | 4 +++- cmd/http/main.go | 4 +++- cmd/main.go | 8 +++++--- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/cmd/africastalking/main.go b/cmd/africastalking/main.go index 11d78b2..58025e0 100644 --- a/cmd/africastalking/main.go +++ b/cmd/africastalking/main.go @@ -30,10 +30,10 @@ import ( ) var ( - logg = logging.NewVanilla() - scriptDir = path.Join("services", "registration") - - build = "dev" + logg = logging.NewVanilla() + scriptDir = path.Join("services", "registration") + build = "dev" + menuSeparator = ": " ) func init() { @@ -128,13 +128,14 @@ func main() { ctx := context.Background() ctx = context.WithValue(ctx, "Database", database) + ctx = context.WithValue(ctx, "MenuSeparator", menuSeparator) pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ Root: "root", OutputSize: uint32(size), FlagCount: uint32(128), - MenuSeparator: ": ", + MenuSeparator: menuSeparator, } if engineDebug { diff --git a/cmd/async/main.go b/cmd/async/main.go index a5cac92..e63f42a 100644 --- a/cmd/async/main.go +++ b/cmd/async/main.go @@ -23,6 +23,7 @@ import ( var ( logg = logging.NewVanilla() scriptDir = path.Join("services", "registration") + menuSeparator = ": " ) func init() { @@ -67,13 +68,14 @@ func main() { ctx := context.Background() ctx = context.WithValue(ctx, "Database", database) + ctx = context.WithValue(ctx, "MenuSeparator", menuSeparator) pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ Root: "root", OutputSize: uint32(size), FlagCount: uint32(128), - MenuSeparator: ": ", + MenuSeparator: menuSeparator, } if engineDebug { diff --git a/cmd/http/main.go b/cmd/http/main.go index 451d693..5196d5f 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -26,6 +26,7 @@ import ( var ( logg = logging.NewVanilla() scriptDir = path.Join("services", "registration") + menuSeparator = ": " ) func init() { @@ -55,13 +56,14 @@ func main() { ctx := context.Background() ctx = context.WithValue(ctx, "Database", database) + ctx = context.WithValue(ctx, "MenuSeparator", menuSeparator) pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ Root: "root", OutputSize: uint32(size), FlagCount: uint32(128), - MenuSeparator: ": ", + MenuSeparator: menuSeparator, } if engineDebug { diff --git a/cmd/main.go b/cmd/main.go index ddcf7a5..62d16a7 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -18,8 +18,9 @@ import ( ) var ( - logg = logging.NewVanilla() - scriptDir = path.Join("services", "registration") + logg = logging.NewVanilla() + scriptDir = path.Join("services", "registration") + menuSeparator = ": " ) func init() { @@ -46,6 +47,7 @@ func main() { ctx := context.Background() ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "Database", database) + ctx = context.WithValue(ctx, "MenuSeparator", menuSeparator) pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ @@ -53,7 +55,7 @@ func main() { SessionId: sessionId, OutputSize: uint32(size), FlagCount: uint32(128), - MenuSeparator: ": ", + MenuSeparator: menuSeparator, } resourceDir := scriptDir From df5e5f1a4bea91849564cf3963337800f5c473d1 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Fri, 13 Dec 2024 11:40:39 +0300 Subject: [PATCH 11/20] properly format the vouchers --- common/vouchers.go | 4 ++-- common/vouchers_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/vouchers.go b/common/vouchers.go index 790e3ca..6cff91d 100644 --- a/common/vouchers.go +++ b/common/vouchers.go @@ -24,7 +24,7 @@ func ProcessVouchers(holdings []dataserviceapi.TokenHoldings) VoucherMetadata { var symbols, balances, decimals, addresses []string for i, h := range holdings { - symbols = append(symbols, fmt.Sprintf("%d: %s", i+1, h.TokenSymbol)) + symbols = append(symbols, fmt.Sprintf("%d:%s", i+1, h.TokenSymbol)) // Scale down the balance scaledBalance := ScaleDownBalance(h.Balance, h.TokenDecimals) @@ -103,7 +103,7 @@ func MatchVoucher(input, symbols, balances, decimals, addresses string) (symbol, logg.Tracef("found", "symlist", symList, "syms", symbols, "input", input) for i, sym := range symList { - parts := strings.SplitN(sym, ": ", 2) + parts := strings.SplitN(sym, ":", 2) if input == parts[0] || strings.EqualFold(input, parts[1]) { symbol = parts[1] diff --git a/common/vouchers_test.go b/common/vouchers_test.go index 2ebb4a0..ba6cd60 100644 --- a/common/vouchers_test.go +++ b/common/vouchers_test.go @@ -34,7 +34,7 @@ func InitializeTestDb(t *testing.T) (context.Context, *UserDataStore) { } func TestMatchVoucher(t *testing.T) { - symbols := "1: SRF\n2: MILO" + symbols := "1:SRF\n2:MILO" balances := "1:100\n2:200" decimals := "1:6\n2:4" addresses := "1:0xd4c288865Ce\n2:0x41c188d63Qa" @@ -65,7 +65,7 @@ func TestProcessVouchers(t *testing.T) { } expectedResult := VoucherMetadata{ - Symbols: "1: SRF\n2: MILO", + Symbols: "1:SRF\n2:MILO", Balances: "1:100\n2:20000", Decimals: "1:6\n2:4", Addresses: "1:0xd4c288865Ce\n2:0x41c188d63Qa", @@ -90,7 +90,7 @@ func TestGetVoucherData(t *testing.T) { // Test voucher data mockData := map[DataTyp][]byte{ - DATA_VOUCHER_SYMBOLS: []byte("1: SRF\n2: MILO"), + DATA_VOUCHER_SYMBOLS: []byte("1:SRF\n2:MILO"), DATA_VOUCHER_BALANCES: []byte("1:100\n2:200"), DATA_VOUCHER_DECIMALS: []byte("1:6\n2:4"), DATA_VOUCHER_ADDRESSES: []byte("1:0xd4c288865Ce\n2:0x41c188d63Qa"), From 5cd791aae7f5900d046ce918b2cb61518720a363 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Fri, 13 Dec 2024 11:43:47 +0300 Subject: [PATCH 12/20] use the MenuSeparator --- internal/handlers/ussd/menuhandler.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 5723bad..d1d246a 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -1676,6 +1676,11 @@ func (h *Handlers) CheckVouchers(ctx context.Context, sym string, input []byte) func (h *Handlers) GetVoucherList(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result + menuSeparator, ok := ctx.Value("MenuSeparator").(string) + if !ok { + return res, fmt.Errorf("missing menu Separator") + } + // Read vouchers from the store voucherData, err := h.prefixDb.Get(ctx, common.ToBytes(common.DATA_VOUCHER_SYMBOLS)) if err != nil { @@ -1683,7 +1688,9 @@ func (h *Handlers) GetVoucherList(ctx context.Context, sym string, input []byte) return res, err } - res.Content = string(voucherData) + formattedData := strings.ReplaceAll(string(voucherData), ":", menuSeparator) + + res.Content = string(formattedData) return res, nil } @@ -1853,6 +1860,12 @@ func (h *Handlers) GetTransactionsList(ctx context.Context, sym string, input [] if !ok { return res, fmt.Errorf("missing session") } + + menuSeparator, ok := ctx.Value("MenuSeparator").(string) + if !ok { + return res, fmt.Errorf("missing menu Separator") + } + store := h.userdataStore publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY) if err != nil { @@ -1900,7 +1913,7 @@ func (h *Handlers) GetTransactionsList(ctx context.Context, sym string, input [] status = "Sent" } - formattedTransactions = append(formattedTransactions, fmt.Sprintf("%d: %s %s %s %s", i+1, status, value, sym, date)) + formattedTransactions = append(formattedTransactions, fmt.Sprintf("%d%s%s %s %s %s", i+1, menuSeparator, status, value, sym, date)) } res.Content = strings.Join(formattedTransactions, "\n") From 7aea2af9a1baca5ca5b9ef3ac38ef74f6b1b08d3 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Fri, 13 Dec 2024 11:44:04 +0300 Subject: [PATCH 13/20] updated tests --- internal/handlers/ussd/menuhandler_test.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 5cc3067..01beb89 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -1961,7 +1961,7 @@ func TestCheckVouchers(t *testing.T) { {ContractAddress: "0x41c188d63Qa", TokenSymbol: "MILO", TokenDecimals: "4", Balance: "200"}, } - expectedSym := []byte("1: SRF\n2: MILO") + expectedSym := []byte("1:SRF\n2:MILO") mockAccountService.On("FetchVouchers", string(publicKey)).Return(mockVouchersResponse, nil) @@ -1982,7 +1982,11 @@ func TestCheckVouchers(t *testing.T) { func TestGetVoucherList(t *testing.T) { sessionId := "session123" + menuSeparator := ":" + ctx := context.WithValue(context.Background(), "SessionId", sessionId) + ctx = context.WithValue(ctx, "MenuSeparator", menuSeparator) + spdb := InitializeTestSubPrefixDb(t, ctx) @@ -2024,7 +2028,7 @@ func TestViewVoucher(t *testing.T) { // Define mock voucher data mockData := map[common.DataTyp][]byte{ - common.DATA_VOUCHER_SYMBOLS: []byte("1: SRF\n2: MILO"), + common.DATA_VOUCHER_SYMBOLS: []byte("1:SRF\n2:MILO"), common.DATA_VOUCHER_BALANCES: []byte("1:100\n2:200"), common.DATA_VOUCHER_DECIMALS: []byte("1:6\n2:4"), common.DATA_VOUCHER_ADDRESSES: []byte("1:0xd4c288865Ce\n2:0x41c188d63Qa"), From 17ba6a06bacdc1398095fd9a2ea0e72094e097f9 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 18 Dec 2024 21:49:42 +0300 Subject: [PATCH 14/20] remove the MenuSeparator from the context --- cmd/africastalking/main.go | 1 - cmd/async/main.go | 1 - cmd/http/main.go | 1 - cmd/main.go | 1 - 4 files changed, 4 deletions(-) diff --git a/cmd/africastalking/main.go b/cmd/africastalking/main.go index 58025e0..3d11ba5 100644 --- a/cmd/africastalking/main.go +++ b/cmd/africastalking/main.go @@ -128,7 +128,6 @@ func main() { ctx := context.Background() ctx = context.WithValue(ctx, "Database", database) - ctx = context.WithValue(ctx, "MenuSeparator", menuSeparator) pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ diff --git a/cmd/async/main.go b/cmd/async/main.go index e63f42a..9cd04b3 100644 --- a/cmd/async/main.go +++ b/cmd/async/main.go @@ -68,7 +68,6 @@ func main() { ctx := context.Background() ctx = context.WithValue(ctx, "Database", database) - ctx = context.WithValue(ctx, "MenuSeparator", menuSeparator) pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ diff --git a/cmd/http/main.go b/cmd/http/main.go index 5196d5f..6ddfded 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -56,7 +56,6 @@ func main() { ctx := context.Background() ctx = context.WithValue(ctx, "Database", database) - ctx = context.WithValue(ctx, "MenuSeparator", menuSeparator) pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ diff --git a/cmd/main.go b/cmd/main.go index 62d16a7..4fd084f 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -47,7 +47,6 @@ func main() { ctx := context.Background() ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "Database", database) - ctx = context.WithValue(ctx, "MenuSeparator", menuSeparator) pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ From d08afff44395133495873cec2ea07b55b550524c Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 18 Dec 2024 21:56:37 +0300 Subject: [PATCH 15/20] add the replaceSeparator func and pass it to the Handler struct --- internal/handlers/handlerservice.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index a14cf59..417fe18 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -2,6 +2,7 @@ package handlers import ( "context" + "strings" "git.defalsify.org/vise.git/asm" "git.defalsify.org/vise.git/db" @@ -64,7 +65,11 @@ func (ls *LocalHandlerService) SetDataStore(db *db.Db) { } func (ls *LocalHandlerService) GetHandler(accountService remote.AccountServiceInterface) (*ussd.Handlers, error) { - ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore, ls.AdminStore, accountService) + replaceSeparator := func(input string) string { + return strings.ReplaceAll(input, ":", ls.Cfg.MenuSeparator) + } + + ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore, ls.AdminStore, accountService, replaceSeparator) if err != nil { return nil, err } From fda68231eacefcdb20edab828f3903b1fc8642c3 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 18 Dec 2024 21:59:09 +0300 Subject: [PATCH 16/20] use the replaceSeparator func to format the generated menus --- internal/handlers/ussd/menuhandler.go | 50 ++++++++++++--------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index d1d246a..7b238e3 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -69,18 +69,19 @@ func (fm *FlagManager) GetFlag(label string) (uint32, error) { } type Handlers struct { - pe *persist.Persister - st *state.State - ca cache.Memory - userdataStore common.DataStore - adminstore *utils.AdminStore - flagManager *asm.FlagParser - accountService remote.AccountServiceInterface - prefixDb storage.PrefixDb - profile *models.Profile + pe *persist.Persister + st *state.State + ca cache.Memory + userdataStore common.DataStore + adminstore *utils.AdminStore + flagManager *asm.FlagParser + accountService remote.AccountServiceInterface + prefixDb storage.PrefixDb + profile *models.Profile + ReplaceSeparator func(string) string } -func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *utils.AdminStore, accountService remote.AccountServiceInterface) (*Handlers, error) { +func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *utils.AdminStore, accountService remote.AccountServiceInterface, replaceSeparator func(string) string) (*Handlers, error) { if userdataStore == nil { return nil, fmt.Errorf("cannot create handler with nil userdata store") } @@ -93,12 +94,13 @@ func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *util prefixDb := storage.NewSubPrefixDb(userdataStore, prefix) h := &Handlers{ - userdataStore: userDb, - flagManager: appFlags, - adminstore: adminstore, - accountService: accountService, - prefixDb: prefixDb, - profile: &models.Profile{Max: 6}, + userdataStore: userDb, + flagManager: appFlags, + adminstore: adminstore, + accountService: accountService, + prefixDb: prefixDb, + profile: &models.Profile{Max: 6}, + ReplaceSeparator: replaceSeparator, } return h, nil } @@ -1676,11 +1678,6 @@ func (h *Handlers) CheckVouchers(ctx context.Context, sym string, input []byte) func (h *Handlers) GetVoucherList(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result - menuSeparator, ok := ctx.Value("MenuSeparator").(string) - if !ok { - return res, fmt.Errorf("missing menu Separator") - } - // Read vouchers from the store voucherData, err := h.prefixDb.Get(ctx, common.ToBytes(common.DATA_VOUCHER_SYMBOLS)) if err != nil { @@ -1688,7 +1685,7 @@ func (h *Handlers) GetVoucherList(ctx context.Context, sym string, input []byte) return res, err } - formattedData := strings.ReplaceAll(string(voucherData), ":", menuSeparator) + formattedData := h.ReplaceSeparator(string(voucherData)) res.Content = string(formattedData) @@ -1861,11 +1858,6 @@ func (h *Handlers) GetTransactionsList(ctx context.Context, sym string, input [] return res, fmt.Errorf("missing session") } - menuSeparator, ok := ctx.Value("MenuSeparator").(string) - if !ok { - return res, fmt.Errorf("missing menu Separator") - } - store := h.userdataStore publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY) if err != nil { @@ -1913,7 +1905,9 @@ func (h *Handlers) GetTransactionsList(ctx context.Context, sym string, input [] status = "Sent" } - formattedTransactions = append(formattedTransactions, fmt.Sprintf("%d%s%s %s %s %s", i+1, menuSeparator, status, value, sym, date)) + // Use the ReplaceSeparator function for the menu separator + transactionLine := fmt.Sprintf("%d%s%s %s %s %s", i+1, h.ReplaceSeparator(":"), status, value, sym, date) + formattedTransactions = append(formattedTransactions, transactionLine) } res.Content = strings.Join(formattedTransactions, "\n") From ecfdab47a8cc0f12e0b4cea6889069421a1adf21 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 18 Dec 2024 22:21:52 +0300 Subject: [PATCH 17/20] updated test --- internal/handlers/ussd/menuhandler_test.go | 58 ++++++++++++++++------ 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 01beb89..22c02e9 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "path" + "strings" "testing" "git.defalsify.org/vise.git/lang" @@ -67,12 +68,20 @@ func TestNewHandlers(t *testing.T) { _, store := InitializeTestStore(t) fm, err := NewFlagManager(flagsPath) - accountService := testservice.TestAccountService{} if err != nil { - t.Logf(err.Error()) + log.Fatal(err) } + + accountService := testservice.TestAccountService{} + + // Mock function for replaceSeparator + mockReplaceSeparator := func(input string) string { + return strings.ReplaceAll(input, ":", ": ") + } + + // Test case for valid UserDataStore t.Run("Valid UserDataStore", func(t *testing.T) { - handlers, err := NewHandlers(fm.parser, store, nil, &accountService) + handlers, err := NewHandlers(fm.parser, store, nil, &accountService, mockReplaceSeparator) if err != nil { t.Fatalf("expected no error, got %v", err) } @@ -82,19 +91,30 @@ func TestNewHandlers(t *testing.T) { if handlers.userdataStore == nil { t.Fatal("expected userdataStore to be set in handlers") } + if handlers.ReplaceSeparator == nil { + t.Fatal("expected ReplaceSeparator to be set in handlers") + } + + // Test ReplaceSeparator functionality + input := "1:Menu item" + expectedOutput := "1: Menu item" + if handlers.ReplaceSeparator(input) != expectedOutput { + t.Fatalf("ReplaceSeparator function did not return expected output: got %v, want %v", handlers.ReplaceSeparator(input), expectedOutput) + } }) - // Test case for nil userdataStore + // Test case for nil UserDataStore t.Run("Nil UserDataStore", func(t *testing.T) { - handlers, err := NewHandlers(fm.parser, nil, nil, &accountService) + handlers, err := NewHandlers(fm.parser, nil, nil, &accountService, mockReplaceSeparator) if err == nil { t.Fatal("expected an error, got none") } if handlers != nil { t.Fatal("expected handlers to be nil") } - if err.Error() != "cannot create handler with nil userdata store" { - t.Fatalf("expected specific error, got %v", err) + expectedError := "cannot create handler with nil userdata store" + if err.Error() != expectedError { + t.Fatalf("expected error '%s', got '%v'", expectedError, err) } }) } @@ -1982,30 +2002,36 @@ func TestCheckVouchers(t *testing.T) { func TestGetVoucherList(t *testing.T) { sessionId := "session123" - menuSeparator := ":" - + ctx := context.WithValue(context.Background(), "SessionId", sessionId) - ctx = context.WithValue(ctx, "MenuSeparator", menuSeparator) - spdb := InitializeTestSubPrefixDb(t, ctx) - h := &Handlers{ - prefixDb: spdb, + // Mock replaceSeparator function + replaceSeparator := func(input string) string { + return strings.ReplaceAll(input, ":", ": ") } - expectedSym := []byte("1:SRF\n2:MILO") + // Initialize Handlers + h := &Handlers{ + prefixDb: spdb, + ReplaceSeparator: replaceSeparator, + } + + mockSyms := []byte("1:SRF\n2:MILO") // Put voucher sym data from the store - err := spdb.Put(ctx, common.ToBytes(common.DATA_VOUCHER_SYMBOLS), expectedSym) + err := spdb.Put(ctx, common.ToBytes(common.DATA_VOUCHER_SYMBOLS), mockSyms) if err != nil { t.Fatal(err) } + expectedSyms := []byte("1: SRF\n2: MILO") + res, err := h.GetVoucherList(ctx, "", []byte("")) assert.NoError(t, err) - assert.Equal(t, res.Content, string(expectedSym)) + assert.Equal(t, res.Content, string(expectedSyms)) } func TestViewVoucher(t *testing.T) { From 055c2db790281cfc9517f7aa878c32f2329b5670 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 18 Dec 2024 22:25:47 +0300 Subject: [PATCH 18/20] use a common mockReplaceSeparator func --- internal/handlers/ussd/menuhandler_test.go | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 22c02e9..3c32ee0 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -33,6 +33,11 @@ var ( flagsPath = path.Join(baseDir, "services", "registration", "pp.csv") ) +// mockReplaceSeparator function +var mockReplaceSeparator = func(input string) string { + return strings.ReplaceAll(input, ":", ": ") +} + // InitializeTestStore sets up and returns an in-memory database and store. func InitializeTestStore(t *testing.T) (context.Context, *common.UserDataStore) { ctx := context.Background() @@ -74,11 +79,6 @@ func TestNewHandlers(t *testing.T) { accountService := testservice.TestAccountService{} - // Mock function for replaceSeparator - mockReplaceSeparator := func(input string) string { - return strings.ReplaceAll(input, ":", ": ") - } - // Test case for valid UserDataStore t.Run("Valid UserDataStore", func(t *testing.T) { handlers, err := NewHandlers(fm.parser, store, nil, &accountService, mockReplaceSeparator) @@ -2007,15 +2007,10 @@ func TestGetVoucherList(t *testing.T) { spdb := InitializeTestSubPrefixDb(t, ctx) - // Mock replaceSeparator function - replaceSeparator := func(input string) string { - return strings.ReplaceAll(input, ":", ": ") - } - // Initialize Handlers h := &Handlers{ prefixDb: spdb, - ReplaceSeparator: replaceSeparator, + ReplaceSeparator: mockReplaceSeparator, } mockSyms := []byte("1:SRF\n2:MILO") From 12928512264e6144c20169bcde51fed7c704eece Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 19 Dec 2024 13:32:39 +0300 Subject: [PATCH 19/20] rename the function to ReplaceSeparatorFunc --- internal/handlers/handlerservice.go | 4 ++-- internal/handlers/ussd/menuhandler.go | 10 +++++----- internal/handlers/ussd/menuhandler_test.go | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index 417fe18..015098e 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -65,11 +65,11 @@ func (ls *LocalHandlerService) SetDataStore(db *db.Db) { } func (ls *LocalHandlerService) GetHandler(accountService remote.AccountServiceInterface) (*ussd.Handlers, error) { - replaceSeparator := func(input string) string { + replaceSeparatorFunc := func(input string) string { return strings.ReplaceAll(input, ":", ls.Cfg.MenuSeparator) } - ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore, ls.AdminStore, accountService, replaceSeparator) + ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore, ls.AdminStore, accountService, replaceSeparatorFunc) if err != nil { return nil, err } diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index f506793..986f8f0 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -78,10 +78,10 @@ type Handlers struct { accountService remote.AccountServiceInterface prefixDb storage.PrefixDb profile *models.Profile - ReplaceSeparator func(string) string + ReplaceSeparatorFunc func(string) string } -func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *utils.AdminStore, accountService remote.AccountServiceInterface, replaceSeparator func(string) string) (*Handlers, error) { +func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *utils.AdminStore, accountService remote.AccountServiceInterface, replaceSeparatorFunc func(string) string) (*Handlers, error) { if userdataStore == nil { return nil, fmt.Errorf("cannot create handler with nil userdata store") } @@ -100,7 +100,7 @@ func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *util accountService: accountService, prefixDb: prefixDb, profile: &models.Profile{Max: 6}, - ReplaceSeparator: replaceSeparator, + ReplaceSeparatorFunc: replaceSeparatorFunc, } return h, nil } @@ -1685,7 +1685,7 @@ func (h *Handlers) GetVoucherList(ctx context.Context, sym string, input []byte) return res, err } - formattedData := h.ReplaceSeparator(string(voucherData)) + formattedData := h.ReplaceSeparatorFunc(string(voucherData)) res.Content = string(formattedData) @@ -1906,7 +1906,7 @@ func (h *Handlers) GetTransactionsList(ctx context.Context, sym string, input [] } // Use the ReplaceSeparator function for the menu separator - transactionLine := fmt.Sprintf("%d%s%s %s %s %s", i+1, h.ReplaceSeparator(":"), status, value, sym, date) + transactionLine := fmt.Sprintf("%d%s%s %s %s %s", i+1, h.ReplaceSeparatorFunc(":"), status, value, sym, date) formattedTransactions = append(formattedTransactions, transactionLine) } diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 3c32ee0..c01678d 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -91,15 +91,15 @@ func TestNewHandlers(t *testing.T) { if handlers.userdataStore == nil { t.Fatal("expected userdataStore to be set in handlers") } - if handlers.ReplaceSeparator == nil { - t.Fatal("expected ReplaceSeparator to be set in handlers") + if handlers.ReplaceSeparatorFunc == nil { + t.Fatal("expected ReplaceSeparatorFunc to be set in handlers") } - // Test ReplaceSeparator functionality + // Test ReplaceSeparatorFunc functionality input := "1:Menu item" expectedOutput := "1: Menu item" - if handlers.ReplaceSeparator(input) != expectedOutput { - t.Fatalf("ReplaceSeparator function did not return expected output: got %v, want %v", handlers.ReplaceSeparator(input), expectedOutput) + if handlers.ReplaceSeparatorFunc(input) != expectedOutput { + t.Fatalf("ReplaceSeparatorFunc function did not return expected output: got %v, want %v", handlers.ReplaceSeparatorFunc(input), expectedOutput) } }) @@ -2009,8 +2009,8 @@ func TestGetVoucherList(t *testing.T) { // Initialize Handlers h := &Handlers{ - prefixDb: spdb, - ReplaceSeparator: mockReplaceSeparator, + prefixDb: spdb, + ReplaceSeparatorFunc: mockReplaceSeparator, } mockSyms := []byte("1:SRF\n2:MILO") From f4f4fdd3aceac3c170c71d5ef317afdee7fa7447 Mon Sep 17 00:00:00 2001 From: konstantinmds Date: Tue, 17 Dec 2024 16:32:10 +0100 Subject: [PATCH 20/20] issue-205: added comments for menu handlers methods and changed function name to better fit function workings. --- internal/handlers/handlerservice.go | 2 +- internal/handlers/ussd/menuhandler.go | 125 ++++++++++++++++---------- 2 files changed, 78 insertions(+), 49 deletions(-) diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index 015098e..1da28c3 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -116,7 +116,7 @@ func (ls *LocalHandlerService) GetHandler(accountService remote.AccountServiceIn ls.DbRs.AddLocalFunc("set_voucher", ussdHandlers.SetVoucher) ls.DbRs.AddLocalFunc("get_voucher_details", ussdHandlers.GetVoucherDetails) ls.DbRs.AddLocalFunc("reset_valid_pin", ussdHandlers.ResetValidPin) - ls.DbRs.AddLocalFunc("check_pin_mismatch", ussdHandlers.CheckPinMisMatch) + ls.DbRs.AddLocalFunc("check_pin_mismatch", ussdHandlers.CheckBlockedNumPinMisMatch) ls.DbRs.AddLocalFunc("validate_blocked_number", ussdHandlers.ValidateBlockedNumber) ls.DbRs.AddLocalFunc("retrieve_blocked_number", ussdHandlers.RetrieveBlockedNumber) ls.DbRs.AddLocalFunc("reset_unregistered_number", ussdHandlers.ResetUnregisteredNumber) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 986f8f0..daf4b29 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -39,7 +39,7 @@ const ( pinPattern = `^\d{4}$` ) -// isValidPIN checks whether the given input is a 4 digit number +// checks whether the given input is a 4 digit number func isValidPIN(pin string) bool { match, _ := regexp.MatchString(pinPattern, pin) return match @@ -69,18 +69,19 @@ func (fm *FlagManager) GetFlag(label string) (uint32, error) { } type Handlers struct { - pe *persist.Persister - st *state.State - ca cache.Memory - userdataStore common.DataStore - adminstore *utils.AdminStore - flagManager *asm.FlagParser - accountService remote.AccountServiceInterface - prefixDb storage.PrefixDb - profile *models.Profile + pe *persist.Persister + st *state.State + ca cache.Memory + userdataStore common.DataStore + adminstore *utils.AdminStore + flagManager *asm.FlagParser + accountService remote.AccountServiceInterface + prefixDb storage.PrefixDb + profile *models.Profile ReplaceSeparatorFunc func(string) string } +// NewHandlers creates a new instance of the Handlers struct with the provided dependencies. func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *utils.AdminStore, accountService remote.AccountServiceInterface, replaceSeparatorFunc func(string) string) (*Handlers, error) { if userdataStore == nil { return nil, fmt.Errorf("cannot create handler with nil userdata store") @@ -94,17 +95,18 @@ func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *util prefixDb := storage.NewSubPrefixDb(userdataStore, prefix) h := &Handlers{ - userdataStore: userDb, - flagManager: appFlags, - adminstore: adminstore, - accountService: accountService, - prefixDb: prefixDb, - profile: &models.Profile{Max: 6}, + userdataStore: userDb, + flagManager: appFlags, + adminstore: adminstore, + accountService: accountService, + prefixDb: prefixDb, + profile: &models.Profile{Max: 6}, ReplaceSeparatorFunc: replaceSeparatorFunc, } return h, nil } +// WithPersister sets persister instance to the handlers. func (h *Handlers) WithPersister(pe *persist.Persister) *Handlers { if h.pe != nil { panic("persister already set") @@ -113,6 +115,7 @@ func (h *Handlers) WithPersister(pe *persist.Persister) *Handlers { return h } +// Init initializes the handler for a new session. func (h *Handlers) Init(ctx context.Context, sym string, input []byte) (resource.Result, error) { var r resource.Result if h.pe == nil { @@ -151,7 +154,7 @@ func (h *Handlers) Exit() { h.pe = nil } -// SetLanguage sets the language across the menu +// SetLanguage sets the language across the menu. func (h *Handlers) SetLanguage(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result @@ -175,6 +178,7 @@ func (h *Handlers) SetLanguage(ctx context.Context, sym string, input []byte) (r return res, nil } +// handles the account creation when no existing account is present for the session and stores associated data in the user data store. func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, res *resource.Result) error { flag_account_created, _ := h.flagManager.GetFlag("flag_account_created") r, err := h.accountService.CreateAccount(ctx) @@ -207,9 +211,9 @@ func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, r return nil } -// CreateAccount checks if any account exists on the JSON data file, and if not +// CreateAccount checks if any account exists on the JSON data file, and if not, // creates an account on the API, -// sets the default values and flags +// sets the default values and flags. func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var err error @@ -233,19 +237,22 @@ func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte) return res, nil } -func (h *Handlers) CheckPinMisMatch(ctx context.Context, sym string, input []byte) (resource.Result, error) { +// CheckBlockedNumPinMisMatch checks if the provided PIN matches a temporary PIN stored for a blocked number. +func (h *Handlers) CheckBlockedNumPinMisMatch(ctx context.Context, sym string, input []byte) (resource.Result, error) { res := resource.Result{} flag_pin_mismatch, _ := h.flagManager.GetFlag("flag_pin_mismatch") sessionId, ok := ctx.Value("SessionId").(string) if !ok { return res, fmt.Errorf("missing session") } + // Get blocked number from storage. store := h.userdataStore blockedNumber, err := store.ReadEntry(ctx, sessionId, common.DATA_BLOCKED_NUMBER) if err != nil { logg.ErrorCtxf(ctx, "failed to read blockedNumber entry with", "key", common.DATA_BLOCKED_NUMBER, "error", err) return res, err } + // Get temporary PIN for the blocked number. temporaryPin, err := store.ReadEntry(ctx, string(blockedNumber), common.DATA_TEMPORARY_VALUE) if err != nil { logg.ErrorCtxf(ctx, "failed to read temporaryPin entry with", "key", common.DATA_TEMPORARY_VALUE, "error", err) @@ -259,6 +266,7 @@ func (h *Handlers) CheckPinMisMatch(ctx context.Context, sym string, input []byt return res, nil } +// VerifyNewPin checks if a new PIN meets the required format criteria. func (h *Handlers) VerifyNewPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { res := resource.Result{} _, ok := ctx.Value("SessionId").(string) @@ -267,7 +275,7 @@ func (h *Handlers) VerifyNewPin(ctx context.Context, sym string, input []byte) ( } flag_valid_pin, _ := h.flagManager.GetFlag("flag_valid_pin") pinInput := string(input) - // Validate that the PIN is a 4-digit number + // Validate that the PIN is a 4-digit number. if isValidPIN(pinInput) { res.FlagSet = append(res.FlagSet, flag_valid_pin) } else { @@ -277,9 +285,9 @@ func (h *Handlers) VerifyNewPin(ctx context.Context, sym string, input []byte) ( return res, nil } -// SaveTemporaryPin saves the valid PIN input to the DATA_TEMPORARY_VALUE +// SaveTemporaryPin saves the valid PIN input to the DATA_TEMPORARY_VALUE, // during the account creation process -// and during the change PIN process +// and during the change PIN process. func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var err error @@ -292,7 +300,7 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt flag_incorrect_pin, _ := h.flagManager.GetFlag("flag_incorrect_pin") accountPIN := string(input) - // Validate that the PIN is a 4-digit number + // Validate that the PIN is a 4-digit number. if !isValidPIN(accountPIN) { res.FlagSet = append(res.FlagSet, flag_incorrect_pin) return res, nil @@ -308,6 +316,7 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt return res, nil } +// SaveOthersTemporaryPin allows authorized users to set temporary PINs for blocked numbers. func (h *Handlers) SaveOthersTemporaryPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var err error @@ -318,12 +327,14 @@ func (h *Handlers) SaveOthersTemporaryPin(ctx context.Context, sym string, input return res, fmt.Errorf("missing session") } temporaryPin := string(input) + // First, we retrieve the blocked number associated with this session blockedNumber, err := store.ReadEntry(ctx, sessionId, common.DATA_BLOCKED_NUMBER) if err != nil { logg.ErrorCtxf(ctx, "failed to read blockedNumber entry with", "key", common.DATA_BLOCKED_NUMBER, "error", err) return res, err } + // Then we save the temporary PIN for that blocked number err = store.WriteEntry(ctx, string(blockedNumber), common.DATA_TEMPORARY_VALUE, []byte(temporaryPin)) if err != nil { logg.ErrorCtxf(ctx, "failed to write temporaryPin entry with", "key", common.DATA_TEMPORARY_VALUE, "value", temporaryPin, "error", err) @@ -333,6 +344,7 @@ func (h *Handlers) SaveOthersTemporaryPin(ctx context.Context, sym string, input return res, nil } +// ConfirmPinChange validates user's new PIN. If input matches the temporary PIN, saves it as the new account PIN. func (h *Handlers) ConfirmPinChange(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result sessionId, ok := ctx.Value("SessionId").(string) @@ -352,6 +364,7 @@ func (h *Handlers) ConfirmPinChange(ctx context.Context, sym string, input []byt } else { res.FlagSet = append(res.FlagSet, flag_pin_mismatch) } + // If matched, save the confirmed PIN as the new account PIN err = store.WriteEntry(ctx, sessionId, common.DATA_ACCOUNT_PIN, []byte(temporaryPin)) if err != nil { logg.ErrorCtxf(ctx, "failed to write temporaryPin entry with", "key", common.DATA_ACCOUNT_PIN, "value", temporaryPin, "error", err) @@ -362,7 +375,7 @@ func (h *Handlers) ConfirmPinChange(ctx context.Context, sym string, input []byt // VerifyCreatePin checks whether the confirmation PIN is similar to the temporary PIN // If similar, it sets the USERFLAG_PIN_SET flag and writes the account PIN allowing the user -// to access the main menu +// to access the main menu. func (h *Handlers) VerifyCreatePin(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result @@ -397,7 +410,7 @@ func (h *Handlers) VerifyCreatePin(ctx context.Context, sym string, input []byte return res, nil } -// codeFromCtx retrieves language codes from the context that can be used for handling translations +// retrieves language codes from the context that can be used for handling translations. func codeFromCtx(ctx context.Context) string { var code string if ctx.Value("Language") != nil { @@ -731,7 +744,7 @@ func (h *Handlers) ResetIncorrectPin(ctx context.Context, sym string, input []by return res, nil } -// Setback sets the flag_back_set flag when the navigation is back +// Setback sets the flag_back_set flag when the navigation is back. func (h *Handlers) SetBack(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result //TODO: @@ -744,7 +757,7 @@ func (h *Handlers) SetBack(ctx context.Context, sym string, input []byte) (resou } // CheckAccountStatus queries the API using the TrackingId and sets flags -// based on the account status +// based on the account status. func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result @@ -784,7 +797,7 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b return res, nil } -// Quit displays the Thank you message and exits the menu +// Quit displays the Thank you message and exits the menu. func (h *Handlers) Quit(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result @@ -799,7 +812,7 @@ func (h *Handlers) Quit(ctx context.Context, sym string, input []byte) (resource return res, nil } -// QuitWithHelp displays helpline information then exits the menu +// QuitWithHelp displays helpline information then exits the menu. func (h *Handlers) QuitWithHelp(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result @@ -814,7 +827,7 @@ func (h *Handlers) QuitWithHelp(ctx context.Context, sym string, input []byte) ( return res, nil } -// VerifyYob verifies the length of the given input +// VerifyYob verifies the length of the given input. func (h *Handlers) VerifyYob(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var err error @@ -836,7 +849,7 @@ func (h *Handlers) VerifyYob(ctx context.Context, sym string, input []byte) (res return res, nil } -// ResetIncorrectYob resets the incorrect date format flag after a new attempt +// ResetIncorrectYob resets the incorrect date format flag after a new attempt. func (h *Handlers) ResetIncorrectYob(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result @@ -846,7 +859,7 @@ func (h *Handlers) ResetIncorrectYob(ctx context.Context, sym string, input []by } // CheckBalance retrieves the balance of the active voucher and sets -// the balance as the result content +// the balance as the result content. func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var err error @@ -896,9 +909,12 @@ func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) ( return res, nil } +// FetchCommunityBalance retrieves and displays the balance for community accounts in user's preferred language. func (h *Handlers) FetchCommunityBalance(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result + // retrieve the language code from the context code := codeFromCtx(ctx) + // Initialize the localization system with the appropriate translation directory l := gotext.NewLocale(translationDir, code) l.AddDomain("default") //TODO: @@ -907,6 +923,10 @@ func (h *Handlers) FetchCommunityBalance(ctx context.Context, sym string, input return res, nil } +// ResetOthersPin handles the PIN reset process for other users' accounts by: +// 1. Retrieving the blocked phone number from the session +// 2. Fetching the temporary PIN associated with that number +// 3. Updating the account PIN with the temporary PIN func (h *Handlers) ResetOthersPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result store := h.userdataStore @@ -932,6 +952,8 @@ func (h *Handlers) ResetOthersPin(ctx context.Context, sym string, input []byte) return res, nil } +// ResetUnregisteredNumber clears the unregistered number flag in the system, +// indicating that a number's registration status should no longer be marked as unregistered. func (h *Handlers) ResetUnregisteredNumber(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result flag_unregistered_number, _ := h.flagManager.GetFlag("flag_unregistered_number") @@ -939,6 +961,8 @@ func (h *Handlers) ResetUnregisteredNumber(ctx context.Context, sym string, inpu return res, nil } +// ValidateBlockedNumber performs validation of phone numbers, specifically for blocked numbers in the system. +// It checks phone number format and verifies registration status. func (h *Handlers) ValidateBlockedNumber(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var err error @@ -1067,7 +1091,7 @@ func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []by } // TransactionReset resets the previous transaction data (Recipient and Amount) -// as well as the invalid flags +// as well as the invalid flags. func (h *Handlers) TransactionReset(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var err error @@ -1120,7 +1144,7 @@ func (h *Handlers) InviteValidRecipient(ctx context.Context, sym string, input [ return res, nil } -// ResetTransactionAmount resets the transaction amount and invalid flag +// ResetTransactionAmount resets the transaction amount and invalid flag. func (h *Handlers) ResetTransactionAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var err error @@ -1250,7 +1274,7 @@ func (h *Handlers) RetrieveBlockedNumber(ctx context.Context, sym string, input return res, nil } -// GetSender returns the sessionId (phoneNumber) +// GetSender returns the sessionId (phoneNumber). func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result @@ -1264,7 +1288,7 @@ func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (res return res, nil } -// GetAmount retrieves the amount from teh Gdbm Db +// GetAmount retrieves the amount from teh Gdbm Db. func (h *Handlers) GetAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result @@ -1288,7 +1312,7 @@ func (h *Handlers) GetAmount(ctx context.Context, sym string, input []byte) (res return res, nil } -// InitiateTransaction calls the TokenTransfer and returns a confirmation based on the result +// InitiateTransaction calls the TokenTransfer and returns a confirmation based on the result. func (h *Handlers) InitiateTransaction(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var err error @@ -1338,6 +1362,8 @@ func (h *Handlers) InitiateTransaction(ctx context.Context, sym string, input [] return res, nil } +// GetCurrentProfileInfo retrieves specific profile fields based on the current state of the USSD session. +// Uses flag management system to track profile field status and handle menu navigation. func (h *Handlers) GetCurrentProfileInfo(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var profileInfo []byte @@ -1357,6 +1383,7 @@ func (h *Handlers) GetCurrentProfileInfo(ctx context.Context, sym string, input if !ok { return res, fmt.Errorf("missing session") } + // Extract the field name from the state machine position. sm, _ := h.st.Where() parts := strings.SplitN(sm, "_", 2) filename := parts[1] @@ -1449,6 +1476,7 @@ func (h *Handlers) GetCurrentProfileInfo(ctx context.Context, sym string, input return res, nil } +// GetProfileInfo provides a comprehensive view of a user's profile. func (h *Handlers) GetProfileInfo(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var defaultValue string @@ -1517,7 +1545,7 @@ func (h *Handlers) GetProfileInfo(ctx context.Context, sym string, input []byte) } // SetDefaultVoucher retrieves the current vouchers -// and sets the first as the default voucher, if no active voucher is set +// and sets the first as the default voucher, if no active voucher is set. func (h *Handlers) SetDefaultVoucher(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var err error @@ -1602,7 +1630,7 @@ func (h *Handlers) SetDefaultVoucher(ctx context.Context, sym string, input []by } // CheckVouchers retrieves the token holdings from the API using the "PublicKey" and stores -// them to gdbm +// them to gdbm. func (h *Handlers) CheckVouchers(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result sessionId, ok := ctx.Value("SessionId").(string) @@ -1674,7 +1702,7 @@ func (h *Handlers) CheckVouchers(ctx context.Context, sym string, input []byte) return res, nil } -// GetVoucherList fetches the list of vouchers and formats them +// GetVoucherList fetches the list of vouchers and formats them. func (h *Handlers) GetVoucherList(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result @@ -1693,7 +1721,7 @@ func (h *Handlers) GetVoucherList(ctx context.Context, sym string, input []byte) } // ViewVoucher retrieves the token holding and balance from the subprefixDB -// and displays it to the user for them to select it +// and displays it to the user for them to select it. func (h *Handlers) ViewVoucher(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result sessionId, ok := ctx.Value("SessionId").(string) @@ -1734,7 +1762,7 @@ func (h *Handlers) ViewVoucher(ctx context.Context, sym string, input []byte) (r return res, nil } -// SetVoucher retrieves the temp voucher data and sets it as the active data +// SetVoucher retrieves the temp voucher data and sets it as the active data. func (h *Handlers) SetVoucher(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result @@ -1760,7 +1788,7 @@ func (h *Handlers) SetVoucher(ctx context.Context, sym string, input []byte) (re return res, nil } -// GetVoucherDetails retrieves the voucher details +// GetVoucherDetails retrieves the voucher details. func (h *Handlers) GetVoucherDetails(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result store := h.userdataStore @@ -1792,7 +1820,7 @@ func (h *Handlers) GetVoucherDetails(ctx context.Context, sym string, input []by return res, nil } -// CheckTransactions retrieves the transactions from the API using the "PublicKey" and stores to prefixDb +// CheckTransactions retrieves the transactions from the API using the "PublicKey" and stores to prefixDb. func (h *Handlers) CheckTransactions(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result sessionId, ok := ctx.Value("SessionId").(string) @@ -1850,7 +1878,7 @@ func (h *Handlers) CheckTransactions(ctx context.Context, sym string, input []by return res, nil } -// GetTransactionsList reads the list of transactions from the db and formats them +// GetTransactionsList fetches the list of transactions and formats them. func (h *Handlers) GetTransactionsList(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result sessionId, ok := ctx.Value("SessionId").(string) @@ -1916,7 +1944,7 @@ func (h *Handlers) GetTransactionsList(ctx context.Context, sym string, input [] } // ViewTransactionStatement retrieves the transaction statement -// and displays it to the user +// and displays it to the user. func (h *Handlers) ViewTransactionStatement(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result sessionId, ok := ctx.Value("SessionId").(string) @@ -1964,6 +1992,7 @@ func (h *Handlers) ViewTransactionStatement(ctx context.Context, sym string, inp return res, nil } +// handles bulk updates of profile information. func (h *Handlers) insertProfileItems(ctx context.Context, sessionId string, res *resource.Result) error { var err error store := h.userdataStore @@ -2000,7 +2029,7 @@ func (h *Handlers) insertProfileItems(ctx context.Context, sessionId string, res return nil } -// UpdateAllProfileItems is used to persist all the new profile information and setup the required profile flags +// UpdateAllProfileItems is used to persist all the new profile information and setup the required profile flags. func (h *Handlers) UpdateAllProfileItems(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result sessionId, ok := ctx.Value("SessionId").(string)