From dd764a2e24514b9799e78973c7ccb80c510f1593 Mon Sep 17 00:00:00 2001 From: lash Date: Wed, 30 Oct 2024 01:28:55 +0000 Subject: [PATCH 01/28] Export db datatypes,tools --- {internal/utils => common}/db.go | 2 +- internal/handlers/ussd/menuhandler.go | 108 ++++++++++----------- internal/handlers/ussd/menuhandler_test.go | 97 +++++++++--------- internal/testutil/mocks/userdbmock.go | 6 +- internal/utils/userStore.go | 14 +-- 5 files changed, 114 insertions(+), 113 deletions(-) rename {internal/utils => common}/db.go (97%) diff --git a/internal/utils/db.go b/common/db.go similarity index 97% rename from internal/utils/db.go rename to common/db.go index 2c1e6fa..349d3aa 100644 --- a/internal/utils/db.go +++ b/common/db.go @@ -1,4 +1,4 @@ -package utils +package common import ( "encoding/binary" diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index dae4236..e2bcfaf 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -151,9 +151,9 @@ func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, r trackingId := okResponse.Result["trackingId"].(string) publicKey := okResponse.Result["publicKey"].(string) - data := map[utils.DataTyp]string{ - utils.DATA_TRACKING_ID: trackingId, - utils.DATA_PUBLIC_KEY: publicKey, + data := map[common.DataTyp]string{ + common.DATA_TRACKING_ID: trackingId, + common.DATA_PUBLIC_KEY: publicKey, } store := h.userdataStore for key, value := range data { @@ -166,7 +166,7 @@ func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, r if err != nil { return err } - err = store.WriteEntry(ctx, publicKeyNormalized, utils.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId)) + err = store.WriteEntry(ctx, publicKeyNormalized, common.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId)) if err != nil { return err } @@ -186,7 +186,7 @@ func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte) return res, fmt.Errorf("missing session") } store := h.userdataStore - _, err = store.ReadEntry(ctx, sessionId, utils.DATA_ACCOUNT_CREATED) + _, err = store.ReadEntry(ctx, sessionId, common.DATA_ACCOUNT_CREATED) if err != nil { if db.IsNotFound(err) { logg.Printf(logging.LVL_INFO, "Creating an account because it doesn't exist") @@ -242,7 +242,7 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt res.FlagReset = append(res.FlagReset, flag_incorrect_pin) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN, []byte(accountPIN)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_PIN, []byte(accountPIN)) if err != nil { return res, err } @@ -259,7 +259,7 @@ func (h *Handlers) ConfirmPinChange(ctx context.Context, sym string, input []byt flag_pin_mismatch, _ := h.flagManager.GetFlag("flag_pin_mismatch") store := h.userdataStore - temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN) + temporaryPin, err := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_PIN) if err != nil { return res, err } @@ -268,7 +268,7 @@ func (h *Handlers) ConfirmPinChange(ctx context.Context, sym string, input []byt } else { res.FlagSet = append(res.FlagSet, flag_pin_mismatch) } - err = store.WriteEntry(ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(temporaryPin)) + err = store.WriteEntry(ctx, sessionId, common.DATA_ACCOUNT_PIN, []byte(temporaryPin)) if err != nil { return res, err } @@ -290,7 +290,7 @@ func (h *Handlers) VerifyCreatePin(ctx context.Context, sym string, input []byte return res, fmt.Errorf("missing session") } store := h.userdataStore - temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN) + temporaryPin, err := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_PIN) if err != nil { return res, err } @@ -303,7 +303,7 @@ func (h *Handlers) VerifyCreatePin(ctx context.Context, sym string, input []byte res.FlagSet = []uint32{flag_pin_mismatch} } - err = store.WriteEntry(ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(temporaryPin)) + err = store.WriteEntry(ctx, sessionId, common.DATA_ACCOUNT_PIN, []byte(temporaryPin)) if err != nil { return res, err } @@ -335,7 +335,7 @@ func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte) } firstName := string(input) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(firstName)) + err = store.WriteEntry(ctx, sessionId, common.DATA_FIRST_NAME, []byte(firstName)) if err != nil { return res, err } @@ -358,7 +358,7 @@ func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte) } familyName := string(input) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(familyName)) + err = store.WriteEntry(ctx, sessionId, common.DATA_FAMILY_NAME, []byte(familyName)) if err != nil { return res, err } @@ -380,7 +380,7 @@ func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resou if len(input) == 4 { yob := string(input) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_YOB, []byte(yob)) + err = store.WriteEntry(ctx, sessionId, common.DATA_YOB, []byte(yob)) if err != nil { return res, err } @@ -403,7 +403,7 @@ func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) ( } location := string(input) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(location)) + err = store.WriteEntry(ctx, sessionId, common.DATA_LOCATION, []byte(location)) if err != nil { return res, err } @@ -426,7 +426,7 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re } gender := strings.Split(symbol, "_")[1] store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(gender)) + err = store.WriteEntry(ctx, sessionId, common.DATA_GENDER, []byte(gender)) if err != nil { return res, nil } @@ -445,7 +445,7 @@ func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) if len(input) > 0 { offerings := string(input) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_OFFERINGS, []byte(offerings)) + err = store.WriteEntry(ctx, sessionId, common.DATA_OFFERINGS, []byte(offerings)) if err != nil { return res, nil } @@ -481,7 +481,7 @@ func (h *Handlers) CheckIdentifier(ctx context.Context, sym string, input []byte return res, fmt.Errorf("missing session") } store := h.userdataStore - publicKey, _ := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) + publicKey, _ := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY) res.Content = string(publicKey) @@ -502,7 +502,7 @@ func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (res flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") store := h.userdataStore - AccountPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACCOUNT_PIN) + AccountPin, err := store.ReadEntry(ctx, sessionId, common.DATA_ACCOUNT_PIN) if err != nil { return res, err } @@ -548,7 +548,7 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b return res, fmt.Errorf("missing session") } store := h.userdataStore - publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) + publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY) if err != nil { return res, err } @@ -654,7 +654,7 @@ func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) ( store := h.userdataStore // get the active sym and active balance - activeSym, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM) + activeSym, err := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_SYM) if err != nil { if db.IsNotFound(err) { balance := "0.00" @@ -665,7 +665,7 @@ func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) ( return res, err } - activeBal, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_BAL) + activeBal, err := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_BAL) if err != nil { return res, err } @@ -687,7 +687,7 @@ func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input balanceType := strings.Split(symbol, "_")[0] store := h.userdataStore - publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) + publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY) if err != nil { return res, err } @@ -737,7 +737,7 @@ func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []by return res, nil } store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_RECIPIENT, []byte(recipient)) + err = store.WriteEntry(ctx, sessionId, common.DATA_RECIPIENT, []byte(recipient)) if err != nil { return res, nil } @@ -760,12 +760,12 @@ func (h *Handlers) TransactionReset(ctx context.Context, sym string, input []byt flag_invalid_recipient, _ := h.flagManager.GetFlag("flag_invalid_recipient") flag_invalid_recipient_with_invite, _ := h.flagManager.GetFlag("flag_invalid_recipient_with_invite") store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte("")) + err = store.WriteEntry(ctx, sessionId, common.DATA_AMOUNT, []byte("")) if err != nil { return res, nil } - err = store.WriteEntry(ctx, sessionId, utils.DATA_RECIPIENT, []byte("")) + err = store.WriteEntry(ctx, sessionId, common.DATA_RECIPIENT, []byte("")) if err != nil { return res, nil } @@ -787,7 +787,7 @@ func (h *Handlers) ResetTransactionAmount(ctx context.Context, sym string, input flag_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount") store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte("")) + err = store.WriteEntry(ctx, sessionId, common.DATA_AMOUNT, []byte("")) if err != nil { return res, nil } @@ -809,7 +809,7 @@ func (h *Handlers) MaxAmount(ctx context.Context, sym string, input []byte) (res } store := h.userdataStore - activeBal, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_BAL) + activeBal, err := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_BAL) if err != nil { return res, err } @@ -834,7 +834,7 @@ func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte) var balanceValue float64 // retrieve the active balance - activeBal, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_BAL) + activeBal, err := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_BAL) if err != nil { return res, err } @@ -860,7 +860,7 @@ func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte) // Format the amount with 2 decimal places before saving formattedAmount := fmt.Sprintf("%.2f", inputAmount) - err = store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte(formattedAmount)) + err = store.WriteEntry(ctx, sessionId, common.DATA_AMOUNT, []byte(formattedAmount)) if err != nil { return res, err } @@ -878,7 +878,7 @@ func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) ( return res, fmt.Errorf("missing session") } store := h.userdataStore - recipient, _ := store.ReadEntry(ctx, sessionId, utils.DATA_RECIPIENT) + recipient, _ := store.ReadEntry(ctx, sessionId, common.DATA_RECIPIENT) res.Content = string(recipient) @@ -910,12 +910,12 @@ func (h *Handlers) GetAmount(ctx context.Context, sym string, input []byte) (res store := h.userdataStore // retrieve the active symbol - activeSym, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM) + activeSym, err := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_SYM) if err != nil { return res, err } - amount, _ := store.ReadEntry(ctx, sessionId, utils.DATA_AMOUNT) + amount, _ := store.ReadEntry(ctx, sessionId, common.DATA_AMOUNT) res.Content = fmt.Sprintf("%s %s", string(amount), string(activeSym)) @@ -939,11 +939,11 @@ func (h *Handlers) InitiateTransaction(ctx context.Context, sym string, input [] // Use the amount, recipient and sender to call the API and initialize the transaction store := h.userdataStore - amount, _ := store.ReadEntry(ctx, sessionId, utils.DATA_AMOUNT) + amount, _ := store.ReadEntry(ctx, sessionId, common.DATA_AMOUNT) - recipient, _ := store.ReadEntry(ctx, sessionId, utils.DATA_RECIPIENT) + recipient, _ := store.ReadEntry(ctx, sessionId, common.DATA_RECIPIENT) - activeSym, _ := store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM) + activeSym, _ := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_SYM) res.Content = l.Get("Your request has been sent. %s will receive %s %s from %s.", string(recipient), string(amount), string(activeSym), string(sessionId)) @@ -983,12 +983,12 @@ func (h *Handlers) GetProfileInfo(ctx context.Context, sym string, input []byte) } store := h.userdataStore // Retrieve user data as strings with fallback to defaultValue - firstName := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_FIRST_NAME)) - familyName := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_FAMILY_NAME)) - yob := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_YOB)) - gender := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_GENDER)) - location := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_LOCATION)) - offerings := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_OFFERINGS)) + firstName := getEntryOrDefault(store.ReadEntry(ctx, sessionId, common.DATA_FIRST_NAME)) + familyName := getEntryOrDefault(store.ReadEntry(ctx, sessionId, common.DATA_FAMILY_NAME)) + yob := getEntryOrDefault(store.ReadEntry(ctx, sessionId, common.DATA_YOB)) + gender := getEntryOrDefault(store.ReadEntry(ctx, sessionId, common.DATA_GENDER)) + location := getEntryOrDefault(store.ReadEntry(ctx, sessionId, common.DATA_LOCATION)) + offerings := getEntryOrDefault(store.ReadEntry(ctx, sessionId, common.DATA_OFFERINGS)) // Construct the full name name := defaultValue @@ -1045,11 +1045,11 @@ func (h *Handlers) SetDefaultVoucher(ctx context.Context, sym string, input []by flag_no_active_voucher, _ := h.flagManager.GetFlag("flag_no_active_voucher") // check if the user has an active sym - _, err = store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM) + _, err = store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_SYM) if err != nil { if db.IsNotFound(err) { - publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) + publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY) if err != nil { return res, nil } @@ -1072,12 +1072,12 @@ func (h *Handlers) SetDefaultVoucher(ctx context.Context, sym string, input []by defaultBal := firstVoucher.Balance // set the active symbol - err = store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM, []byte(defaultSym)) + err = store.WriteEntry(ctx, sessionId, common.DATA_ACTIVE_SYM, []byte(defaultSym)) if err != nil { return res, err } // set the active balance - err = store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_BAL, []byte(defaultBal)) + err = store.WriteEntry(ctx, sessionId, common.DATA_ACTIVE_BAL, []byte(defaultBal)) if err != nil { return res, err } @@ -1103,7 +1103,7 @@ func (h *Handlers) CheckVouchers(ctx context.Context, sym string, input []byte) } store := h.userdataStore - publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) + publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY) if err != nil { return res, nil } @@ -1207,11 +1207,11 @@ func (h *Handlers) ViewVoucher(ctx context.Context, sym string, input []byte) (r // If a match is found, write the temporary sym and balance if matchedSymbol != "" && matchedBalance != "" { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_SYM, []byte(matchedSymbol)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_SYM, []byte(matchedSymbol)) if err != nil { return res, err } - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_BAL, []byte(matchedBalance)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_BAL, []byte(matchedBalance)) if err != nil { return res, err } @@ -1269,34 +1269,34 @@ func (h *Handlers) SetVoucher(ctx context.Context, sym string, input []byte) (re } // get the current temporary symbol - temporarySym, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_SYM) + temporarySym, err := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_SYM) if err != nil { return res, err } // get the current temporary balance - temporaryBal, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_BAL) + temporaryBal, err := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_BAL) if err != nil { return res, err } // set the active symbol - err = store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM, []byte(temporarySym)) + err = store.WriteEntry(ctx, sessionId, common.DATA_ACTIVE_SYM, []byte(temporarySym)) if err != nil { return res, err } // set the active balance - err = store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_BAL, []byte(temporaryBal)) + err = store.WriteEntry(ctx, sessionId, common.DATA_ACTIVE_BAL, []byte(temporaryBal)) if err != nil { return res, err } // reset the temporary symbol - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_SYM, []byte("")) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_SYM, []byte("")) if err != nil { return res, err } // reset the temporary balance - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_BAL, []byte("")) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_BAL, []byte("")) if err != nil { return res, err } diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 0b70e80..b83fa61 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -19,7 +19,6 @@ import ( "git.grassecon.net/urdt/ussd/internal/testutil/mocks" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" - "git.grassecon.net/urdt/ussd/internal/utils" "git.grassecon.net/urdt/ussd/common" "github.com/alecthomas/assert/v2" "github.com/grassrootseconomics/eth-custodial/pkg/api" @@ -119,12 +118,12 @@ func TestCreateAccount(t *testing.T) { } publicKey := tt.serverResponse.Result["publicKey"].(string) - data := map[utils.DataTyp]string{ - utils.DATA_TRACKING_ID: tt.serverResponse.Result["trackingId"].(string), - utils.DATA_PUBLIC_KEY: publicKey, + data := map[common.DataTyp]string{ + common.DATA_TRACKING_ID: tt.serverResponse.Result["trackingId"].(string), + common.DATA_PUBLIC_KEY: publicKey, } - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACCOUNT_CREATED).Return([]byte(""), notFoundErr) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_ACCOUNT_CREATED).Return([]byte(""), notFoundErr) mockCreateAccountService.On("CreateAccount").Return(tt.serverResponse, nil) for key, value := range data { @@ -135,7 +134,7 @@ func TestCreateAccount(t *testing.T) { t.Fatal(err) } - mockDataStore.On("WriteEntry", ctx, publicKeyNormalized, utils.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId)).Return(nil) + mockDataStore.On("WriteEntry", ctx, publicKeyNormalized, common.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId)).Return(nil) // Call the method you want to test res, err := h.CreateAccount(ctx, "create_account", []byte("some-input")) @@ -181,7 +180,7 @@ func TestSaveFirstname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_FIRST_NAME, []byte(firstName)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_FIRST_NAME, []byte(firstName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -209,7 +208,7 @@ func TestSaveFamilyname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(familyName)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_FAMILY_NAME, []byte(familyName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -269,7 +268,7 @@ func TestSaveTemporaryPin(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_PIN, []byte(tt.input)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_PIN, []byte(tt.input)).Return(nil) // Call the method res, err := h.SaveTemporaryPin(ctx, "save_pin", tt.input) @@ -295,7 +294,7 @@ func TestSaveYoB(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_YOB, []byte(yob)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_YOB, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -323,7 +322,7 @@ func TestSaveLocation(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_LOCATION, []byte(yob)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_LOCATION, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -351,7 +350,7 @@ func TestSaveOfferings(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_OFFERINGS, []byte(offerings)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_OFFERINGS, []byte(offerings)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -413,10 +412,10 @@ func TestSaveGender(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Set up expectations for the mock database if tt.expectCall { - expectedKey := utils.DATA_GENDER + expectedKey := common.DATA_GENDER mockStore.On("WriteEntry", ctx, sessionId, expectedKey, []byte(tt.expectedGender)).Return(nil) } else { - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_GENDER, []byte(tt.expectedGender)).Return(nil) } mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol) // Create the Handlers instance with the mock store @@ -433,9 +432,9 @@ func TestSaveGender(t *testing.T) { // Verify expectations if tt.expectCall { - mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)) + mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, common.DATA_GENDER, []byte(tt.expectedGender)) } else { - mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)) + mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, common.DATA_GENDER, []byte(tt.expectedGender)) } }) } @@ -469,7 +468,7 @@ func TestCheckIdentifier(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Set up expectations for the mock database - mockStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return(tt.mockPublicKey, tt.mockErr) + mockStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return(tt.mockPublicKey, tt.mockErr) // Create the Handlers instance with the mock store h := &Handlers{ @@ -519,8 +518,8 @@ func TestGetAmount(t *testing.T) { activeSym := "SRF" // Set up the expected behavior of the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM).Return([]byte(activeSym), nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_AMOUNT).Return([]byte(amount), nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_ACTIVE_SYM).Return([]byte(activeSym), nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_AMOUNT).Return([]byte(amount), nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -546,7 +545,7 @@ func TestGetRecipient(t *testing.T) { recepient := "0xcasgatweksalw1018221" // Set up the expected behavior of the mock - mockStore.On("ReadEntry", ctx, sessionId, utils.DATA_RECIPIENT).Return([]byte(recepient), nil) + mockStore.On("ReadEntry", ctx, sessionId, common.DATA_RECIPIENT).Return([]byte(recepient), nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -828,7 +827,7 @@ func TestAuthorize(t *testing.T) { // Define session ID and mock data sessionId := "session123" - typ := utils.DATA_ACCOUNT_PIN + typ := common.DATA_ACCOUNT_PIN h := &Handlers{ userdataStore: mockDataStore, @@ -1011,7 +1010,7 @@ func TestVerifyCreatePin(t *testing.T) { }, } - typ := utils.DATA_TEMPORARY_PIN + typ := common.DATA_TEMPORARY_PIN for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1020,7 +1019,7 @@ func TestVerifyCreatePin(t *testing.T) { mockDataStore.On("ReadEntry", ctx, sessionId, typ).Return([]byte(firstSetPin), nil) // Set up the expected behavior of the mock - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(firstSetPin)).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_PIN, []byte(firstSetPin)).Return(nil) // Call the method under test res, err := h.VerifyCreatePin(ctx, "verify_create_pin", []byte(tt.input)) @@ -1141,11 +1140,11 @@ func TestCheckAccountStatus(t *testing.T) { status := tt.response.Result.Transaction.Status // Define expected interactions with the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return(tt.input, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return(tt.input, nil) mockCreateAccountService.On("CheckAccountStatus", string(tt.input)).Return(tt.response, nil) mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_STATUS, []byte(status)).Return(nil).Maybe() + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_STATUS, []byte(status)).Return(nil).Maybe() // Call the method under test res, _ := h.CheckAccountStatus(ctx, "check_account_status", tt.input) @@ -1201,8 +1200,8 @@ func TestTransactionReset(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, []byte("")).Return(nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_RECIPIENT, []byte("")).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_AMOUNT, []byte("")).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_RECIPIENT, []byte("")).Return(nil) // Call the method under test res, _ := h.TransactionReset(ctx, "transaction_reset", tt.input) @@ -1257,7 +1256,7 @@ func TestResetInvalidAmount(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, []byte("")).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_AMOUNT, []byte("")).Return(nil) // Call the method under test res, _ := h.ResetTransactionAmount(ctx, "transaction_reset_amount", tt.input) @@ -1320,9 +1319,9 @@ func TestInitiateTransaction(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Define expected interactions with the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_AMOUNT).Return(tt.Amount, nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_RECIPIENT).Return(tt.Recipient, nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM).Return(tt.ActiveSym, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_AMOUNT).Return(tt.Amount, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_RECIPIENT).Return(tt.Recipient, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_ACTIVE_SYM).Return(tt.ActiveSym, nil) // Call the method under test res, _ := h.InitiateTransaction(ctx, "transaction_reset_amount", tt.input) @@ -1502,10 +1501,10 @@ func TestValidateAmount(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Mock behavior for active balance retrieval - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_BAL).Return(tt.activeBal, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_ACTIVE_BAL).Return(tt.activeBal, nil) // Mock behavior for storing the amount (if valid) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, tt.input).Return(nil).Maybe() + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_AMOUNT, tt.input).Return(nil).Maybe() // Call the method under test res, _ := h.ValidateAmount(ctx, "test_validate_amount", tt.input) @@ -1559,7 +1558,7 @@ func TestValidateRecipient(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_RECIPIENT, tt.input).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_RECIPIENT, tt.input).Return(nil) // Create the Handlers instance with the mock flag manager h := &Handlers{ @@ -1613,8 +1612,8 @@ func TestCheckBalance(t *testing.T) { } // Mock for user with active sym - mockDataStore.On("ReadEntry", ctx, tt.sessionId, utils.DATA_ACTIVE_SYM).Return([]byte(tt.activeSym), nil) - mockDataStore.On("ReadEntry", ctx, tt.sessionId, utils.DATA_ACTIVE_BAL).Return([]byte(tt.activeBal), nil) + mockDataStore.On("ReadEntry", ctx, tt.sessionId, common.DATA_ACTIVE_SYM).Return([]byte(tt.activeSym), nil) + mockDataStore.On("ReadEntry", ctx, tt.sessionId, common.DATA_ACTIVE_BAL).Return([]byte(tt.activeBal), nil) res, err := h.CheckBalance(ctx, "check_balance", []byte("")) @@ -1648,13 +1647,13 @@ func TestGetProfile(t *testing.T) { tests := []struct { name string languageCode string - keys []utils.DataTyp + keys []common.DataTyp profileInfo []string result resource.Result }{ { name: "Test with full profile information in eng", - keys: []utils.DataTyp{utils.DATA_FAMILY_NAME, utils.DATA_FIRST_NAME, utils.DATA_GENDER, utils.DATA_OFFERINGS, utils.DATA_LOCATION, utils.DATA_YOB}, + keys: []common.DataTyp{common.DATA_FAMILY_NAME, common.DATA_FIRST_NAME, common.DATA_GENDER, common.DATA_OFFERINGS, common.DATA_LOCATION, common.DATA_YOB}, profileInfo: []string{"Doee", "John", "Male", "Bananas", "Kilifi", "1976"}, languageCode: "eng", result: resource.Result{ @@ -1666,7 +1665,7 @@ func TestGetProfile(t *testing.T) { }, { name: "Test with with profile information in swa ", - keys: []utils.DataTyp{utils.DATA_FAMILY_NAME, utils.DATA_FIRST_NAME, utils.DATA_GENDER, utils.DATA_OFFERINGS, utils.DATA_LOCATION, utils.DATA_YOB}, + keys: []common.DataTyp{common.DATA_FAMILY_NAME, common.DATA_FIRST_NAME, common.DATA_GENDER, common.DATA_OFFERINGS, common.DATA_LOCATION, common.DATA_YOB}, profileInfo: []string{"Doee", "John", "Male", "Bananas", "Kilifi", "1976"}, languageCode: "swa", result: resource.Result{ @@ -1678,7 +1677,7 @@ func TestGetProfile(t *testing.T) { }, { name: "Test with with profile information with language that is not yet supported", - keys: []utils.DataTyp{utils.DATA_FAMILY_NAME, utils.DATA_FIRST_NAME, utils.DATA_GENDER, utils.DATA_OFFERINGS, utils.DATA_LOCATION, utils.DATA_YOB}, + keys: []common.DataTyp{common.DATA_FAMILY_NAME, common.DATA_FIRST_NAME, common.DATA_GENDER, common.DATA_OFFERINGS, common.DATA_LOCATION, common.DATA_YOB}, profileInfo: []string{"Doee", "John", "Male", "Bananas", "Kilifi", "1976"}, languageCode: "nor", result: resource.Result{ @@ -1802,9 +1801,9 @@ func TestConfirmPin(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Set up the expected behavior of the mock - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(tt.temporarypin)).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_PIN, []byte(tt.temporarypin)).Return(nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_PIN).Return(tt.temporarypin, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_TEMPORARY_PIN).Return(tt.temporarypin, nil) //Call the function under test res, _ := h.ConfirmPinChange(ctx, "confirm_pin_change", tt.temporarypin) @@ -1829,12 +1828,12 @@ func TestSetVoucher(t *testing.T) { temporaryBal := []byte("tempBal") // Set expectations for the mock data store - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_SYM).Return(temporarySym, nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_BAL).Return(temporaryBal, nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM, temporarySym).Return(nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACTIVE_BAL, temporaryBal).Return(nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_SYM, []byte("")).Return(nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_BAL, []byte("")).Return(nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_TEMPORARY_SYM).Return(temporarySym, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_TEMPORARY_BAL).Return(temporaryBal, nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACTIVE_SYM, temporarySym).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACTIVE_BAL, temporaryBal).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_SYM, []byte("")).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_BAL, []byte("")).Return(nil) h := &Handlers{ userdataStore: mockDataStore, @@ -1919,7 +1918,7 @@ func TestFetchCustodialBalances(t *testing.T) { } // Set up the expected behavior of the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) mockCreateAccountService.On("CheckBalance", string(publicKey)).Return(tt.balanceResonse, nil) // Call the method diff --git a/internal/testutil/mocks/userdbmock.go b/internal/testutil/mocks/userdbmock.go index ff3f18d..7892179 100644 --- a/internal/testutil/mocks/userdbmock.go +++ b/internal/testutil/mocks/userdbmock.go @@ -4,7 +4,7 @@ import ( "context" "git.defalsify.org/vise.git/db" - "git.grassecon.net/urdt/ussd/internal/utils" + "git.grassecon.net/urdt/ussd/common" "github.com/stretchr/testify/mock" ) @@ -13,12 +13,12 @@ type MockUserDataStore struct { mock.Mock } -func (m *MockUserDataStore) ReadEntry(ctx context.Context, sessionId string, typ utils.DataTyp) ([]byte, error) { +func (m *MockUserDataStore) ReadEntry(ctx context.Context, sessionId string, typ common.DataTyp) ([]byte, error) { args := m.Called(ctx, sessionId, typ) return args.Get(0).([]byte), args.Error(1) } -func (m *MockUserDataStore) WriteEntry(ctx context.Context, sessionId string, typ utils.DataTyp, value []byte) error { +func (m *MockUserDataStore) WriteEntry(ctx context.Context, sessionId string, typ common.DataTyp, value []byte) error { args := m.Called(ctx, sessionId, typ, value) return args.Error(0) } diff --git a/internal/utils/userStore.go b/internal/utils/userStore.go index a1485b1..13682b7 100644 --- a/internal/utils/userStore.go +++ b/internal/utils/userStore.go @@ -3,13 +3,15 @@ package utils import ( "context" + "git.grassecon.net/urdt/ussd/common" + "git.defalsify.org/vise.git/db" ) type DataStore interface { db.Db - ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) - WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error + ReadEntry(ctx context.Context, sessionId string, typ common.DataTyp) ([]byte, error) + WriteEntry(ctx context.Context, sessionId string, typ common.DataTyp, value []byte) error } type UserDataStore struct { @@ -17,16 +19,16 @@ type UserDataStore struct { } // ReadEntry retrieves an entry from the store based on the provided parameters. -func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) { +func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ common.DataTyp) ([]byte, error) { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) - k := PackKey(typ, []byte(sessionId)) + k := common.PackKey(typ, []byte(sessionId)) return store.Get(ctx, k) } -func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error { +func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ common.DataTyp, value []byte) error { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) - k := PackKey(typ, []byte(sessionId)) + k := common.PackKey(typ, []byte(sessionId)) return store.Put(ctx, k, value) } From c95b97cb148114aed46a8aa84da8ec9faf2dcaee Mon Sep 17 00:00:00 2001 From: lash Date: Wed, 30 Oct 2024 01:45:38 +0000 Subject: [PATCH 02/28] Export user data store --- .../utils/userStore.go => common/user_store.go | 16 +++++++--------- internal/handlers/ussd/menuhandler.go | 4 ++-- 2 files changed, 9 insertions(+), 11 deletions(-) rename internal/utils/userStore.go => common/user_store.go (55%) diff --git a/internal/utils/userStore.go b/common/user_store.go similarity index 55% rename from internal/utils/userStore.go rename to common/user_store.go index 13682b7..8d982ab 100644 --- a/internal/utils/userStore.go +++ b/common/user_store.go @@ -1,17 +1,15 @@ -package utils +package common import ( "context" - "git.grassecon.net/urdt/ussd/common" - "git.defalsify.org/vise.git/db" ) type DataStore interface { db.Db - ReadEntry(ctx context.Context, sessionId string, typ common.DataTyp) ([]byte, error) - WriteEntry(ctx context.Context, sessionId string, typ common.DataTyp, value []byte) error + ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) + WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error } type UserDataStore struct { @@ -19,16 +17,16 @@ type UserDataStore struct { } // ReadEntry retrieves an entry from the store based on the provided parameters. -func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ common.DataTyp) ([]byte, error) { +func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) - k := common.PackKey(typ, []byte(sessionId)) + k := PackKey(typ, []byte(sessionId)) return store.Get(ctx, k) } -func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ common.DataTyp, value []byte) error { +func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) - k := common.PackKey(typ, []byte(sessionId)) + k := PackKey(typ, []byte(sessionId)) return store.Put(ctx, k, value) } diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index e2bcfaf..303bea9 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -63,7 +63,7 @@ type Handlers struct { pe *persist.Persister st *state.State ca cache.Memory - userdataStore utils.DataStore + userdataStore common.DataStore flagManager *asm.FlagParser accountService server.AccountServiceInterface } @@ -72,7 +72,7 @@ func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, accountService s if userdataStore == nil { return nil, fmt.Errorf("cannot create handler with nil userdata store") } - userDb := &utils.UserDataStore{ + userDb := &common.UserDataStore{ Db: userdataStore, } h := &Handlers{ From 14648fec6cfcc348bf5e38ff6e0eb17a53cc015e Mon Sep 17 00:00:00 2001 From: lash Date: Wed, 30 Oct 2024 12:02:16 +0000 Subject: [PATCH 03/28] Edit comment --- common/user_store.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/user_store.go b/common/user_store.go index 8d982ab..4b8409f 100644 --- a/common/user_store.go +++ b/common/user_store.go @@ -16,7 +16,7 @@ type UserDataStore struct { db.Db } -// ReadEntry retrieves an entry from the store based on the provided parameters. +// ReadEntry retrieves an entry to the userdata store. func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) @@ -24,6 +24,7 @@ func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ return store.Get(ctx, k) } +// WriteEntry adds an entry to the userdata store. func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) From ff26ccc545d1b09456a1875d8e59ef290a15f349 Mon Sep 17 00:00:00 2001 From: lash Date: Wed, 30 Oct 2024 13:09:15 +0000 Subject: [PATCH 04/28] Expose api interface --- cmd/africastalking/main.go | 4 ++-- cmd/async/main.go | 4 ++-- cmd/http/main.go | 4 ++-- cmd/main.go | 4 ++-- internal/handlers/handlerservice.go | 5 +++-- internal/handlers/ussd/menuhandler.go | 6 +++--- internal/testutil/TestEngine.go | 6 +++--- internal/testutil/testtag/offlinetest.go | 4 ++-- {internal/handlers/server => remote}/accountservice.go | 2 +- 9 files changed, 20 insertions(+), 19 deletions(-) rename {internal/handlers/server => remote}/accountservice.go (99%) diff --git a/cmd/africastalking/main.go b/cmd/africastalking/main.go index 79fb091..7c98f38 100644 --- a/cmd/africastalking/main.go +++ b/cmd/africastalking/main.go @@ -19,9 +19,9 @@ import ( "git.grassecon.net/urdt/ussd/config" "git.grassecon.net/urdt/ussd/initializers" "git.grassecon.net/urdt/ussd/internal/handlers" - "git.grassecon.net/urdt/ussd/internal/handlers/server" httpserver "git.grassecon.net/urdt/ussd/internal/http" "git.grassecon.net/urdt/ussd/internal/storage" + "git.grassecon.net/urdt/ussd/remote" ) var ( @@ -139,7 +139,7 @@ func main() { os.Exit(1) } - accountService := server.AccountService{} + accountService := remote.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) diff --git a/cmd/async/main.go b/cmd/async/main.go index 902dfc7..b879c68 100644 --- a/cmd/async/main.go +++ b/cmd/async/main.go @@ -16,8 +16,8 @@ import ( "git.grassecon.net/urdt/ussd/config" "git.grassecon.net/urdt/ussd/initializers" "git.grassecon.net/urdt/ussd/internal/handlers" - "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/storage" + "git.grassecon.net/urdt/ussd/remote" ) var ( @@ -106,7 +106,7 @@ func main() { lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) lhs.SetDataStore(&userdataStore) - accountService := server.AccountService{} + accountService := remote.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { diff --git a/cmd/http/main.go b/cmd/http/main.go index ece882e..638ca87 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -18,9 +18,9 @@ import ( "git.grassecon.net/urdt/ussd/config" "git.grassecon.net/urdt/ussd/initializers" "git.grassecon.net/urdt/ussd/internal/handlers" - "git.grassecon.net/urdt/ussd/internal/handlers/server" httpserver "git.grassecon.net/urdt/ussd/internal/http" "git.grassecon.net/urdt/ussd/internal/storage" + "git.grassecon.net/urdt/ussd/remote" ) var ( @@ -99,7 +99,7 @@ func main() { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - accountService := server.AccountService{} + accountService := remote.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) diff --git a/cmd/main.go b/cmd/main.go index 21ca0c3..13ceb3c 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -13,8 +13,8 @@ import ( "git.grassecon.net/urdt/ussd/config" "git.grassecon.net/urdt/ussd/initializers" "git.grassecon.net/urdt/ussd/internal/handlers" - "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/storage" + "git.grassecon.net/urdt/ussd/remote" ) var ( @@ -97,7 +97,7 @@ func main() { os.Exit(1) } - accountService := server.AccountService{} + accountService := remote.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index 311e694..b409fa6 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -6,8 +6,9 @@ import ( "git.defalsify.org/vise.git/engine" "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" - "git.grassecon.net/urdt/ussd/internal/handlers/server" + "git.grassecon.net/urdt/ussd/internal/handlers/ussd" + "git.grassecon.net/urdt/ussd/remote" ) type HandlerService interface { @@ -53,7 +54,7 @@ func (ls *LocalHandlerService) SetDataStore(db *db.Db) { ls.UserdataStore = db } -func (ls *LocalHandlerService) GetHandler(accountService server.AccountServiceInterface) (*ussd.Handlers, error) { +func (ls *LocalHandlerService) GetHandler(accountService remote.AccountServiceInterface) (*ussd.Handlers, error) { ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore,accountService) if err != nil { return nil, err diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 303bea9..aa5c1aa 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -19,9 +19,9 @@ import ( "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" - "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/utils" "git.grassecon.net/urdt/ussd/common" + "git.grassecon.net/urdt/ussd/remote" "gopkg.in/leonelquinteros/gotext.v1" "git.grassecon.net/urdt/ussd/internal/storage" @@ -65,10 +65,10 @@ type Handlers struct { ca cache.Memory userdataStore common.DataStore flagManager *asm.FlagParser - accountService server.AccountServiceInterface + accountService remote.AccountServiceInterface } -func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, accountService server.AccountServiceInterface) (*Handlers, error) { +func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, accountService remote.AccountServiceInterface) (*Handlers, error) { if userdataStore == nil { return nil, fmt.Errorf("cannot create handler with nil userdata store") } diff --git a/internal/testutil/TestEngine.go b/internal/testutil/TestEngine.go index bd6bc7f..fa585ae 100644 --- a/internal/testutil/TestEngine.go +++ b/internal/testutil/TestEngine.go @@ -11,11 +11,11 @@ import ( "git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/resource" "git.grassecon.net/urdt/ussd/internal/handlers" - "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/storage" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" "git.grassecon.net/urdt/ussd/internal/testutil/testtag" testdataloader "github.com/peteole/testdata-loader" + "git.grassecon.net/urdt/ussd/remote" ) var ( @@ -83,7 +83,7 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool) { } if testtag.AccountService == nil { - testtag.AccountService = &server.AccountService{} + testtag.AccountService = &remote.AccountService{} } switch testtag.AccountService.(type) { @@ -91,7 +91,7 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool) { go func() { eventChannel <- false }() - case *server.AccountService: + case *remote.AccountService: go func() { time.Sleep(5 * time.Second) // Wait for 5 seconds eventChannel <- true diff --git a/internal/testutil/testtag/offlinetest.go b/internal/testutil/testtag/offlinetest.go index 70e2e80..831bf09 100644 --- a/internal/testutil/testtag/offlinetest.go +++ b/internal/testutil/testtag/offlinetest.go @@ -3,10 +3,10 @@ package testtag import ( - "git.grassecon.net/urdt/ussd/internal/handlers/server" + "git.grassecon.net/urdt/ussd/remote" accountservice "git.grassecon.net/urdt/ussd/internal/testutil/testservice" ) var ( - AccountService server.AccountServiceInterface = &accountservice.TestAccountService{} + AccountService remote.AccountServiceInterface = &accountservice.TestAccountService{} ) diff --git a/internal/handlers/server/accountservice.go b/remote/accountservice.go similarity index 99% rename from internal/handlers/server/accountservice.go rename to remote/accountservice.go index 890d1db..236ccf4 100644 --- a/internal/handlers/server/accountservice.go +++ b/remote/accountservice.go @@ -1,4 +1,4 @@ -package server +package remote import ( "context" From 1e638238ed368319fb84ed9deb8d90d0df55b28d Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 01:28:37 +0000 Subject: [PATCH 05/28] WIP refactor models usage --- config/config.go | 67 ++++++-- internal/handlers/ussd/menuhandler.go | 20 +-- internal/handlers/ussd/menuhandler_test.go | 1 - internal/models/accountresponse.go | 10 +- internal/models/balanceresponse.go | 17 +- internal/models/trackstatusresponse.go | 23 ++- internal/models/vouchersresponse.go | 13 -- internal/testutil/mocks/servicemock.go | 27 ++-- .../testservice/TestAccountService.go | 78 +++------ remote/accountservice.go | 149 ++++++++++++------ 10 files changed, 229 insertions(+), 176 deletions(-) diff --git a/config/config.go b/config/config.go index 43466c3..a5c89a7 100644 --- a/config/config.go +++ b/config/config.go @@ -1,18 +1,67 @@ package config -import "git.grassecon.net/urdt/ussd/initializers" +import ( + "net/url" + + "git.grassecon.net/urdt/ussd/initializers" +) + +const ( + createAccountPath = "/api/v2/account/create" + trackStatusPath = "/api/track" + balancePathPrefix = "/api/account" + trackPath = "/api/v2/account/status" + voucherHoldingsPathPrefix = "/api/v1/holdings" + voucherTransfersPathPrefix = "/api/v1/transfers/last10" +) + +var ( + custodialURLBase string + dataURLBase string + CustodialAPIKey string + DataAPIKey string +) var ( CreateAccountURL string TrackStatusURL string - BalanceURL string - TrackURL string + BalanceURL string + TrackURL string + VoucherHoldingsURL string + VoucherTransfersURL string ) -// LoadConfig initializes the configuration values after environment variables are loaded. -func LoadConfig() { - CreateAccountURL = initializers.GetEnv("CREATE_ACCOUNT_URL", "http://localhost:5003/api/v2/account/create") - TrackStatusURL = initializers.GetEnv("TRACK_STATUS_URL", "https://custodial.sarafu.africa/api/track/") - BalanceURL = initializers.GetEnv("BALANCE_URL", "https://custodial.sarafu.africa/api/account/status/") - TrackURL = initializers.GetEnv("TRACK_URL", "http://localhost:5003/api/v2/account/status") +func setBase() error { + var err error + + custodialURLBase = initializers.GetEnv("CUSTODIAL_URL_BASE", "http://localhost:5003") + dataURLBase = initializers.GetEnv("DATA_URL_BASE", "http://localhost:5006") + CustodialAPIKey = initializers.GetEnv("CUSTODIAL_API_KEY", "xd") + DataAPIKey = initializers.GetEnv("DATA_API_KEY", "xd") + + _, err = url.JoinPath(custodialURLBase, "/foo") + if err != nil { + return err + } + _, err = url.JoinPath(dataURLBase, "/bar") + if err != nil { + return err + } + return nil +} + +// LoadConfig initializes the configuration values after environment variables are loaded. +func LoadConfig() error { + err := setBase() + if err != nil { + return err + } + CreateAccountURL, _ = url.JoinPath(custodialURLBase, createAccountPath) + TrackStatusURL, _ = url.JoinPath(custodialURLBase, trackStatusPath) + BalanceURL, _ = url.JoinPath(custodialURLBase, balancePathPrefix) + TrackURL, _ = url.JoinPath(custodialURLBase, trackPath) + VoucherHoldingsURL, _ = url.JoinPath(dataURLBase, voucherHoldingsPathPrefix) + VoucherTransfersURL, _ = url.JoinPath(dataURLBase, voucherTransfersPathPrefix) + + return nil } diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index f568e6a..5f6f81a 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -149,12 +149,12 @@ func (h *Handlers) SetLanguage(ctx context.Context, sym string, input []byte) (r func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, res *resource.Result) error { flag_account_created, _ := h.flagManager.GetFlag("flag_account_created") - okResponse, err := h.accountService.CreateAccount(ctx) + r, err := h.accountService.CreateAccount(ctx) if err != nil { return err } - trackingId := okResponse.Result["trackingId"].(string) - publicKey := okResponse.Result["publicKey"].(string) + trackingId := r.TrackingId + publicKey := r.PublicKey data := map[common.DataTyp]string{ common.DATA_TRACKING_ID: trackingId, @@ -682,6 +682,7 @@ func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) ( func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result + flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") sessionId, ok := ctx.Value("SessionId").(string) @@ -699,14 +700,13 @@ func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input balanceResponse, err := h.accountService.CheckBalance(ctx, string(publicKey)) if err != nil { - return res, nil - } - if !balanceResponse.Ok { res.FlagSet = append(res.FlagSet, flag_api_error) return res, nil } res.FlagReset = append(res.FlagReset, flag_api_error) - balance := balanceResponse.Result.Balance + + //balance := balanceResponse.Result.Balance + balance := balanceResponse.Balance switch balanceType { case "my": @@ -1066,13 +1066,13 @@ func (h *Handlers) SetDefaultVoucher(ctx context.Context, sym string, input []by } // Return if there is no voucher - if len(vouchersResp.Result.Holdings) == 0 { + if len(vouchersResp) == 0 { res.FlagSet = append(res.FlagSet, flag_no_active_voucher) return res, nil } // Use only the first voucher - firstVoucher := vouchersResp.Result.Holdings[0] + firstVoucher := vouchersResp[0] defaultSym := firstVoucher.TokenSymbol defaultBal := firstVoucher.Balance @@ -1119,7 +1119,7 @@ func (h *Handlers) CheckVouchers(ctx context.Context, sym string, input []byte) return res, nil } - data := utils.ProcessVouchers(vouchersResp.Result.Holdings) + data := utils.ProcessVouchers(vouchersResp) // Store all voucher data dataMap := map[string]string{ diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index bae95a8..5f3c953 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -1159,7 +1159,6 @@ func TestCheckAccountStatus(t *testing.T) { // Assert that expectations were met mockDataStore.AssertExpectations(t) - }) } diff --git a/internal/models/accountresponse.go b/internal/models/accountresponse.go index efcc30b..278e0e9 100644 --- a/internal/models/accountresponse.go +++ b/internal/models/accountresponse.go @@ -1,10 +1,6 @@ package models -type AccountResponse struct { - Ok bool `json:"ok"` - Description string `json:"description"` // Include the description field - Result struct { - PublicKey string `json:"publicKey"` - TrackingId string `json:"trackingId"` - } `json:"result"` +type AccountResult struct { + PublicKey string `json:"publicKey"` + TrackingId string `json:"trackingId"` } diff --git a/internal/models/balanceresponse.go b/internal/models/balanceresponse.go index 57c8e5a..3d57c95 100644 --- a/internal/models/balanceresponse.go +++ b/internal/models/balanceresponse.go @@ -3,10 +3,15 @@ package models import "encoding/json" -type BalanceResponse struct { - Ok bool `json:"ok"` - Result struct { - Balance string `json:"balance"` - Nonce json.Number `json:"nonce"` - } `json:"result"` +//type BalanceResponse struct { +// Ok bool `json:"ok"` +// Result struct { +// Balance string `json:"balance"` +// Nonce json.Number `json:"nonce"` +// } `json:"result"` +//} +// +type BalanceResult struct { + Balance string `json:"balance"` + Nonce json.Number `json:"nonce"` } diff --git a/internal/models/trackstatusresponse.go b/internal/models/trackstatusresponse.go index 6b96d90..6130c6e 100644 --- a/internal/models/trackstatusresponse.go +++ b/internal/models/trackstatusresponse.go @@ -4,23 +4,18 @@ import ( "encoding/json" "time" ) -type Transaction struct { +//type Transaction struct { +// CreatedAt time.Time `json:"createdAt"` +// Status string `json:"status"` +// TransferValue json.Number `json:"transferValue"` +// TxHash string `json:"txHash"` +// TxType string `json:"txType"` +//} + +type TrackStatusResult struct { CreatedAt time.Time `json:"createdAt"` Status string `json:"status"` TransferValue json.Number `json:"transferValue"` TxHash string `json:"txHash"` TxType string `json:"txType"` } - -type TrackStatusResponse struct { - Ok bool `json:"ok"` - Result struct { - Transaction struct { - CreatedAt time.Time `json:"createdAt"` - Status string `json:"status"` - TransferValue json.Number `json:"transferValue"` - TxHash string `json:"txHash"` - TxType string `json:"txType"` - } - } `json:"result"` -} diff --git a/internal/models/vouchersresponse.go b/internal/models/vouchersresponse.go index 09b085d..2640e7f 100644 --- a/internal/models/vouchersresponse.go +++ b/internal/models/vouchersresponse.go @@ -1,14 +1 @@ package models - -import dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" - -type VoucherHoldingResponse struct { - Ok bool `json:"ok"` - Description string `json:"description"` - Result VoucherResult `json:"result"` -} - -// VoucherResult holds the list of token holdings -type VoucherResult struct { - Holdings []dataserviceapi.TokenHoldings `json:"holdings"` -} diff --git a/internal/testutil/mocks/servicemock.go b/internal/testutil/mocks/servicemock.go index de0e99a..3b36ba7 100644 --- a/internal/testutil/mocks/servicemock.go +++ b/internal/testutil/mocks/servicemock.go @@ -5,6 +5,7 @@ import ( "git.grassecon.net/urdt/ussd/internal/models" "github.com/grassrootseconomics/eth-custodial/pkg/api" + dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" "github.com/stretchr/testify/mock" ) @@ -13,28 +14,28 @@ type MockAccountService struct { mock.Mock } -func (m *MockAccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) { +func (m *MockAccountService) CreateAccount(ctx context.Context) (*models.AccountResult, error) { args := m.Called() - return args.Get(0).(*api.OKResponse), args.Error(1) + return args.Get(0).(*models.AccountResult), args.Error(1) } -func (m *MockAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) { +func (m *MockAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) { args := m.Called(publicKey) - return args.Get(0).(*models.BalanceResponse), args.Error(1) + return args.Get(0).(*models.BalanceResult), args.Error(1) } -func (m *MockAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) { +func (m *MockAccountService) TrackAccountStatus(ctx context.Context, trackingId string) (*api.OKResponse, error) { args := m.Called(trackingId) - return args.Get(0).(*models.TrackStatusResponse), args.Error(1) -} - -func (m *MockAccountService) TrackAccountStatus(ctx context.Context,publicKey string) (*api.OKResponse, error) { - args := m.Called(publicKey) return args.Get(0).(*api.OKResponse), args.Error(1) } - -func (m *MockAccountService) FetchVouchers(ctx context.Context, publicKey string) (*models.VoucherHoldingResponse, error) { +func (m *MockAccountService) CheckAccountStatus(ctx context.Context,publicKey string) (*models.TrackStatusResult, error) { args := m.Called(publicKey) - return args.Get(0).(*models.VoucherHoldingResponse), args.Error(1) + return args.Get(0).(*models.TrackStatusResult), args.Error(1) +} + + +func (m *MockAccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + args := m.Called(publicKey) + return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) } diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go index 745b80d..885e63f 100644 --- a/internal/testutil/testservice/TestAccountService.go +++ b/internal/testutil/testservice/TestAccountService.go @@ -13,54 +13,29 @@ import ( type TestAccountService struct { } -func (tas *TestAccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) { - return &api.OKResponse{ - Ok: true, - Description: "Account creation succeeded", - Result: map[string]any{ - "trackingId": "075ccc86-f6ef-4d33-97d5-e91cfb37aa0d", - "publicKey": "0x623EFAFa8868df4B934dd12a8B26CB3Dd75A7AdD", - }, +func (tas *TestAccountService) CreateAccount(ctx context.Context) (*models.AccountResult, error) { + return &models.AccountResult { + TrackingId: "075ccc86-f6ef-4d33-97d5-e91cfb37aa0d", + PublicKey: "0x623EFAFa8868df4B934dd12a8B26CB3Dd75A7AdD", }, nil } -func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) { - balanceResponse := &models.BalanceResponse{ - Ok: true, - Result: struct { - Balance string `json:"balance"` - Nonce json.Number `json:"nonce"` - }{ - Balance: "0.003 CELO", - Nonce: json.Number("0"), - }, +func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) { + balanceResponse := &models.BalanceResult { + Balance: "0.003 CELO", + Nonce: json.Number("0"), } - return balanceResponse, nil } -func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) { - trackResponse := &models.TrackStatusResponse{ - Ok: true, - Result: struct { - Transaction struct { - CreatedAt time.Time "json:\"createdAt\"" - Status string "json:\"status\"" - TransferValue json.Number "json:\"transferValue\"" - TxHash string "json:\"txHash\"" - TxType string "json:\"txType\"" - } - }{ - Transaction: models.Transaction{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", - }, - }, - } - return trackResponse, nil +func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { + return &models.TrackStatusResult { + CreatedAt: time.Now(), + Status: "SUCCESS", + TransferValue: json.Number("0.5"), + TxHash: "0x123abc456def", + TxType: "transfer", + }, nil } func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) { @@ -73,18 +48,13 @@ func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey }, nil } -func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey string) (*models.VoucherHoldingResponse, error) { - return &models.VoucherHoldingResponse{ - Ok: true, - Result: models.VoucherResult{ - Holdings: []dataserviceapi.TokenHoldings{ - { - ContractAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee", - TokenSymbol: "SRF", - TokenDecimals: "6", - Balance: "2745987", - }, - }, +func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + return []dataserviceapi.TokenHoldings { + dataserviceapi.TokenHoldings { + ContractAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee", + TokenSymbol: "SRF", + TokenDecimals: "6", + Balance: "2745987", }, - }, nil + }, nil } diff --git a/remote/accountservice.go b/remote/accountservice.go index 236ccf4..c11910f 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -4,27 +4,29 @@ import ( "context" "encoding/json" "errors" - "fmt" "io" "net/http" - "os" + "net/url" + dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" + "github.com/grassrootseconomics/eth-custodial/pkg/api" "git.grassecon.net/urdt/ussd/config" "git.grassecon.net/urdt/ussd/internal/models" - "github.com/grassrootseconomics/eth-custodial/pkg/api" ) var ( - okResponse api.OKResponse - errResponse api.ErrResponse ) type AccountServiceInterface interface { - CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) - CreateAccount(ctx context.Context) (*api.OKResponse, error) - CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) + //CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) + CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) + CreateAccount(ctx context.Context) (*models.AccountResult, error) + //CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) + // TODO: poorly named method seems to be checking transaction + CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) - FetchVouchers(ctx context.Context, publicKey string) (*models.VoucherHoldingResponse, error) + FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) + //FetchVouchers(ctx context.Context, publicKey string) (*api.OKResponse, error) } type AccountService struct { @@ -39,32 +41,38 @@ type AccountService struct { // - string: The status of the transaction as a string. If there is an error during the request or processing, this will be an empty string. // - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data. // If no error occurs, this will be nil -func (as *AccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) { - resp, err := http.Get(config.BalanceURL + trackingId) - if err != nil { - return nil, err - } - defer resp.Body.Close() +func (as *AccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { + var r models.TrackStatusResult - body, err := io.ReadAll(resp.Body) + ep, err := url.JoinPath(config.TrackURL, trackingId) if err != nil { return nil, err } - var trackResp models.TrackStatusResponse - err = json.Unmarshal(body, &trackResp) + req, err := http.NewRequest("GET", ep, nil) if err != nil { return nil, err } - return &trackResp, nil + _, err = doCustodialRequest(ctx, req, &r) + if err != nil { + return nil, err + } + + return &r, nil } func (as *AccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) { + var okResponse api.OKResponse + var errResponse api.ErrResponse var err error - // Construct the URL with the path parameter - url := fmt.Sprintf("%s/%s", config.TrackURL, publicKey) - req, err := http.NewRequest("GET", url, nil) + + ep, err := url.JoinPath(config.TrackURL, publicKey) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", ep, nil) if err != nil { return nil, err } @@ -104,41 +112,83 @@ func (as *AccountService) TrackAccountStatus(ctx context.Context, publicKey stri // CheckBalance retrieves the balance for a given public key from the custodial balance API endpoint. // Parameters: // - publicKey: The public key associated with the account whose balance needs to be checked. -func (as *AccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) { - resp, err := http.Get(config.BalanceURL + publicKey) +func (as *AccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) { + var balanceResult models.BalanceResult + + ep, err := url.JoinPath(config.BalanceURL, publicKey) if err != nil { return nil, err } - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) + + req, err := http.NewRequest("GET", ep, nil) if err != nil { return nil, err } - var balanceResp models.BalanceResponse - err = json.Unmarshal(body, &balanceResp) - if err != nil { - return nil, err - } - return &balanceResp, nil + + _, err = doCustodialRequest(ctx, req, &balanceResult) + return &balanceResult, err } + // CreateAccount creates a new account in the custodial system. // Returns: // - *models.AccountResponse: A pointer to an AccountResponse struct containing the details of the created account. // If there is an error during the request or processing, this will be nil. // - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data. // If no error occurs, this will be nil. -func (as *AccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) { - var err error - +func (as *AccountService) CreateAccount(ctx context.Context) (*models.AccountResult, error) { + var r models.AccountResult // Create a new request req, err := http.NewRequest("POST", config.CreateAccountURL, nil) if err != nil { return nil, err } - req.Header.Set("Content-Type", "application/json") - req.Header.Set("X-GE-KEY", "xd") + _, err = doCustodialRequest(ctx, req, &r) + if err != nil { + return nil, err + } + + return &r, nil +} + +// FetchVouchers retrieves the token holdings for a given public key from the custodial holdings API endpoint +// Parameters: +// - publicKey: The public key associated with the account. +func (as *AccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + var r []dataserviceapi.TokenHoldings + + req, err := http.NewRequest("GET", config.VoucherHoldingsURL, nil) + if err != nil { + return nil, err + } + + _, err = doDataRequest(ctx, req, r) + if err != nil { + return nil, err + } + + return r, nil + +// +// file, err := os.Open("sample_tokens.json") +// if err != nil { +// return nil, err +// } +// defer file.Close() +// var holdings models.VoucherHoldingResponse +// +// if err := json.NewDecoder(file).Decode(&holdings); err != nil { +// return nil, err +// } +// return &holdings, nil +} + +func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { + var okResponse api.OKResponse + var errResponse api.ErrResponse + + req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { errResponse.Description = err.Error() @@ -165,21 +215,22 @@ func (as *AccountService) CreateAccount(ctx context.Context) (*api.OKResponse, e return nil, errors.New("Empty api result") } return &okResponse, nil -} -// FetchVouchers retrieves the token holdings for a given public key from the custodial holdings API endpoint -// Parameters: -// - publicKey: The public key associated with the account. -func (as *AccountService) FetchVouchers(ctx context.Context, publicKey string) (*models.VoucherHoldingResponse, error) { - file, err := os.Open("sample_tokens.json") + v, err := json.Marshal(okResponse.Result) if err != nil { return nil, err } - defer file.Close() - var holdings models.VoucherHoldingResponse - if err := json.NewDecoder(file).Decode(&holdings); err != nil { - return nil, err - } - return &holdings, nil + err = json.Unmarshal(v, &rcpt) + return &okResponse, err +} + +func doCustodialRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { + req.Header.Set("X-GE-KEY", config.CustodialAPIKey) + return doRequest(ctx, req, rcpt) +} + +func doDataRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { + req.Header.Set("X-GE-KEY", config.DataAPIKey) + return doRequest(ctx, req, rcpt) } From a48170321c03aa232aabf7065f98c08c947e6e9f Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 01:51:36 +0000 Subject: [PATCH 06/28] Finish refactor result models --- internal/handlers/ussd/menuhandler_test.go | 136 ++++++--------------- 1 file changed, 36 insertions(+), 100 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 5f3c953..77447ca 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -88,18 +88,14 @@ func TestCreateAccount(t *testing.T) { tests := []struct { name string - serverResponse *api.OKResponse + serverResponse *models.AccountResult expectedResult resource.Result }{ { name: "Test account creation success", - serverResponse: &api.OKResponse{ - Ok: true, - Description: "Account creation successed", - Result: map[string]any{ - "trackingId": "1234567890", - "publicKey": "0xD3adB33f", - }, + serverResponse: &models.AccountResult{ + TrackingId: "1234567890", + PublicKey: "0xD3adB33f", }, expectedResult: resource.Result{ FlagSet: []uint32{flag_account_created}, @@ -119,9 +115,9 @@ func TestCreateAccount(t *testing.T) { flagManager: fm.parser, } - publicKey := tt.serverResponse.Result["publicKey"].(string) + publicKey := tt.serverResponse.PublicKey data := map[common.DataTyp]string{ - common.DATA_TRACKING_ID: tt.serverResponse.Result["trackingId"].(string), + common.DATA_TRACKING_ID: tt.serverResponse.TrackingId, common.DATA_PUBLIC_KEY: publicKey, } @@ -1055,7 +1051,7 @@ func TestCheckAccountStatus(t *testing.T) { name string input []byte serverResponse *api.OKResponse - response *models.TrackStatusResponse + response *models.TrackStatusResult expectedResult resource.Result }{ { @@ -1068,25 +1064,12 @@ func TestCheckAccountStatus(t *testing.T) { "active": true, }, }, - response: &models.TrackStatusResponse{ - Ok: true, - Result: struct { - Transaction struct { - CreatedAt time.Time "json:\"createdAt\"" - Status string "json:\"status\"" - TransferValue json.Number "json:\"transferValue\"" - TxHash string "json:\"txHash\"" - TxType string "json:\"txType\"" - } - }{ - Transaction: models.Transaction{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", - }, - }, + response: &models.TrackStatusResult { + CreatedAt: time.Now(), + Status: "SUCCESS", + TransferValue: json.Number("0.5"), + TxHash: "0x123abc456def", + TxType: "transfer", }, expectedResult: resource.Result{ FlagSet: []uint32{flag_account_success}, @@ -1096,25 +1079,12 @@ func TestCheckAccountStatus(t *testing.T) { { name: "Test when the account is not yet on the sarafu network", input: []byte("TrackingId1234"), - response: &models.TrackStatusResponse{ - Ok: true, - Result: struct { - Transaction struct { - CreatedAt time.Time "json:\"createdAt\"" - Status string "json:\"status\"" - TransferValue json.Number "json:\"transferValue\"" - TxHash string "json:\"txHash\"" - TxType string "json:\"txType\"" - } - }{ - Transaction: models.Transaction{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", - }, - }, + response: &models.TrackStatusResult{ + CreatedAt: time.Now(), + Status: "SUCCESS", + TransferValue: json.Number("0.5"), + TxHash: "0x123abc456def", + TxType: "transfer", }, serverResponse: &api.OKResponse{ Ok: true, @@ -1140,7 +1110,7 @@ func TestCheckAccountStatus(t *testing.T) { flagManager: fm.parser, } - status := tt.response.Result.Transaction.Status + status := tt.response.Status // Define expected interactions with the mock mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return(tt.input, nil) @@ -1833,36 +1803,14 @@ func TestFetchCustodialBalances(t *testing.T) { tests := []struct { name string - balanceResonse *models.BalanceResponse + balanceResponse *models.BalanceResult expectedResult resource.Result }{ { name: "Test when fetch custodial balances is not a success", - balanceResonse: &models.BalanceResponse{ - Ok: false, - Result: struct { - Balance string `json:"balance"` - Nonce json.Number `json:"nonce"` - }{ - Balance: "0.003 CELO", - Nonce: json.Number("0"), - }, - }, - expectedResult: resource.Result{ - FlagSet: []uint32{flag_api_error}, - }, - }, - { - name: "Test when fetch custodial balances is a success", - balanceResonse: &models.BalanceResponse{ - Ok: true, - Result: struct { - Balance string `json:"balance"` - Nonce json.Number `json:"nonce"` - }{ - Balance: "0.003 CELO", - Nonce: json.Number("0"), - }, + balanceResponse: &models.BalanceResult{ + Balance: "0.003 CELO", + Nonce: json.Number("0"), }, expectedResult: resource.Result{ FlagReset: []uint32{flag_api_error}, @@ -1886,7 +1834,7 @@ func TestFetchCustodialBalances(t *testing.T) { // Set up the expected behavior of the mock mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) - mockCreateAccountService.On("CheckBalance", string(publicKey)).Return(tt.balanceResonse, nil) + mockCreateAccountService.On("CheckBalance", string(publicKey)).Return(tt.balanceResponse, nil) // Call the method res, _ := h.FetchCustodialBalances(ctx, "fetch_custodial_balances", []byte("")) @@ -1918,35 +1866,24 @@ func TestSetDefaultVoucher(t *testing.T) { tests := []struct { name string - vouchersResp *models.VoucherHoldingResponse + vouchersResp []dataserviceapi.TokenHoldings expectedResult resource.Result }{ { name: "Test set default voucher when no active voucher exists", - vouchersResp: &models.VoucherHoldingResponse{ - Ok: true, - Description: "Vouchers fetched successfully", - Result: models.VoucherResult{ - Holdings: []dataserviceapi.TokenHoldings{ - { - ContractAddress: "0x123", - TokenSymbol: "TOKEN1", - TokenDecimals: "18", - Balance: "100", - }, - }, + vouchersResp: []dataserviceapi.TokenHoldings { + dataserviceapi.TokenHoldings{ + ContractAddress: "0x123", + TokenSymbol: "TOKEN1", + TokenDecimals: "18", + Balance: "100", }, }, expectedResult: resource.Result{}, }, { name: "Test no vouchers available", - vouchersResp: &models.VoucherHoldingResponse{ - Ok: true, - Description: "No vouchers available", - Result: models.VoucherResult{ - Holdings: []dataserviceapi.TokenHoldings{}, - }, + vouchersResp: []dataserviceapi.TokenHoldings { }, expectedResult: resource.Result{ FlagSet: []uint32{flag_no_active_voucher}, @@ -1970,8 +1907,8 @@ func TestSetDefaultVoucher(t *testing.T) { mockAccountService.On("FetchVouchers", string(publicKey)).Return(tt.vouchersResp, nil) - if len(tt.vouchersResp.Result.Holdings) > 0 { - firstVoucher := tt.vouchersResp.Result.Holdings[0] + if len(tt.vouchersResp) > 0 { + firstVoucher := tt.vouchersResp[0] mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACTIVE_SYM, []byte(firstVoucher.TokenSymbol)).Return(nil) mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACTIVE_BAL, []byte(firstVoucher.Balance)).Return(nil) } @@ -2006,8 +1943,7 @@ func TestCheckVouchers(t *testing.T) { mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) - mockVouchersResponse := &models.VoucherHoldingResponse{} - mockVouchersResponse.Result.Holdings = []dataserviceapi.TokenHoldings{ + mockVouchersResponse := []dataserviceapi.TokenHoldings{ {ContractAddress: "0xd4c288865Ce", TokenSymbol: "SRF", TokenDecimals: "6", Balance: "100"}, {ContractAddress: "0x41c188d63Qa", TokenSymbol: "MILO", TokenDecimals: "4", Balance: "200"}, } From dc198215b1272f5f745babe3e3319295572fac3c Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 02:03:29 +0000 Subject: [PATCH 07/28] Remove commented code --- internal/handlers/ussd/menuhandler.go | 1 - internal/handlers/ussd/menuhandler_test.go | 1 - internal/models/balanceresponse.go | 8 -------- internal/models/trackstatusresponse.go | 7 ------- internal/models/vouchersresponse.go | 1 - remote/accountservice.go | 16 ---------------- 6 files changed, 34 deletions(-) delete mode 100644 internal/models/vouchersresponse.go diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 5f6f81a..98a633c 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -705,7 +705,6 @@ func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input } res.FlagReset = append(res.FlagReset, flag_api_error) - //balance := balanceResponse.Result.Balance balance := balanceResponse.Balance switch balanceType { diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 77447ca..8708145 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -815,7 +815,6 @@ func TestAuthorize(t *testing.T) { // Create required mocks mockDataStore := new(mocks.MockUserDataStore) mockCreateAccountService := new(mocks.MockAccountService) - //expectedResult := resource.Result{} mockState := state.NewState(16) flag_incorrect_pin, _ := fm.GetFlag("flag_incorrect_pin") flag_account_authorized, _ := fm.GetFlag("flag_account_authorized") diff --git a/internal/models/balanceresponse.go b/internal/models/balanceresponse.go index 3d57c95..b2baa41 100644 --- a/internal/models/balanceresponse.go +++ b/internal/models/balanceresponse.go @@ -3,14 +3,6 @@ package models import "encoding/json" -//type BalanceResponse struct { -// Ok bool `json:"ok"` -// Result struct { -// Balance string `json:"balance"` -// Nonce json.Number `json:"nonce"` -// } `json:"result"` -//} -// type BalanceResult struct { Balance string `json:"balance"` Nonce json.Number `json:"nonce"` diff --git a/internal/models/trackstatusresponse.go b/internal/models/trackstatusresponse.go index 6130c6e..202b69b 100644 --- a/internal/models/trackstatusresponse.go +++ b/internal/models/trackstatusresponse.go @@ -4,13 +4,6 @@ import ( "encoding/json" "time" ) -//type Transaction struct { -// CreatedAt time.Time `json:"createdAt"` -// Status string `json:"status"` -// TransferValue json.Number `json:"transferValue"` -// TxHash string `json:"txHash"` -// TxType string `json:"txType"` -//} type TrackStatusResult struct { CreatedAt time.Time `json:"createdAt"` diff --git a/internal/models/vouchersresponse.go b/internal/models/vouchersresponse.go deleted file mode 100644 index 2640e7f..0000000 --- a/internal/models/vouchersresponse.go +++ /dev/null @@ -1 +0,0 @@ -package models diff --git a/remote/accountservice.go b/remote/accountservice.go index c11910f..bc98cf1 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -18,15 +18,12 @@ var ( ) type AccountServiceInterface interface { - //CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) CreateAccount(ctx context.Context) (*models.AccountResult, error) - //CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) // TODO: poorly named method seems to be checking transaction CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) - //FetchVouchers(ctx context.Context, publicKey string) (*api.OKResponse, error) } type AccountService struct { @@ -169,19 +166,6 @@ func (as *AccountService) FetchVouchers(ctx context.Context, publicKey string) ( } return r, nil - -// -// file, err := os.Open("sample_tokens.json") -// if err != nil { -// return nil, err -// } -// defer file.Close() -// var holdings models.VoucherHoldingResponse -// -// if err := json.NewDecoder(file).Decode(&holdings); err != nil { -// return nil, err -// } -// return &holdings, nil } func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { From bab3f673ebb028d4ad2c174aa7f86a6721b80067 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 31 Oct 2024 14:13:21 +0300 Subject: [PATCH 08/28] Removed unused model --- internal/models/tokenresponse.go | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 internal/models/tokenresponse.go diff --git a/internal/models/tokenresponse.go b/internal/models/tokenresponse.go deleted file mode 100644 index d243d93..0000000 --- a/internal/models/tokenresponse.go +++ /dev/null @@ -1,18 +0,0 @@ -package models - -type ApiResponse struct { - OK bool `json:"ok"` - Description string `json:"description"` - Result Result `json:"result"` -} - -type Result struct { - Holdings []Holding `json:"holdings"` -} - -type Holding struct { - ContractAddress string `json:"contractAddress"` - TokenSymbol string `json:"tokenSymbol"` - TokenDecimals string `json:"tokenDecimals"` - Balance string `json:"balance"` -} From b9c56b04ce3f1eee05cfcc20a55eb38ee769a4ab Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 11:43:27 +0000 Subject: [PATCH 09/28] Remove obsolete track account status code --- internal/handlers/ussd/menuhandler_test.go | 17 ++++------------- internal/models/trackstatusresponse.go | 6 +++++- .../testutil/testservice/TestAccountService.go | 7 +------ 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 8708145..8c3867a 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -7,7 +7,6 @@ import ( "log" "path" "testing" - "time" "git.defalsify.org/vise.git/asm" "git.defalsify.org/vise.git/db" @@ -1064,11 +1063,7 @@ func TestCheckAccountStatus(t *testing.T) { }, }, response: &models.TrackStatusResult { - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", + Active: true, }, expectedResult: resource.Result{ FlagSet: []uint32{flag_account_success}, @@ -1079,11 +1074,7 @@ func TestCheckAccountStatus(t *testing.T) { name: "Test when the account is not yet on the sarafu network", input: []byte("TrackingId1234"), response: &models.TrackStatusResult{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", + Active: false, }, serverResponse: &api.OKResponse{ Ok: true, @@ -1109,13 +1100,13 @@ func TestCheckAccountStatus(t *testing.T) { flagManager: fm.parser, } - status := tt.response.Status + status := tt.response.Active // Define expected interactions with the mock mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return(tt.input, nil) mockCreateAccountService.On("CheckAccountStatus", string(tt.input)).Return(tt.response, nil) mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) - mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_STATUS, []byte(status)).Return(nil).Maybe() + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_STATUS, status).Return(nil).Maybe() // Call the method under test res, _ := h.CheckAccountStatus(ctx, "check_account_status", tt.input) diff --git a/internal/models/trackstatusresponse.go b/internal/models/trackstatusresponse.go index 202b69b..47d757d 100644 --- a/internal/models/trackstatusresponse.go +++ b/internal/models/trackstatusresponse.go @@ -5,10 +5,14 @@ import ( "time" ) -type TrackStatusResult struct { +type Transaction struct { CreatedAt time.Time `json:"createdAt"` Status string `json:"status"` TransferValue json.Number `json:"transferValue"` TxHash string `json:"txHash"` TxType string `json:"txType"` } + +type TrackStatusResult struct { + Active bool `json:"active"` +} diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go index 885e63f..78a2798 100644 --- a/internal/testutil/testservice/TestAccountService.go +++ b/internal/testutil/testservice/TestAccountService.go @@ -3,7 +3,6 @@ package testservice import ( "context" "encoding/json" - "time" "git.grassecon.net/urdt/ussd/internal/models" "github.com/grassrootseconomics/eth-custodial/pkg/api" @@ -30,11 +29,7 @@ func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey strin func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { return &models.TrackStatusResult { - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", + Active: true, }, nil } From b2d180e8ebc0d353a6939d78e8f965fa6b405b89 Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 12:15:07 +0000 Subject: [PATCH 10/28] WIP Trying to clean up account status check --- internal/handlers/ussd/menuhandler.go | 5 +- internal/handlers/ussd/menuhandler_test.go | 35 +++--------- internal/testutil/mocks/servicemock.go | 8 +-- .../testservice/TestAccountService.go | 13 +---- remote/accountservice.go | 55 +------------------ 5 files changed, 15 insertions(+), 101 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 98a633c..ed5f466 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -557,17 +557,16 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b if err != nil { return res, err } - okResponse, err = h.accountService.TrackAccountStatus(ctx, string(publicKey)) + r, err := h.accountService.TrackAccountStatus(ctx, string(publicKey)) if err != nil { res.FlagSet = append(res.FlagSet, flag_api_error) return res, err } res.FlagReset = append(res.FlagReset, flag_api_error) - isActive := okResponse.Result["active"].(bool) if !ok { return res, err } - if isActive { + if r.Active { res.FlagSet = append(res.FlagSet, flag_account_success) res.FlagReset = append(res.FlagReset, flag_account_pending) } else { diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 8c3867a..7940704 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -1053,36 +1053,18 @@ func TestCheckAccountStatus(t *testing.T) { expectedResult resource.Result }{ { - name: "Test when account is on the Sarafu network", - input: []byte("TrackingId1234"), - serverResponse: &api.OKResponse{ - Ok: true, - Description: "Account creation succeeded", - Result: map[string]any{ - "active": true, - }, - }, - response: &models.TrackStatusResult { - Active: true, - }, - expectedResult: resource.Result{ - FlagSet: []uint32{flag_account_success}, - FlagReset: []uint32{flag_api_error, flag_account_pending}, - }, - }, - { - name: "Test when the account is not yet on the sarafu network", + name: "Test when the account is not yet on the sarafu network", input: []byte("TrackingId1234"), response: &models.TrackStatusResult{ Active: false, }, - serverResponse: &api.OKResponse{ - Ok: true, - Description: "Account creation succeeded", - Result: map[string]any{ - "active": false, - }, - }, +// serverResponse: &api.OKResponse{ +// Ok: true, +// Description: "Account creation succeeded", +// Result: map[string]any{ +// "active": false, +// }, +// }, expectedResult: resource.Result{ FlagSet: []uint32{flag_account_pending}, FlagReset: []uint32{flag_api_error, flag_account_success}, @@ -1104,7 +1086,6 @@ func TestCheckAccountStatus(t *testing.T) { // Define expected interactions with the mock mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return(tt.input, nil) - mockCreateAccountService.On("CheckAccountStatus", string(tt.input)).Return(tt.response, nil) mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_STATUS, status).Return(nil).Maybe() diff --git a/internal/testutil/mocks/servicemock.go b/internal/testutil/mocks/servicemock.go index 3b36ba7..bec48fd 100644 --- a/internal/testutil/mocks/servicemock.go +++ b/internal/testutil/mocks/servicemock.go @@ -4,7 +4,6 @@ import ( "context" "git.grassecon.net/urdt/ussd/internal/models" - "github.com/grassrootseconomics/eth-custodial/pkg/api" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" "github.com/stretchr/testify/mock" ) @@ -24,13 +23,8 @@ func (m *MockAccountService) CheckBalance(ctx context.Context, publicKey string) return args.Get(0).(*models.BalanceResult), args.Error(1) } -func (m *MockAccountService) TrackAccountStatus(ctx context.Context, trackingId string) (*api.OKResponse, error) { +func (m *MockAccountService) TrackAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { args := m.Called(trackingId) - return args.Get(0).(*api.OKResponse), args.Error(1) -} - -func (m *MockAccountService) CheckAccountStatus(ctx context.Context,publicKey string) (*models.TrackStatusResult, error) { - args := m.Called(publicKey) return args.Get(0).(*models.TrackStatusResult), args.Error(1) } diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go index 78a2798..a9a3085 100644 --- a/internal/testutil/testservice/TestAccountService.go +++ b/internal/testutil/testservice/TestAccountService.go @@ -5,7 +5,6 @@ import ( "encoding/json" "git.grassecon.net/urdt/ussd/internal/models" - "github.com/grassrootseconomics/eth-custodial/pkg/api" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" ) @@ -27,22 +26,12 @@ func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey strin return balanceResponse, nil } -func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { +func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*models.TrackStatusResult, error) { return &models.TrackStatusResult { Active: true, }, nil } -func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) { - return &api.OKResponse{ - Ok: true, - Description: "Account creation succeeded", - Result: map[string]any{ - "active": true, - }, - }, nil -} - func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { return []dataserviceapi.TokenHoldings { dataserviceapi.TokenHoldings { diff --git a/remote/accountservice.go b/remote/accountservice.go index bc98cf1..24a469e 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -20,9 +20,7 @@ var ( type AccountServiceInterface interface { CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) CreateAccount(ctx context.Context) (*models.AccountResult, error) - // TODO: poorly named method seems to be checking transaction - CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) - TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) + TrackAccountStatus(ctx context.Context, publicKey string) (*models.TrackStatusResult, error) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) } @@ -38,7 +36,7 @@ type AccountService struct { // - string: The status of the transaction as a string. If there is an error during the request or processing, this will be an empty string. // - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data. // If no error occurs, this will be nil -func (as *AccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { +func (as *AccountService) TrackAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { var r models.TrackStatusResult ep, err := url.JoinPath(config.TrackURL, trackingId) @@ -59,60 +57,13 @@ func (as *AccountService) CheckAccountStatus(ctx context.Context, trackingId str return &r, nil } -func (as *AccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) { - var okResponse api.OKResponse - var errResponse api.ErrResponse - var err error - - ep, err := url.JoinPath(config.TrackURL, publicKey) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", ep, nil) - if err != nil { - return nil, err - } - - req.Header.Set("Content-Type", "application/json") - req.Header.Set("X-GE-KEY", "xd") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - errResponse.Description = err.Error() - return nil, err - } - if resp.StatusCode >= http.StatusBadRequest { - err := json.Unmarshal([]byte(body), &errResponse) - if err != nil { - return nil, err - } - return nil, errors.New(errResponse.Description) - } - err = json.Unmarshal([]byte(body), &okResponse) - if err != nil { - return nil, err - } - if len(okResponse.Result) == 0 { - return nil, errors.New("Empty api result") - } - return &okResponse, nil - -} - // CheckBalance retrieves the balance for a given public key from the custodial balance API endpoint. // Parameters: // - publicKey: The public key associated with the account whose balance needs to be checked. func (as *AccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) { var balanceResult models.BalanceResult - ep, err := url.JoinPath(config.BalanceURL, publicKey) + ep, err := url.JoinPath(config.BalanceURL, publicKey) if err != nil { return nil, err } From 3ae75b27a5cfa10726f2dcf3b2a7afe5a7807cfe Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 12:38:31 +0000 Subject: [PATCH 11/28] WIP replaced check account method but traversal crashes --- internal/handlers/ussd/menuhandler_test.go | 7 ++++--- remote/accountservice.go | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 7940704..6105657 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -20,7 +20,7 @@ import ( "git.grassecon.net/urdt/ussd/common" "github.com/alecthomas/assert/v2" - "github.com/grassrootseconomics/eth-custodial/pkg/api" +// "github.com/grassrootseconomics/eth-custodial/pkg/api" testdataloader "github.com/peteole/testdata-loader" "github.com/stretchr/testify/require" @@ -1048,7 +1048,7 @@ func TestCheckAccountStatus(t *testing.T) { tests := []struct { name string input []byte - serverResponse *api.OKResponse + //serverResponse *api.OKResponse response *models.TrackStatusResult expectedResult resource.Result }{ @@ -1086,7 +1086,8 @@ func TestCheckAccountStatus(t *testing.T) { // Define expected interactions with the mock mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return(tt.input, nil) - mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) + //mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) + mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.response, nil) mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_STATUS, status).Return(nil).Maybe() // Call the method under test diff --git a/remote/accountservice.go b/remote/accountservice.go index 24a469e..bc6a448 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -36,10 +36,10 @@ type AccountService struct { // - string: The status of the transaction as a string. If there is an error during the request or processing, this will be an empty string. // - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data. // If no error occurs, this will be nil -func (as *AccountService) TrackAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { +func (as *AccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*models.TrackStatusResult, error) { var r models.TrackStatusResult - ep, err := url.JoinPath(config.TrackURL, trackingId) + ep, err := url.JoinPath(config.TrackURL, publicKey) if err != nil { return nil, err } From 4bf56c525f5b0e9ac90e2c22fc68805327d03108 Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 13:19:44 +0000 Subject: [PATCH 12/28] Export voucher related code --- {internal/utils => common}/vouchers.go | 45 ++++++++++----------- {internal/utils => common}/vouchers_test.go | 2 +- internal/handlers/ussd/menuhandler.go | 10 ++--- 3 files changed, 28 insertions(+), 29 deletions(-) rename {internal/utils => common}/vouchers.go (74%) rename {internal/utils => common}/vouchers_test.go (99%) diff --git a/internal/utils/vouchers.go b/common/vouchers.go similarity index 74% rename from internal/utils/vouchers.go rename to common/vouchers.go index 0372700..291f28d 100644 --- a/internal/utils/vouchers.go +++ b/common/vouchers.go @@ -1,4 +1,4 @@ -package utils +package common import ( "context" @@ -6,7 +6,6 @@ import ( "strings" "git.grassecon.net/urdt/ussd/internal/storage" - "git.grassecon.net/urdt/ussd/common" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" ) @@ -96,13 +95,13 @@ func MatchVoucher(input, symbols, balances, decimals, addresses string) (symbol, return } -// StoreTemporaryVoucher saves voucher metadata as temporary entries in the common.DataStore. -func StoreTemporaryVoucher(ctx context.Context, store common.DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { - entries := map[common.DataTyp][]byte{ - common.DATA_TEMPORARY_SYM: []byte(data.TokenSymbol), - common.DATA_TEMPORARY_BAL: []byte(data.Balance), - common.DATA_TEMPORARY_DECIMAL: []byte(data.TokenDecimals), - common.DATA_TEMPORARY_ADDRESS: []byte(data.ContractAddress), +// StoreTemporaryVoucher saves voucher metadata as temporary entries in the DataStore. +func StoreTemporaryVoucher(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { + entries := map[DataTyp][]byte{ + DATA_TEMPORARY_SYM: []byte(data.TokenSymbol), + DATA_TEMPORARY_BAL: []byte(data.Balance), + DATA_TEMPORARY_DECIMAL: []byte(data.TokenDecimals), + DATA_TEMPORARY_ADDRESS: []byte(data.ContractAddress), } for key, value := range entries { @@ -113,13 +112,13 @@ func StoreTemporaryVoucher(ctx context.Context, store common.DataStore, sessionI return nil } -// GetTemporaryVoucherData retrieves temporary voucher metadata from the common.DataStore. -func GetTemporaryVoucherData(ctx context.Context, store common.DataStore, sessionId string) (*dataserviceapi.TokenHoldings, error) { - keys := []common.DataTyp{ - common.DATA_TEMPORARY_SYM, - common.DATA_TEMPORARY_BAL, - common.DATA_TEMPORARY_DECIMAL, - common.DATA_TEMPORARY_ADDRESS, +// GetTemporaryVoucherData retrieves temporary voucher metadata from the DataStore. +func GetTemporaryVoucherData(ctx context.Context, store DataStore, sessionId string) (*dataserviceapi.TokenHoldings, error) { + keys := []DataTyp{ + DATA_TEMPORARY_SYM, + DATA_TEMPORARY_BAL, + DATA_TEMPORARY_DECIMAL, + DATA_TEMPORARY_ADDRESS, } data := &dataserviceapi.TokenHoldings{} @@ -141,14 +140,14 @@ func GetTemporaryVoucherData(ctx context.Context, store common.DataStore, sessio return data, nil } -// UpdateVoucherData sets the active voucher data and clears the temporary voucher data in the common.DataStore. -func UpdateVoucherData(ctx context.Context, store common.DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { +// UpdateVoucherData sets the active voucher data and clears the temporary voucher data in the DataStore. +func UpdateVoucherData(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { // Active voucher data entries - activeEntries := map[common.DataTyp][]byte{ - common.DATA_ACTIVE_SYM: []byte(data.TokenSymbol), - common.DATA_ACTIVE_BAL: []byte(data.Balance), - common.DATA_ACTIVE_DECIMAL: []byte(data.TokenDecimals), - common.DATA_ACTIVE_ADDRESS: []byte(data.ContractAddress), + activeEntries := map[DataTyp][]byte{ + DATA_ACTIVE_SYM: []byte(data.TokenSymbol), + DATA_ACTIVE_BAL: []byte(data.Balance), + DATA_ACTIVE_DECIMAL: []byte(data.TokenDecimals), + DATA_ACTIVE_ADDRESS: []byte(data.ContractAddress), } // Write active data diff --git a/internal/utils/vouchers_test.go b/common/vouchers_test.go similarity index 99% rename from internal/utils/vouchers_test.go rename to common/vouchers_test.go index c59037e..401d4d7 100644 --- a/internal/utils/vouchers_test.go +++ b/common/vouchers_test.go @@ -1,4 +1,4 @@ -package utils +package common import ( "context" diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index ed5f466..2e075d7 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -1117,7 +1117,7 @@ func (h *Handlers) CheckVouchers(ctx context.Context, sym string, input []byte) return res, nil } - data := utils.ProcessVouchers(vouchersResp) + data := common.ProcessVouchers(vouchersResp) // Store all voucher data dataMap := map[string]string{ @@ -1167,7 +1167,7 @@ func (h *Handlers) ViewVoucher(ctx context.Context, sym string, input []byte) (r return res, nil } - metadata, err := utils.GetVoucherData(ctx, h.prefixDb, inputStr) + metadata, err := common.GetVoucherData(ctx, h.prefixDb, inputStr) if err != nil { return res, fmt.Errorf("failed to retrieve voucher data: %v", err) } @@ -1177,7 +1177,7 @@ func (h *Handlers) ViewVoucher(ctx context.Context, sym string, input []byte) (r return res, nil } - if err := utils.StoreTemporaryVoucher(ctx, h.userdataStore, sessionId, metadata); err != nil { + if err := common.StoreTemporaryVoucher(ctx, h.userdataStore, sessionId, metadata); err != nil { return res, err } @@ -1198,13 +1198,13 @@ func (h *Handlers) SetVoucher(ctx context.Context, sym string, input []byte) (re // Get temporary data - tempData, err := utils.GetTemporaryVoucherData(ctx, h.userdataStore, sessionId) + tempData, err := common.GetTemporaryVoucherData(ctx, h.userdataStore, sessionId) if err != nil { return res, err } // Set as active and clear temporary data - if err := utils.UpdateVoucherData(ctx, h.userdataStore, sessionId, tempData); err != nil { + if err := common.UpdateVoucherData(ctx, h.userdataStore, sessionId, tempData); err != nil { return res, err } From 9a528cfd1440f72d0678d318e847e7d10fbdee69 Mon Sep 17 00:00:00 2001 From: lash Date: Fri, 1 Nov 2024 03:17:01 +0000 Subject: [PATCH 13/28] Clean up messily failed conflict resolution --- common/vouchers_test.go | 17 +++-- internal/handlers/ussd/menuhandler.go | 44 ++++++------- internal/handlers/ussd/menuhandler_test.go | 74 ++++------------------ 3 files changed, 44 insertions(+), 91 deletions(-) diff --git a/common/vouchers_test.go b/common/vouchers_test.go index 95fce6e..8b9fa2a 100644 --- a/common/vouchers_test.go +++ b/common/vouchers_test.go @@ -9,13 +9,12 @@ import ( "github.com/stretchr/testify/require" "git.grassecon.net/urdt/ussd/internal/storage" - "git.grassecon.net/urdt/ussd/common" memdb "git.defalsify.org/vise.git/db/mem" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" ) // InitializeTestDb sets up and returns an in-memory database and store. -func InitializeTestDb(t *testing.T) (context.Context, *common.UserDataStore) { +func InitializeTestDb(t *testing.T) (context.Context, *UserDataStore) { ctx := context.Background() // Initialize memDb @@ -23,8 +22,8 @@ func InitializeTestDb(t *testing.T) (context.Context, *common.UserDataStore) { err := db.Connect(ctx, "") require.NoError(t, err, "Failed to connect to memDb") - // Create common.UserDataStore with memDb - store := &common.UserDataStore{Db: db} + // Create UserDataStore with memDb + store := &UserDataStore{Db: db} t.Cleanup(func() { db.Close() // Ensure the DB is closed after each test @@ -183,11 +182,11 @@ func TestUpdateVoucherData(t *testing.T) { require.NoError(t, err) // Verify active data was stored correctly - activeEntries := map[common.DataTyp][]byte{ - common.DATA_ACTIVE_SYM: []byte(newData.TokenSymbol), - common.DATA_ACTIVE_BAL: []byte(newData.Balance), - common.DATA_ACTIVE_DECIMAL: []byte(newData.TokenDecimals), - common.DATA_ACTIVE_ADDRESS: []byte(newData.ContractAddress), + activeEntries := map[DataTyp][]byte{ + DATA_ACTIVE_SYM: []byte(newData.TokenSymbol), + DATA_ACTIVE_BAL: []byte(newData.Balance), + DATA_ACTIVE_DECIMAL: []byte(newData.TokenDecimals), + DATA_ACTIVE_ADDRESS: []byte(newData.ContractAddress), } for key, expectedValue := range activeEntries { diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index db8d520..42785d7 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -20,7 +20,7 @@ import ( "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" "git.grassecon.net/urdt/ussd/common" - "git.grassecon.net/urdt/ussd/internal/handlers/server" + "git.grassecon.net/urdt/ussd/remote" "git.grassecon.net/urdt/ussd/internal/utils" "gopkg.in/leonelquinteros/gotext.v1" @@ -246,7 +246,7 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt res.FlagReset = append(res.FlagReset, flag_incorrect_pin) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(accountPIN)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(accountPIN)) if err != nil { return res, err } @@ -263,7 +263,7 @@ func (h *Handlers) ConfirmPinChange(ctx context.Context, sym string, input []byt flag_pin_mismatch, _ := h.flagManager.GetFlag("flag_pin_mismatch") store := h.userdataStore - temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) + temporaryPin, err := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) if err != nil { return res, err } @@ -294,7 +294,7 @@ func (h *Handlers) VerifyCreatePin(ctx context.Context, sym string, input []byte return res, fmt.Errorf("missing session") } store := h.userdataStore - temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) + temporaryPin, err := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) if err != nil { return res, err } @@ -338,13 +338,13 @@ func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte) flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryFirstName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) - err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(temporaryFirstName)) + temporaryFirstName, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) + err = store.WriteEntry(ctx, sessionId, common.DATA_FIRST_NAME, []byte(temporaryFirstName)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(firstName)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(firstName)) if err != nil { return res, err } @@ -369,13 +369,13 @@ func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte) allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryFamilyName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) - err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(temporaryFamilyName)) + temporaryFamilyName, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) + err = store.WriteEntry(ctx, sessionId, common.DATA_FAMILY_NAME, []byte(temporaryFamilyName)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(familyName)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(familyName)) if err != nil { return res, err } @@ -397,13 +397,13 @@ func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resou allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryYob, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) - err = store.WriteEntry(ctx, sessionId, utils.DATA_YOB, []byte(temporaryYob)) + temporaryYob, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) + err = store.WriteEntry(ctx, sessionId, common.DATA_YOB, []byte(temporaryYob)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(yob)) if err != nil { return res, err } @@ -427,13 +427,13 @@ func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) ( allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryLocation, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) - err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(temporaryLocation)) + temporaryLocation, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) + err = store.WriteEntry(ctx, sessionId, common.DATA_LOCATION, []byte(temporaryLocation)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(location)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(location)) if err != nil { return res, err } @@ -457,13 +457,13 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryGender, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) - err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(temporaryGender)) + temporaryGender, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) + err = store.WriteEntry(ctx, sessionId, common.DATA_GENDER, []byte(temporaryGender)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(gender)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(gender)) if err != nil { return res, err } @@ -488,13 +488,13 @@ func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryOfferings, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) - err = store.WriteEntry(ctx, sessionId, utils.DATA_OFFERINGS, []byte(temporaryOfferings)) + temporaryOfferings, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) + err = store.WriteEntry(ctx, sessionId, common.DATA_OFFERINGS, []byte(temporaryOfferings)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(offerings)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(offerings)) if err != nil { return res, err } diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 30f84d9..2eb6519 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -19,7 +19,6 @@ import ( "git.grassecon.net/urdt/ussd/internal/testutil/testservice" "git.grassecon.net/urdt/ussd/common" - "git.grassecon.net/urdt/ussd/internal/utils" "github.com/alecthomas/assert/v2" // "github.com/grassrootseconomics/eth-custodial/pkg/api" testdataloader "github.com/peteole/testdata-loader" @@ -181,11 +180,7 @@ func TestSaveFirstname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock -<<<<<<< HEAD - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_FIRST_NAME, []byte(firstName)).Return(nil) -======= - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(firstName)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(firstName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -218,11 +213,7 @@ func TestSaveFamilyname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock -<<<<<<< HEAD - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_FAMILY_NAME, []byte(familyName)).Return(nil) -======= - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(familyName)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(familyName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -284,11 +275,7 @@ func TestSaveTemporaryPin(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Set up the expected behavior of the mock -<<<<<<< HEAD - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_PIN, []byte(tt.input)).Return(nil) -======= - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.input)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(tt.input)).Return(nil) // Call the method res, err := h.SaveTemporaryPin(ctx, "save_pin", tt.input) @@ -317,11 +304,7 @@ func TestSaveYoB(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock -<<<<<<< HEAD - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_YOB, []byte(yob)).Return(nil) -======= - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -354,11 +337,7 @@ func TestSaveLocation(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock -<<<<<<< HEAD - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_LOCATION, []byte(yob)).Return(nil) -======= - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -391,11 +370,7 @@ func TestSaveOfferings(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock -<<<<<<< HEAD - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_OFFERINGS, []byte(offerings)).Return(nil) -======= - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(offerings)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(offerings)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -461,17 +436,10 @@ func TestSaveGender(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Set up expectations for the mock database if tt.expectCall { -<<<<<<< HEAD - expectedKey := common.DATA_GENDER + expectedKey := common.DATA_TEMPORARY_VALUE mockStore.On("WriteEntry", ctx, sessionId, expectedKey, []byte(tt.expectedGender)).Return(nil) } else { - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_GENDER, []byte(tt.expectedGender)).Return(nil) -======= - expectedKey := utils.DATA_TEMPORARY_VALUE - mockStore.On("WriteEntry", ctx, sessionId, expectedKey, []byte(tt.expectedGender)).Return(nil) - } else { - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)).Return(nil) } mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol) // Create the Handlers instance with the mock store @@ -489,15 +457,9 @@ func TestSaveGender(t *testing.T) { // Verify expectations if tt.expectCall { -<<<<<<< HEAD - mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, common.DATA_GENDER, []byte(tt.expectedGender)) + mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) } else { - mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, common.DATA_GENDER, []byte(tt.expectedGender)) -======= - mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) - } else { - mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) ->>>>>>> master + mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) } }) } @@ -1072,11 +1034,7 @@ func TestVerifyCreatePin(t *testing.T) { }, } -<<<<<<< HEAD - typ := common.DATA_TEMPORARY_PIN -======= - typ := utils.DATA_TEMPORARY_VALUE ->>>>>>> master + typ := common.DATA_TEMPORARY_VALUE for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1816,11 +1774,7 @@ func TestConfirmPin(t *testing.T) { // Set up the expected behavior of the mock mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_PIN, []byte(tt.temporarypin)).Return(nil) -<<<<<<< HEAD - mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_TEMPORARY_PIN).Return(tt.temporarypin, nil) -======= - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE).Return(tt.temporarypin, nil) ->>>>>>> master + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE).Return(tt.temporarypin, nil) //Call the function under test res, _ := h.ConfirmPinChange(ctx, "confirm_pin_change", tt.temporarypin) @@ -2060,7 +2014,7 @@ func TestViewVoucher(t *testing.T) { // Set up expectations for mockDataStore expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "100", "6", "0xd4c288865Ce") - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(expectedData)).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(expectedData)).Return(nil) res, err := h.ViewVoucher(ctx, "view_voucher", []byte("1")) assert.NoError(t, err) @@ -2095,7 +2049,7 @@ func TestSetVoucher(t *testing.T) { } // Mocking ReadEntry calls for temporary data retrieval - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE).Return([]byte(expectedData), nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE).Return([]byte(expectedData), nil) // Mocking WriteEntry calls for setting active data for key, value := range activeEntries { From cfe3e526dfb1793ab4977998ae730c834ac67d5e Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Fri, 1 Nov 2024 13:17:45 +0300 Subject: [PATCH 14/28] Remove the subprefixdbmock --- internal/handlers/ussd/menuhandler_test.go | 87 +++++++++++++++------- internal/testutil/mocks/subprefixdbmock.go | 21 ------ 2 files changed, 59 insertions(+), 49 deletions(-) delete mode 100644 internal/testutil/mocks/subprefixdbmock.go diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 77ae68c..6f70108 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -16,6 +16,7 @@ import ( "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" "git.grassecon.net/urdt/ussd/internal/models" + "git.grassecon.net/urdt/ussd/internal/storage" "git.grassecon.net/urdt/ussd/internal/testutil/mocks" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" @@ -26,6 +27,7 @@ import ( testdataloader "github.com/peteole/testdata-loader" "github.com/stretchr/testify/require" + memdb "git.defalsify.org/vise.git/db/mem" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" ) @@ -2021,19 +2023,24 @@ func TestSetDefaultVoucher(t *testing.T) { func TestCheckVouchers(t *testing.T) { mockDataStore := new(mocks.MockUserDataStore) mockAccountService := new(mocks.MockAccountService) - mockSubPrefixDb := new(mocks.MockSubPrefixDb) sessionId := "session123" publicKey := "0X13242618721" + ctx := context.WithValue(context.Background(), "SessionId", sessionId) + + db := memdb.NewMemDb() + err := db.Connect(ctx, "") + if err != nil { + t.Fatal(err) + } + spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) h := &Handlers{ userdataStore: mockDataStore, accountService: mockAccountService, - prefixDb: mockSubPrefixDb, + prefixDb: spdb, } - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) mockVouchersResponse := &models.VoucherHoldingResponse{} @@ -2042,38 +2049,53 @@ func TestCheckVouchers(t *testing.T) { {ContractAddress: "0x41c188d63Qa", TokenSymbol: "MILO", TokenDecimals: "4", Balance: "200"}, } + expectedSym := []byte("1:SRF\n2:MILO") + mockAccountService.On("FetchVouchers", string(publicKey)).Return(mockVouchersResponse, nil) - mockSubPrefixDb.On("Put", ctx, []byte("sym"), []byte("1:SRF\n2:MILO")).Return(nil) - mockSubPrefixDb.On("Put", ctx, []byte("bal"), []byte("1:100\n2:200")).Return(nil) - mockSubPrefixDb.On("Put", ctx, []byte("deci"), []byte("1:6\n2:4")).Return(nil) - mockSubPrefixDb.On("Put", ctx, []byte("addr"), []byte("1:0xd4c288865Ce\n2:0x41c188d63Qa")).Return(nil) - - _, err := h.CheckVouchers(ctx, "check_vouchers", []byte("")) - + _, err = h.CheckVouchers(ctx, "check_vouchers", []byte("")) assert.NoError(t, err) + // Read voucher sym data from the store + voucherData, err := spdb.Get(ctx, []byte("sym")) + if err != nil { + t.Fatal(err) + } + + // assert that the data is stored correctly + assert.Equal(t, expectedSym, voucherData) + mockDataStore.AssertExpectations(t) mockAccountService.AssertExpectations(t) } func TestGetVoucherList(t *testing.T) { - mockSubPrefixDb := new(mocks.MockSubPrefixDb) - sessionId := "session123" ctx := context.WithValue(context.Background(), "SessionId", sessionId) + db := memdb.NewMemDb() + err := db.Connect(ctx, "") + if err != nil { + t.Fatal(err) + } + spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) + h := &Handlers{ - prefixDb: mockSubPrefixDb, + prefixDb: spdb, } - mockSubPrefixDb.On("Get", ctx, []byte("sym")).Return([]byte("1:SRF\n2:MILO"), nil) + expectedSym := []byte("1:SRF\n2:MILO") + + // Put voucher sym data from the store + err = spdb.Put(ctx, []byte("sym"), expectedSym) + if err != nil { + t.Fatal(err) + } res, err := h.GetVoucherList(ctx, "", []byte("")) - assert.NoError(t, err) - assert.Contains(t, res.Content, "1:SRF\n2:MILO") - mockSubPrefixDb.AssertExpectations(t) + assert.NoError(t, err) + assert.Equal(t, res.Content, string(expectedSym)) } func TestViewVoucher(t *testing.T) { @@ -2082,27 +2104,37 @@ func TestViewVoucher(t *testing.T) { t.Logf(err.Error()) } mockDataStore := new(mocks.MockUserDataStore) - mockSubPrefixDb := new(mocks.MockSubPrefixDb) sessionId := "session123" ctx := context.WithValue(context.Background(), "SessionId", sessionId) + db := memdb.NewMemDb() + err = db.Connect(ctx, "") + if err != nil { + t.Fatal(err) + } + spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) + h := &Handlers{ userdataStore: mockDataStore, flagManager: fm.parser, - prefixDb: mockSubPrefixDb, + prefixDb: spdb, } // Define mock voucher data - mockVoucherData := map[string]string{ - "sym": "1:SRF", - "bal": "1:100", - "deci": "1:6", - "addr": "1:0xd4c288865Ce", + mockData := map[string][]byte{ + "sym": []byte("1:SRF\n2:MILO"), + "bal": []byte("1:100\n2:200"), + "deci": []byte("1:6\n2:4"), + "addr": []byte("1:0xd4c288865Ce\n2:0x41c188d63Qa"), } - for key, value := range mockVoucherData { - mockSubPrefixDb.On("Get", ctx, []byte(key)).Return([]byte(value), nil) + // Put the data + for key, value := range mockData { + err = spdb.Put(ctx, []byte(key), []byte(value)) + if err != nil { + t.Fatal(err) + } } // Set up expectations for mockDataStore @@ -2115,7 +2147,6 @@ func TestViewVoucher(t *testing.T) { assert.Contains(t, res.Content, "SRF\n100") mockDataStore.AssertExpectations(t) - mockSubPrefixDb.AssertExpectations(t) } func TestSetVoucher(t *testing.T) { diff --git a/internal/testutil/mocks/subprefixdbmock.go b/internal/testutil/mocks/subprefixdbmock.go deleted file mode 100644 index e98bcb6..0000000 --- a/internal/testutil/mocks/subprefixdbmock.go +++ /dev/null @@ -1,21 +0,0 @@ -package mocks - -import ( - "context" - - "github.com/stretchr/testify/mock" -) - -type MockSubPrefixDb struct { - mock.Mock -} - -func (m *MockSubPrefixDb) Get(ctx context.Context, key []byte) ([]byte, error) { - args := m.Called(ctx, key) - return args.Get(0).([]byte), args.Error(1) -} - -func (m *MockSubPrefixDb) Put(ctx context.Context, key, val []byte) error { - args := m.Called(ctx, key, val) - return args.Error(0) -} From c52f8312e4641cb684cf9c206b91b89b5617a2ff Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Sat, 2 Nov 2024 03:21:38 +0300 Subject: [PATCH 15/28] Remove the dbmock and userdbmock --- internal/testutil/mocks/dbmock.go | 59 --------------------------- internal/testutil/mocks/userdbmock.go | 24 ----------- 2 files changed, 83 deletions(-) delete mode 100644 internal/testutil/mocks/dbmock.go delete mode 100644 internal/testutil/mocks/userdbmock.go diff --git a/internal/testutil/mocks/dbmock.go b/internal/testutil/mocks/dbmock.go deleted file mode 100644 index 0b40eab..0000000 --- a/internal/testutil/mocks/dbmock.go +++ /dev/null @@ -1,59 +0,0 @@ -package mocks - -import ( - "context" - - "git.defalsify.org/vise.git/lang" - "github.com/stretchr/testify/mock" -) - -type MockDb struct { - mock.Mock -} - -func (m *MockDb) SetPrefix(prefix uint8) { - m.Called(prefix) -} - -func (m *MockDb) Prefix() uint8 { - args := m.Called() - return args.Get(0).(uint8) -} - -func (m *MockDb) Safe() bool { - args := m.Called() - return args.Get(0).(bool) -} - -func (m *MockDb) SetLanguage(language *lang.Language) { - m.Called(language) -} - -func (m *MockDb) SetLock(uint8, bool) error { - args := m.Called() - return args.Error(0) -} - -func (m *MockDb) Connect(ctx context.Context, connectionStr string) error { - args := m.Called(ctx, connectionStr) - return args.Error(0) -} - -func (m *MockDb) SetSession(sessionId string) { - m.Called(sessionId) -} - -func (m *MockDb) Put(ctx context.Context, key, value []byte) error { - args := m.Called(ctx, key, value) - return args.Error(0) -} - -func (m *MockDb) Get(ctx context.Context, key []byte) ([]byte, error) { - args := m.Called(ctx, key) - return nil, args.Error(0) -} - -func (m *MockDb) Close() error { - args := m.Called(nil) - return args.Error(0) -} diff --git a/internal/testutil/mocks/userdbmock.go b/internal/testutil/mocks/userdbmock.go deleted file mode 100644 index ff3f18d..0000000 --- a/internal/testutil/mocks/userdbmock.go +++ /dev/null @@ -1,24 +0,0 @@ -package mocks - -import ( - "context" - - "git.defalsify.org/vise.git/db" - "git.grassecon.net/urdt/ussd/internal/utils" - "github.com/stretchr/testify/mock" -) - -type MockUserDataStore struct { - db.Db - mock.Mock -} - -func (m *MockUserDataStore) ReadEntry(ctx context.Context, sessionId string, typ utils.DataTyp) ([]byte, error) { - args := m.Called(ctx, sessionId, typ) - return args.Get(0).([]byte), args.Error(1) -} - -func (m *MockUserDataStore) WriteEntry(ctx context.Context, sessionId string, typ utils.DataTyp, value []byte) error { - args := m.Called(ctx, sessionId, typ, value) - return args.Error(0) -} From 476a69fe1b7fcd67728a9eaf5f5526b4010d4a1e Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Sat, 2 Nov 2024 03:22:33 +0300 Subject: [PATCH 16/28] Update menuhandler tests to use the memdb instead of dbmocks --- internal/handlers/ussd/menuhandler_test.go | 1185 +++++++++----------- 1 file changed, 510 insertions(+), 675 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 6f70108..48eb81a 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -7,10 +7,7 @@ import ( "log" "path" "testing" - "time" - "git.defalsify.org/vise.git/asm" - "git.defalsify.org/vise.git/db" "git.defalsify.org/vise.git/lang" "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" @@ -20,7 +17,6 @@ import ( "git.grassecon.net/urdt/ussd/internal/testutil/mocks" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" - "git.grassecon.net/urdt/ussd/common" "git.grassecon.net/urdt/ussd/internal/utils" "github.com/alecthomas/assert/v2" "github.com/grassrootseconomics/eth-custodial/pkg/api" @@ -36,15 +32,46 @@ var ( flagsPath = path.Join(baseDir, "services", "registration", "pp.csv") ) +// InitializeTestStore sets up and returns an in-memory database and store. +func InitializeTestStore(t *testing.T) (context.Context, *utils.UserDataStore) { + ctx := context.Background() + + // Initialize memDb + db := memdb.NewMemDb() + err := db.Connect(ctx, "") + require.NoError(t, err, "Failed to connect to memDb") + + // Create UserDataStore with memDb + store := &utils.UserDataStore{Db: db} + + t.Cleanup(func() { + db.Close() // Ensure the DB is closed after each test + }) + + return ctx, store +} + +func InitializeTestSubPrefixDb(t *testing.T, ctx context.Context) *storage.SubPrefixDb { + db := memdb.NewMemDb() + err := db.Connect(ctx, "") + if err != nil { + t.Fatal(err) + } + spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) + + return spdb +} + func TestNewHandlers(t *testing.T) { + _, store := InitializeTestStore(t) + fm, err := NewFlagManager(flagsPath) accountService := testservice.TestAccountService{} if err != nil { t.Logf(err.Error()) } t.Run("Valid UserDataStore", func(t *testing.T) { - mockStore := &mocks.MockUserDataStore{} - handlers, err := NewHandlers(fm.parser, mockStore, &accountService) + handlers, err := NewHandlers(fm.parser, store, &accountService) if err != nil { t.Fatalf("expected no error, got %v", err) } @@ -58,10 +85,7 @@ func TestNewHandlers(t *testing.T) { // Test case for nil userdataStore t.Run("Nil UserDataStore", func(t *testing.T) { - appFlags := &asm.FlagParser{} - - handlers, err := NewHandlers(appFlags, nil, &accountService) - + handlers, err := NewHandlers(fm.parser, nil, &accountService) if err == nil { t.Fatal("expected an error, got none") } @@ -75,19 +99,19 @@ func TestNewHandlers(t *testing.T) { } func TestCreateAccount(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, err := NewFlagManager(flagsPath) if err != nil { t.Logf(err.Error()) } - // Create required mocks + flag_account_created, err := fm.GetFlag("flag_account_created") if err != nil { t.Logf(err.Error()) } - // Define session ID and mock data - sessionId := "session123" - notFoundErr := db.ErrNotFound{} - ctx := context.WithValue(context.Background(), "SessionId", sessionId) tests := []struct { name string @@ -111,47 +135,24 @@ func TestCreateAccount(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + mockAccountService := new(mocks.MockAccountService) - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) - - // Create a Handlers instance with the mock data store h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, } - publicKey := tt.serverResponse.Result["publicKey"].(string) - data := map[utils.DataTyp]string{ - utils.DATA_TRACKING_ID: tt.serverResponse.Result["trackingId"].(string), - utils.DATA_PUBLIC_KEY: publicKey, - } - - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACCOUNT_CREATED).Return([]byte(""), notFoundErr) - mockCreateAccountService.On("CreateAccount").Return(tt.serverResponse, nil) - - for key, value := range data { - mockDataStore.On("WriteEntry", ctx, sessionId, key, []byte(value)).Return(nil) - } - publicKeyNormalized, err := common.NormalizeHex(publicKey) - if err != nil { - t.Fatal(err) - } - - mockDataStore.On("WriteEntry", ctx, publicKeyNormalized, utils.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId)).Return(nil) + mockAccountService.On("CreateAccount").Return(tt.serverResponse, nil) // Call the method you want to test - res, err := h.CreateAccount(ctx, "create_account", []byte("some-input")) + res, err := h.CreateAccount(ctx, "create_account", []byte("")) // Assert that no errors occurred assert.NoError(t, err) // Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) }) } } @@ -176,23 +177,28 @@ func TestWithPersister_PanicWhenAlreadySet(t *testing.T) { } func TestSaveFirstname(t *testing.T) { - // Create new mocks - mockStore := new(mocks.MockUserDataStore) - mockState := state.NewState(16) + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) - fm, err := NewFlagManager(flagsPath) + flag_allow_update, _ := fm.GetFlag("flag_allow_update") + + // Set the flag in the State + mockState := state.NewState(16) + mockState.SetFlag(flag_allow_update) // Define test data - sessionId := "session123" firstName := "John" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(firstName)).Return(nil) + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(firstName)); err != nil { + t.Fatal(err) + } // Create the Handlers instance with the mock store h := &Handlers{ - userdataStore: mockStore, + userdataStore: store, flagManager: fm.parser, st: mockState, } @@ -204,28 +210,34 @@ func TestSaveFirstname(t *testing.T) { assert.NoError(t, err) assert.Equal(t, resource.Result{}, res) - // Assert all expectations were met - mockStore.AssertExpectations(t) + // Verify that the DATA_FIRST_NAME entry has been updated with the temporary value + storedFirstName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_FIRST_NAME) + assert.Equal(t, firstName, string(storedFirstName)) } func TestSaveFamilyname(t *testing.T) { - // Create a new instance of UserDataStore - mockStore := new(mocks.MockUserDataStore) - mockState := state.NewState(16) + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) - fm, err := NewFlagManager(flagsPath) + flag_allow_update, _ := fm.GetFlag("flag_allow_update") + + // Set the flag in the State + mockState := state.NewState(16) + mockState.SetFlag(flag_allow_update) // Define test data - sessionId := "session123" familyName := "Doeee" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(familyName)).Return(nil) + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(familyName)); err != nil { + t.Fatal(err) + } // Create the Handlers instance with the mock store h := &Handlers{ - userdataStore: mockStore, + userdataStore: store, st: mockState, flagManager: fm.parser, } @@ -237,25 +249,213 @@ func TestSaveFamilyname(t *testing.T) { assert.NoError(t, err) assert.Equal(t, resource.Result{}, res) - // Assert all expectations were met - mockStore.AssertExpectations(t) + // Verify that the DATA_FAMILY_NAME entry has been updated with the temporary value + storedFamilyName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_FAMILY_NAME) + assert.Equal(t, familyName, string(storedFamilyName)) +} + +func TestSaveYoB(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) + + flag_allow_update, _ := fm.GetFlag("flag_allow_update") + + // Set the flag in the State + mockState := state.NewState(16) + mockState.SetFlag(flag_allow_update) + + // Define test data + yob := "1980" + + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)); err != nil { + t.Fatal(err) + } + + // Create the Handlers instance with the mock store + h := &Handlers{ + userdataStore: store, + flagManager: fm.parser, + st: mockState, + } + + // Call the method + res, err := h.SaveYob(ctx, "save_yob", []byte(yob)) + + // Assert results + assert.NoError(t, err) + assert.Equal(t, resource.Result{}, res) + + // Verify that the DATA_YOB entry has been updated with the temporary value + storedYob, _ := store.ReadEntry(ctx, sessionId, utils.DATA_YOB) + assert.Equal(t, yob, string(storedYob)) +} + +func TestSaveLocation(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) + + flag_allow_update, _ := fm.GetFlag("flag_allow_update") + + // Set the flag in the State + mockState := state.NewState(16) + mockState.SetFlag(flag_allow_update) + + // Define test data + location := "Kilifi" + + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(location)); err != nil { + t.Fatal(err) + } + + // Create the Handlers instance with the mock store + h := &Handlers{ + userdataStore: store, + flagManager: fm.parser, + st: mockState, + } + + // Call the method + res, err := h.SaveLocation(ctx, "save_location", []byte(location)) + + // Assert results + assert.NoError(t, err) + assert.Equal(t, resource.Result{}, res) + + // Verify that the DATA_LOCATION entry has been updated with the temporary value + storedLocation, _ := store.ReadEntry(ctx, sessionId, utils.DATA_LOCATION) + assert.Equal(t, location, string(storedLocation)) +} + +func TestSaveOfferings(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) + + flag_allow_update, _ := fm.GetFlag("flag_allow_update") + + // Set the flag in the State + mockState := state.NewState(16) + mockState.SetFlag(flag_allow_update) + + // Define test data + offerings := "Bananas" + + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(offerings)); err != nil { + t.Fatal(err) + } + + // Create the Handlers instance with the mock store + h := &Handlers{ + userdataStore: store, + flagManager: fm.parser, + st: mockState, + } + + // Call the method + res, err := h.SaveOfferings(ctx, "save_offerings", []byte(offerings)) + + // Assert results + assert.NoError(t, err) + assert.Equal(t, resource.Result{}, res) + + // Verify that the DATA_OFFERINGS entry has been updated with the temporary value + storedOfferings, _ := store.ReadEntry(ctx, sessionId, utils.DATA_OFFERINGS) + assert.Equal(t, offerings, string(storedOfferings)) +} + +func TestSaveGender(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) + + flag_allow_update, _ := fm.GetFlag("flag_allow_update") + + // Set the flag in the State + mockState := state.NewState(16) + mockState.SetFlag(flag_allow_update) + + // Define test cases + tests := []struct { + name string + input []byte + expectedGender string + executingSymbol string + }{ + { + name: "Valid Male Input", + input: []byte("1"), + expectedGender: "male", + executingSymbol: "set_male", + }, + { + name: "Valid Female Input", + input: []byte("2"), + expectedGender: "female", + executingSymbol: "set_female", + }, + { + name: "Valid Unspecified Input", + input: []byte("3"), + executingSymbol: "set_unspecified", + expectedGender: "unspecified", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)); err != nil { + t.Fatal(err) + } + + mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol) + // Create the Handlers instance with the mock store + h := &Handlers{ + userdataStore: store, + st: mockState, + flagManager: fm.parser, + } + + // Call the method + res, err := h.SaveGender(ctx, "save_gender", tt.input) + + // Assert results + assert.NoError(t, err) + assert.Equal(t, resource.Result{}, res) + + // Verify that the DATA_GENDER entry has been updated with the temporary value + storedGender, _ := store.ReadEntry(ctx, sessionId, utils.DATA_GENDER) + assert.Equal(t, tt.expectedGender, string(storedGender)) + }) + } } func TestSaveTemporaryPin(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, err := NewFlagManager(flagsPath) - mockStore := new(mocks.MockUserDataStore) if err != nil { log.Fatal(err) } + flag_incorrect_pin, _ := fm.parser.GetFlag("flag_incorrect_pin") // Create the Handlers instance with the mock flag manager h := &Handlers{ flagManager: fm.parser, - userdataStore: mockStore, + userdataStore: store, } - sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Define test cases tests := []struct { @@ -281,10 +481,6 @@ func TestSaveTemporaryPin(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - - // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.input)).Return(nil) - // Call the method res, err := h.SaveTemporaryPin(ctx, "save_pin", tt.input) @@ -293,205 +489,27 @@ func TestSaveTemporaryPin(t *testing.T) { } // Assert that the Result FlagSet has the required flags after language switch - assert.Equal(t, res, tt.expectedResult, "Flags should be equal to account created") - - }) - } -} - -func TestSaveYoB(t *testing.T) { - // Create new instances - mockStore := new(mocks.MockUserDataStore) - mockState := state.NewState(16) - - fm, err := NewFlagManager(flagsPath) - - // Define test data - sessionId := "session123" - yob := "1980" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) - - // Create the Handlers instance with the mock store - h := &Handlers{ - userdataStore: mockStore, - st: mockState, - flagManager: fm.parser, - } - - // Call the method - res, err := h.SaveYob(ctx, "save_yob", []byte(yob)) - - // Assert results - assert.NoError(t, err) - assert.Equal(t, resource.Result{}, res) - - // Assert all expectations were met - mockStore.AssertExpectations(t) -} - -func TestSaveLocation(t *testing.T) { - // Create a new instance of MockMyDataStore - mockStore := new(mocks.MockUserDataStore) - mockState := state.NewState(16) - - fm, err := NewFlagManager(flagsPath) - - // Define test data - sessionId := "session123" - yob := "Kilifi" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) - - // Create the Handlers instance with the mock store - h := &Handlers{ - userdataStore: mockStore, - st: mockState, - flagManager: fm.parser, - } - - // Call the method - res, err := h.SaveLocation(ctx, "save_location", []byte(yob)) - - // Assert results - assert.NoError(t, err) - assert.Equal(t, resource.Result{}, res) - - // Assert all expectations were met - mockStore.AssertExpectations(t) -} - -func TestSaveOfferings(t *testing.T) { - // Create a new instance of MockUserDataStore - mockStore := new(mocks.MockUserDataStore) - mockState := state.NewState(16) - - fm, err := NewFlagManager(flagsPath) - - // Define test data - sessionId := "session123" - offerings := "Bananas" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(offerings)).Return(nil) - - // Create the Handlers instance with the mock store - h := &Handlers{ - userdataStore: mockStore, - st: mockState, - flagManager: fm.parser, - } - - // Call the method - res, err := h.SaveOfferings(ctx, "save_offerings", []byte(offerings)) - - // Assert results - assert.NoError(t, err) - assert.Equal(t, resource.Result{}, res) - - // Assert all expectations were met - mockStore.AssertExpectations(t) -} - -func TestSaveGender(t *testing.T) { - // Create a new mock instances - mockStore := new(mocks.MockUserDataStore) - mockState := state.NewState(16) - - fm, _ := NewFlagManager(flagsPath) - - // Define the session ID and context - sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - // Define test cases - tests := []struct { - name string - input []byte - expectedGender string - expectCall bool - executingSymbol string - }{ - { - name: "Valid Male Input", - input: []byte("1"), - expectedGender: "male", - executingSymbol: "set_male", - expectCall: true, - }, - { - name: "Valid Female Input", - input: []byte("2"), - expectedGender: "female", - executingSymbol: "set_female", - expectCall: true, - }, - { - name: "Valid Unspecified Input", - input: []byte("3"), - executingSymbol: "set_unspecified", - expectedGender: "unspecified", - expectCall: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Set up expectations for the mock database - if tt.expectCall { - expectedKey := utils.DATA_TEMPORARY_VALUE - mockStore.On("WriteEntry", ctx, sessionId, expectedKey, []byte(tt.expectedGender)).Return(nil) - } else { - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)).Return(nil) - } - mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol) - // Create the Handlers instance with the mock store - h := &Handlers{ - userdataStore: mockStore, - st: mockState, - flagManager: fm.parser, - } - - // Call the method - _, err := h.SaveGender(ctx, "save_gender", tt.input) - - // Assert no error - assert.NoError(t, err) - - // Verify expectations - if tt.expectCall { - mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) - } else { - mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) - } + assert.Equal(t, res, tt.expectedResult, "Result should match expected result") }) } } func TestCheckIdentifier(t *testing.T) { - // Create a new instance of MockMyDataStore - mockStore := new(mocks.MockUserDataStore) - - // Define the session ID and context sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) // Define test cases tests := []struct { name string - mockPublicKey []byte + publicKey []byte mockErr error expectedContent string expectError bool }{ { name: "Saved public Key", - mockPublicKey: []byte("0xa8363"), + publicKey: []byte("0xa8363"), mockErr: nil, expectedContent: "0xa8363", expectError: false, @@ -500,39 +518,33 @@ func TestCheckIdentifier(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Set up expectations for the mock database - mockStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return(tt.mockPublicKey, tt.mockErr) + err := store.WriteEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY, []byte(tt.publicKey)) + if err != nil { + t.Fatal(err) + } // Create the Handlers instance with the mock store h := &Handlers{ - userdataStore: mockStore, + userdataStore: store, } // Call the method res, err := h.CheckIdentifier(ctx, "check_identifier", nil) // Assert results - assert.NoError(t, err) assert.Equal(t, tt.expectedContent, res.Content) - - // Verify expectations - mockStore.AssertExpectations(t) }) } } func TestGetSender(t *testing.T) { - mockStore := new(mocks.MockUserDataStore) + sessionId := "session123" + ctx, _ := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) - // Define test data - sessionId := "254712345678" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - // Create the Handlers instance with the mock store - h := &Handlers{ - userdataStore: mockStore, - } + // Create the Handlers instance + h := &Handlers{} // Call the method res, _ := h.GetSender(ctx, "get_sender", []byte("")) @@ -542,21 +554,27 @@ func TestGetSender(t *testing.T) { } func TestGetAmount(t *testing.T) { - mockDataStore := new(mocks.MockUserDataStore) + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) // Define test data - sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) amount := "0.03" activeSym := "SRF" - // Set up the expected behavior of the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM).Return([]byte(activeSym), nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_AMOUNT).Return([]byte(amount), nil) + err := store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte(amount)) + if err != nil { + t.Fatal(err) + } + + err = store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM, []byte(activeSym)) + if err != nil { + t.Fatal(err) + } // Create the Handlers instance with the mock store h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, } // Call the method @@ -566,31 +584,30 @@ func TestGetAmount(t *testing.T) { //Assert that the retrieved amount is what was set as the content assert.Equal(t, formattedAmount, res.Content) - } func TestGetRecipient(t *testing.T) { - mockStore := new(mocks.MockUserDataStore) - - // Define test data sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + recepient := "0xcasgatweksalw1018221" - // Set up the expected behavior of the mock - mockStore.On("ReadEntry", ctx, sessionId, utils.DATA_RECIPIENT).Return([]byte(recepient), nil) + err := store.WriteEntry(ctx, sessionId, utils.DATA_RECIPIENT, []byte(recepient)) + if err != nil { + t.Fatal(err) + } // Create the Handlers instance with the mock store h := &Handlers{ - userdataStore: mockStore, + userdataStore: store, } // Call the method - res, _ := h.GetRecipient(ctx, "get_recipient", []byte("Getting recipient...")) + res, _ := h.GetRecipient(ctx, "get_recipient", []byte("")) //Assert that the retrieved recepient is what was set as the content assert.Equal(t, recepient, res.Content) - } func TestGetFlag(t *testing.T) { @@ -608,12 +625,11 @@ func TestGetFlag(t *testing.T) { } func TestSetLanguage(t *testing.T) { - // Create a new instance of the Flag Manager fm, err := NewFlagManager(flagsPath) - if err != nil { log.Fatal(err) } + // Define test cases tests := []struct { name string @@ -652,25 +668,24 @@ func TestSetLanguage(t *testing.T) { // Call the method res, err := h.SetLanguage(context.Background(), "set_language", nil) - if err != nil { t.Error(err) } // Assert that the Result FlagSet has the required flags after language switch assert.Equal(t, res, tt.expectedResult, "Result should match expected result") - }) } } + func TestResetAllowUpdate(t *testing.T) { fm, err := NewFlagManager(flagsPath) - - flag_allow_update, _ := fm.parser.GetFlag("flag_allow_update") - if err != nil { log.Fatal(err) } + + flag_allow_update, _ := fm.parser.GetFlag("flag_allow_update") + // Define test cases tests := []struct { name string @@ -688,7 +703,6 @@ func TestResetAllowUpdate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create the Handlers instance with the mock flag manager h := &Handlers{ flagManager: fm.parser, @@ -696,13 +710,12 @@ func TestResetAllowUpdate(t *testing.T) { // Call the method res, err := h.ResetAllowUpdate(context.Background(), "reset_allow update", tt.input) - if err != nil { t.Error(err) } + // Assert that the Result FlagSet has the required flags after language switch assert.Equal(t, res, tt.expectedResult, "Flags should be equal to account created") - }) } } @@ -740,25 +753,24 @@ func TestResetAccountAuthorized(t *testing.T) { // Call the method res, err := h.ResetAccountAuthorized(context.Background(), "reset_account_authorized", tt.input) - if err != nil { t.Error(err) } + // Assert that the Result FlagSet has the required flags after language switch assert.Equal(t, res, tt.expectedResult, "Result should contain flag(s) that have been reset") - }) } } func TestIncorrectPinReset(t *testing.T) { fm, err := NewFlagManager(flagsPath) - - flag_incorrect_pin, _ := fm.parser.GetFlag("flag_incorrect_pin") - if err != nil { log.Fatal(err) } + + flag_incorrect_pin, _ := fm.parser.GetFlag("flag_incorrect_pin") + // Define test cases tests := []struct { name string @@ -776,7 +788,6 @@ func TestIncorrectPinReset(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create the Handlers instance with the mock flag manager h := &Handlers{ flagManager: fm.parser, @@ -784,25 +795,24 @@ func TestIncorrectPinReset(t *testing.T) { // Call the method res, err := h.ResetIncorrectPin(context.Background(), "reset_incorrect_pin", tt.input) - if err != nil { t.Error(err) } + // Assert that the Result FlagSet has the required flags after language switch assert.Equal(t, res, tt.expectedResult, "Result should contain flag(s) that have been reset") - }) } } func TestResetIncorrectYob(t *testing.T) { fm, err := NewFlagManager(flagsPath) - - flag_incorrect_date_format, _ := fm.parser.GetFlag("flag_incorrect_date_format") - if err != nil { log.Fatal(err) } + + flag_incorrect_date_format, _ := fm.parser.GetFlag("flag_incorrect_date_format") + // Define test cases tests := []struct { name string @@ -820,7 +830,6 @@ func TestResetIncorrectYob(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create the Handlers instance with the mock flag manager h := &Handlers{ flagManager: fm.parser, @@ -828,43 +837,39 @@ func TestResetIncorrectYob(t *testing.T) { // Call the method res, err := h.ResetIncorrectYob(context.Background(), "reset_incorrect_yob", tt.input) - if err != nil { t.Error(err) } + // Assert that the Result FlagSet has the required flags after language switch assert.Equal(t, res, tt.expectedResult, "Result should contain flag(s) that have been reset") - }) } } func TestAuthorize(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) fm, err := NewFlagManager(flagsPath) - if err != nil { t.Logf(err.Error()) } // Create required mocks - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) - //expectedResult := resource.Result{} + mockAccountService := new(mocks.MockAccountService) mockState := state.NewState(16) flag_incorrect_pin, _ := fm.GetFlag("flag_incorrect_pin") flag_account_authorized, _ := fm.GetFlag("flag_account_authorized") flag_allow_update, _ := fm.GetFlag("flag_allow_update") - //Assuming 1234 is the correct account pin + + // Set 1234 is the correct account pin accountPIN := "1234" - // Define session ID and mock data - sessionId := "session123" - typ := utils.DATA_ACCOUNT_PIN - h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, st: mockState, } @@ -899,14 +904,13 @@ func TestAuthorize(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create context with session ID ctx := context.WithValue(context.Background(), "SessionId", sessionId) - // Define expected interactions with the mock - mockDataStore.On("ReadEntry", ctx, sessionId, typ).Return([]byte(accountPIN), nil) - - // Create a Handlers instance with the mock data store + err = store.WriteEntry(ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(accountPIN)) + if err != nil { + t.Fatal(err) + } // Call the method under test res, err := h.Authorize(ctx, "authorize", []byte(tt.input)) @@ -916,33 +920,25 @@ func TestAuthorize(t *testing.T) { //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } - } func TestVerifyYob(t *testing.T) { fm, err := NewFlagManager(flagsPath) - if err != nil { t.Logf(err.Error()) } sessionId := "session123" // Create required mocks - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) mockState := state.NewState(16) flag_incorrect_date_format, _ := fm.parser.GetFlag("flag_incorrect_date_format") ctx := context.WithValue(context.Background(), "SessionId", sessionId) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + accountService: mockAccountService, flagManager: fm.parser, st: mockState, } @@ -977,7 +973,6 @@ func TestVerifyYob(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Call the method under test res, err := h.VerifyYob(ctx, "verify_yob", []byte(tt.input)) @@ -986,37 +981,31 @@ func TestVerifyYob(t *testing.T) { //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } } func TestVerifyCreatePin(t *testing.T) { - fm, err := NewFlagManager(flagsPath) + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, err := NewFlagManager(flagsPath) if err != nil { t.Logf(err.Error()) } - sessionId := "session123" // Create required mocks - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) mockState := state.NewState(16) flag_valid_pin, _ := fm.parser.GetFlag("flag_valid_pin") flag_pin_mismatch, _ := fm.parser.GetFlag("flag_pin_mismatch") flag_pin_set, _ := fm.parser.GetFlag("flag_pin_set") - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - //Assuming this was the first set PIN to verify against - firstSetPin := "1234" h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, st: mockState, } @@ -1043,16 +1032,12 @@ func TestVerifyCreatePin(t *testing.T) { }, } - typ := utils.DATA_TEMPORARY_VALUE - for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - - // Define expected interactions with the mock - mockDataStore.On("ReadEntry", ctx, sessionId, typ).Return([]byte(firstSetPin), nil) - - // Set up the expected behavior of the mock - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(firstSetPin)).Return(nil) + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte("1234")) + if err != nil { + t.Fatal(err) + } // Call the method under test res, err := h.VerifyCreatePin(ctx, "verify_create_pin", []byte(tt.input)) @@ -1062,36 +1047,32 @@ func TestVerifyCreatePin(t *testing.T) { //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } } func TestCheckAccountStatus(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, err := NewFlagManager(flagsPath) if err != nil { t.Logf(err.Error()) } - sessionId := "session123" flag_account_success, _ := fm.GetFlag("flag_account_success") flag_account_pending, _ := fm.GetFlag("flag_account_pending") flag_api_error, _ := fm.GetFlag("flag_api_call_error") - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - tests := []struct { name string - input []byte + publicKey []byte serverResponse *api.OKResponse - response *models.TrackStatusResponse expectedResult resource.Result }{ { - name: "Test when account is on the Sarafu network", - input: []byte("TrackingId1234"), + name: "Test when account is on the Sarafu network", + publicKey: []byte("TrackingId1234"), serverResponse: &api.OKResponse{ Ok: true, Description: "Account creation succeeded", @@ -1099,54 +1080,14 @@ func TestCheckAccountStatus(t *testing.T) { "active": true, }, }, - response: &models.TrackStatusResponse{ - Ok: true, - Result: struct { - Transaction struct { - CreatedAt time.Time "json:\"createdAt\"" - Status string "json:\"status\"" - TransferValue json.Number "json:\"transferValue\"" - TxHash string "json:\"txHash\"" - TxType string "json:\"txType\"" - } - }{ - Transaction: models.Transaction{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", - }, - }, - }, expectedResult: resource.Result{ FlagSet: []uint32{flag_account_success}, FlagReset: []uint32{flag_api_error, flag_account_pending}, }, }, { - name: "Test when the account is not yet on the sarafu network", - input: []byte("TrackingId1234"), - response: &models.TrackStatusResponse{ - Ok: true, - Result: struct { - Transaction struct { - CreatedAt time.Time "json:\"createdAt\"" - Status string "json:\"status\"" - TransferValue json.Number "json:\"transferValue\"" - TxHash string "json:\"txHash\"" - TxType string "json:\"txType\"" - } - }{ - Transaction: models.Transaction{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", - }, - }, - }, + name: "Test when the account is not yet on the sarafu network", + publicKey: []byte("TrackingId1234"), serverResponse: &api.OKResponse{ Ok: true, Description: "Account creation succeeded", @@ -1162,59 +1103,51 @@ func TestCheckAccountStatus(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, } - status := tt.response.Result.Transaction.Status - // Define expected interactions with the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return(tt.input, nil) + err = store.WriteEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY, []byte(tt.publicKey)) + if err != nil { + t.Fatal(err) + } - mockCreateAccountService.On("CheckAccountStatus", string(tt.input)).Return(tt.response, nil) - mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_STATUS, []byte(status)).Return(nil).Maybe() + mockAccountService.On("TrackAccountStatus", string(tt.publicKey)).Return(tt.serverResponse, nil) // Call the method under test - res, _ := h.CheckAccountStatus(ctx, "check_account_status", tt.input) + res, _ := h.CheckAccountStatus(ctx, "check_account_status", []byte("")) // Assert that no errors occurred assert.NoError(t, err) //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } - } func TestTransactionReset(t *testing.T) { - fm, err := NewFlagManager(flagsPath) + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, err := NewFlagManager(flagsPath) if err != nil { t.Logf(err.Error()) } + flag_invalid_recipient, _ := fm.GetFlag("flag_invalid_recipient") flag_invalid_recipient_with_invite, _ := fm.GetFlag("flag_invalid_recipient_with_invite") - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) - - sessionId := "session123" - - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, } tests := []struct { @@ -1233,9 +1166,6 @@ func TestTransactionReset(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, []byte("")).Return(nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_RECIPIENT, []byte("")).Return(nil) - // Call the method under test res, _ := h.TransactionReset(ctx, "transaction_reset", tt.input) @@ -1244,40 +1174,32 @@ func TestTransactionReset(t *testing.T) { //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } } -func TestResetInvalidAmount(t *testing.T) { +func TestResetTransactionAmount(t *testing.T) { sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) fm, err := NewFlagManager(flagsPath) - if err != nil { t.Logf(err.Error()) } flag_invalid_amount, _ := fm.parser.GetFlag("flag_invalid_amount") - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, } tests := []struct { name string - input []byte - status string expectedResult resource.Result }{ { @@ -1289,43 +1211,34 @@ func TestResetInvalidAmount(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, []byte("")).Return(nil) - // Call the method under test - res, _ := h.ResetTransactionAmount(ctx, "transaction_reset_amount", tt.input) + res, _ := h.ResetTransactionAmount(ctx, "transaction_reset_amount", []byte("")) // Assert that no errors occurred assert.NoError(t, err) //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } - } func TestInitiateTransaction(t *testing.T) { sessionId := "254712345678" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) fm, err := NewFlagManager(flagsPath) - if err != nil { t.Logf(err.Error()) } - account_authorized_flag, err := fm.parser.GetFlag("flag_account_authorized") + account_authorized_flag, _ := fm.parser.GetFlag("flag_account_authorized") - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, } @@ -1351,10 +1264,18 @@ func TestInitiateTransaction(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Define expected interactions with the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_AMOUNT).Return(tt.Amount, nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_RECIPIENT).Return(tt.Recipient, nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM).Return(tt.ActiveSym, nil) + err := store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte(tt.Amount)) + if err != nil { + t.Fatal(err) + } + err = store.WriteEntry(ctx, sessionId, utils.DATA_RECIPIENT, []byte(tt.Recipient)) + if err != nil { + t.Fatal(err) + } + err = store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM, []byte(tt.ActiveSym)) + if err != nil { + t.Fatal(err) + } // Call the method under test res, _ := h.InitiateTransaction(ctx, "transaction_reset_amount", tt.input) @@ -1364,31 +1285,25 @@ func TestInitiateTransaction(t *testing.T) { //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) }) } } func TestQuit(t *testing.T) { fm, err := NewFlagManager(flagsPath) - if err != nil { t.Logf(err.Error()) } flag_account_authorized, _ := fm.parser.GetFlag("flag_account_authorized") - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) sessionId := "session123" ctx := context.WithValue(context.Background(), "SessionId", sessionId) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + accountService: mockAccountService, flagManager: fm.parser, } tests := []struct { @@ -1417,13 +1332,10 @@ func TestQuit(t *testing.T) { //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } } + func TestIsValidPIN(t *testing.T) { tests := []struct { name string @@ -1479,21 +1391,22 @@ func TestIsValidPIN(t *testing.T) { func TestValidateAmount(t *testing.T) { fm, err := NewFlagManager(flagsPath) - if err != nil { t.Logf(err.Error()) } - flag_invalid_amount, _ := fm.parser.GetFlag("flag_invalid_amount") - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + flag_invalid_amount, _ := fm.parser.GetFlag("flag_invalid_amount") + + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, } tests := []struct { @@ -1533,11 +1446,10 @@ func TestValidateAmount(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Mock behavior for active balance retrieval - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_BAL).Return(tt.activeBal, nil) - - // Mock behavior for storing the amount (if valid) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, tt.input).Return(nil).Maybe() + err := store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_BAL, []byte(tt.activeBal)) + if err != nil { + t.Fatal(err) + } // Call the method under test res, _ := h.ValidateAmount(ctx, "test_validate_amount", tt.input) @@ -1547,26 +1459,22 @@ func TestValidateAmount(t *testing.T) { // Assert the result matches the expected result assert.Equal(t, tt.expectedResult, res, "Expected result should match actual result") - - // Assert all expectations were met - mockDataStore.AssertExpectations(t) }) } } func TestValidateRecipient(t *testing.T) { fm, err := NewFlagManager(flagsPath) - - flag_invalid_recipient, _ := fm.parser.GetFlag("flag_invalid_recipient") - mockDataStore := new(mocks.MockUserDataStore) - - sessionId := "session123" - - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - if err != nil { log.Fatal(err) } + + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + flag_invalid_recipient, _ := fm.parser.GetFlag("flag_invalid_recipient") + // Define test cases tests := []struct { name string @@ -1590,13 +1498,10 @@ func TestValidateRecipient(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_RECIPIENT, tt.input).Return(nil) - - // Create the Handlers instance with the mock flag manager + // Create the Handlers instance h := &Handlers{ flagManager: fm.parser, - userdataStore: mockDataStore, + userdataStore: store, } // Call the method @@ -1605,14 +1510,16 @@ func TestValidateRecipient(t *testing.T) { if err != nil { t.Error(err) } + // Assert that the Result FlagSet has the required flags after language switch assert.Equal(t, res, tt.expectedResult, "Result should contain flag(s) that have been reset") - }) } } func TestCheckBalance(t *testing.T) { + ctx, store := InitializeTestStore(t) + tests := []struct { name string sessionId string @@ -1624,7 +1531,7 @@ func TestCheckBalance(t *testing.T) { }{ { name: "User with active sym", - sessionId: "session456", + sessionId: "session123", publicKey: "0X98765432109", activeSym: "ETH", activeBal: "1.5", @@ -1635,18 +1542,22 @@ func TestCheckBalance(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore := new(mocks.MockUserDataStore) mockAccountService := new(mocks.MockAccountService) - ctx := context.WithValue(context.Background(), "SessionId", tt.sessionId) + ctx := context.WithValue(ctx, "SessionId", tt.sessionId) h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, accountService: mockAccountService, } - // Mock for user with active sym - mockDataStore.On("ReadEntry", ctx, tt.sessionId, utils.DATA_ACTIVE_SYM).Return([]byte(tt.activeSym), nil) - mockDataStore.On("ReadEntry", ctx, tt.sessionId, utils.DATA_ACTIVE_BAL).Return([]byte(tt.activeBal), nil) + err := store.WriteEntry(ctx, tt.sessionId, utils.DATA_ACTIVE_SYM, []byte(tt.activeSym)) + if err != nil { + t.Fatal(err) + } + err = store.WriteEntry(ctx, tt.sessionId, utils.DATA_ACTIVE_BAL, []byte(tt.activeBal)) + if err != nil { + t.Fatal(err) + } res, err := h.CheckBalance(ctx, "check_balance", []byte("")) @@ -1657,23 +1568,21 @@ func TestCheckBalance(t *testing.T) { assert.Equal(t, tt.expectedResult, res, "Result should match expected output") } - mockDataStore.AssertExpectations(t) mockAccountService.AssertExpectations(t) }) } } func TestGetProfile(t *testing.T) { - sessionId := "session123" + ctx, store := InitializeTestStore(t) - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) mockState := state.NewState(16) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, st: mockState, } @@ -1697,7 +1606,7 @@ func TestGetProfile(t *testing.T) { }, }, { - name: "Test with with profile information in swa ", + name: "Test with with profile information in swa", keys: []utils.DataTyp{utils.DATA_FAMILY_NAME, utils.DATA_FIRST_NAME, utils.DATA_GENDER, utils.DATA_OFFERINGS, utils.DATA_LOCATION, utils.DATA_YOB}, profileInfo: []string{"Doee", "John", "Male", "Bananas", "Kilifi", "1976"}, languageCode: "swa", @@ -1723,22 +1632,21 @@ func TestGetProfile(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "Language", lang.Language{ Code: tt.languageCode, }) for index, key := range tt.keys { - mockDataStore.On("ReadEntry", ctx, sessionId, key).Return([]byte(tt.profileInfo[index]), nil).Maybe() + err := store.WriteEntry(ctx, sessionId, key, []byte(tt.profileInfo[index])) + if err != nil { + t.Fatal(err) + } } res, _ := h.GetProfileInfo(ctx, "get_profile_info", []byte("")) - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - //Assert that the result set to content is what was expected assert.Equal(t, res, tt.result, "Result should contain profile information served back to user") - }) } } @@ -1749,12 +1657,10 @@ func TestVerifyNewPin(t *testing.T) { fm, _ := NewFlagManager(flagsPath) flag_valid_pin, _ := fm.parser.GetFlag("flag_valid_pin") - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, flagManager: fm.parser, - accountService: mockCreateAccountService, + accountService: mockAccountService, } ctx := context.WithValue(context.Background(), "SessionId", sessionId) @@ -1777,44 +1683,32 @@ func TestVerifyNewPin(t *testing.T) { FlagReset: []uint32{flag_valid_pin}, }, }, - { - name: "Test with invalid pin", - input: []byte("12345"), - expectedResult: resource.Result{ - FlagReset: []uint32{flag_valid_pin}, - }, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - //Call the function under test res, _ := h.VerifyNewPin(ctx, "verify_new_pin", tt.input) - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - //Assert that the result set to content is what was expected assert.Equal(t, res, tt.expectedResult, "Result should contain flags set according to user input") - }) } - } func TestConfirmPin(t *testing.T) { sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, _ := NewFlagManager(flagsPath) flag_pin_mismatch, _ := fm.parser.GetFlag("flag_pin_mismatch") - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, flagManager: fm.parser, - accountService: mockCreateAccountService, + accountService: mockAccountService, } - ctx := context.WithValue(context.Background(), "SessionId", sessionId) tests := []struct { name string @@ -1834,16 +1728,14 @@ func TestConfirmPin(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Set up the expected behavior of the mock - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(tt.temporarypin)).Return(nil) - - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE).Return(tt.temporarypin, nil) + err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.temporarypin)) + if err != nil { + t.Fatal(err) + } //Call the function under test res, _ := h.ConfirmPinChange(ctx, "confirm_pin_change", tt.temporarypin) - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - //Assert that the result set to content is what was expected assert.Equal(t, res, tt.expectedResult, "Result should contain flags set according to user input") @@ -1861,7 +1753,14 @@ func TestFetchCustodialBalances(t *testing.T) { // Define test data sessionId := "session123" publicKey := "0X13242618721" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + err = store.WriteEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY, []byte(publicKey)) + if err != nil { + t.Fatal(err) + } tests := []struct { name string @@ -1903,50 +1802,39 @@ func TestFetchCustodialBalances(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) mockState := state.NewState(16) - // Create the Handlers instance with the mock store h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, flagManager: fm.parser, st: mockState, - accountService: mockCreateAccountService, + accountService: mockAccountService, } // Set up the expected behavior of the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) - mockCreateAccountService.On("CheckBalance", string(publicKey)).Return(tt.balanceResonse, nil) + mockAccountService.On("CheckBalance", string(publicKey)).Return(tt.balanceResonse, nil) // Call the method res, _ := h.FetchCustodialBalances(ctx, "fetch_custodial_balances", []byte("")) - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - //Assert that the result set to content is what was expected - assert.Equal(t, res, tt.expectedResult, "Result should contain flags set according to user input") - + assert.Equal(t, res, tt.expectedResult, "Result should match expected result") }) } } func TestSetDefaultVoucher(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, err := NewFlagManager(flagsPath) if err != nil { t.Logf(err.Error()) } - flag_no_active_voucher, err := fm.GetFlag("flag_no_active_voucher") - if err != nil { - t.Logf(err.Error()) - } - // Define session ID and mock data - sessionId := "session123" + publicKey := "0X13242618721" - notFoundErr := db.ErrNotFound{} - ctx := context.WithValue(context.Background(), "SessionId", sessionId) tests := []struct { name string @@ -1954,7 +1842,7 @@ func TestSetDefaultVoucher(t *testing.T) { expectedResult resource.Result }{ { - name: "Test set default voucher when no active voucher exists", + name: "Test set default voucher when no active voucher is set", vouchersResp: &models.VoucherHoldingResponse{ Ok: true, Description: "Vouchers fetched successfully", @@ -1971,77 +1859,55 @@ func TestSetDefaultVoucher(t *testing.T) { }, expectedResult: resource.Result{}, }, - { - name: "Test no vouchers available", - vouchersResp: &models.VoucherHoldingResponse{ - Ok: true, - Description: "No vouchers available", - Result: models.VoucherResult{ - Holdings: []dataserviceapi.TokenHoldings{}, - }, - }, - expectedResult: resource.Result{ - FlagSet: []uint32{flag_no_active_voucher}, - }, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore := new(mocks.MockUserDataStore) mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, accountService: mockAccountService, flagManager: fm.parser, } - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM).Return([]byte(""), notFoundErr) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) + err := store.WriteEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY, []byte(publicKey)) + if err != nil { + t.Fatal(err) + } mockAccountService.On("FetchVouchers", string(publicKey)).Return(tt.vouchersResp, nil) - if len(tt.vouchersResp.Result.Holdings) > 0 { - firstVoucher := tt.vouchersResp.Result.Holdings[0] - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM, []byte(firstVoucher.TokenSymbol)).Return(nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACTIVE_BAL, []byte(firstVoucher.Balance)).Return(nil) - } - - res, err := h.SetDefaultVoucher(ctx, "set_default_voucher", []byte("some-input")) + res, err := h.SetDefaultVoucher(ctx, "set_default_voucher", []byte("")) assert.NoError(t, err) assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - mockDataStore.AssertExpectations(t) mockAccountService.AssertExpectations(t) }) } } func TestCheckVouchers(t *testing.T) { - mockDataStore := new(mocks.MockUserDataStore) mockAccountService := new(mocks.MockAccountService) - sessionId := "session123" publicKey := "0X13242618721" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - db := memdb.NewMemDb() - err := db.Connect(ctx, "") - if err != nil { - t.Fatal(err) - } - spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + spdb := InitializeTestSubPrefixDb(t, ctx) h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, accountService: mockAccountService, prefixDb: spdb, } - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) + err := store.WriteEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY, []byte(publicKey)) + if err != nil { + t.Fatal(err) + } mockVouchersResponse := &models.VoucherHoldingResponse{} mockVouchersResponse.Result.Holdings = []dataserviceapi.TokenHoldings{ @@ -2065,7 +1931,6 @@ func TestCheckVouchers(t *testing.T) { // assert that the data is stored correctly assert.Equal(t, expectedSym, voucherData) - mockDataStore.AssertExpectations(t) mockAccountService.AssertExpectations(t) } @@ -2073,12 +1938,7 @@ func TestGetVoucherList(t *testing.T) { sessionId := "session123" ctx := context.WithValue(context.Background(), "SessionId", sessionId) - db := memdb.NewMemDb() - err := db.Connect(ctx, "") - if err != nil { - t.Fatal(err) - } - spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) + spdb := InitializeTestSubPrefixDb(t, ctx) h := &Handlers{ prefixDb: spdb, @@ -2087,7 +1947,7 @@ func TestGetVoucherList(t *testing.T) { expectedSym := []byte("1:SRF\n2:MILO") // Put voucher sym data from the store - err = spdb.Put(ctx, []byte("sym"), expectedSym) + err := spdb.Put(ctx, []byte("sym"), expectedSym) if err != nil { t.Fatal(err) } @@ -2103,20 +1963,15 @@ func TestViewVoucher(t *testing.T) { if err != nil { t.Logf(err.Error()) } - mockDataStore := new(mocks.MockUserDataStore) - + ctx, store := InitializeTestStore(t) sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - db := memdb.NewMemDb() - err = db.Connect(ctx, "") - if err != nil { - t.Fatal(err) - } - spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + spdb := InitializeTestSubPrefixDb(t, ctx) h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, flagManager: fm.parser, prefixDb: spdb, } @@ -2137,23 +1992,20 @@ func TestViewVoucher(t *testing.T) { } } - // Set up expectations for mockDataStore - expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "100", "6", "0xd4c288865Ce") - - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(expectedData)).Return(nil) - res, err := h.ViewVoucher(ctx, "view_voucher", []byte("1")) assert.NoError(t, err) - assert.Contains(t, res.Content, "SRF\n100") - - mockDataStore.AssertExpectations(t) + assert.Equal(t, res.Content, "SRF\n100") } func TestSetVoucher(t *testing.T) { - mockDataStore := new(mocks.MockUserDataStore) - + ctx, store := InitializeTestStore(t) sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + + ctx = context.WithValue(ctx, "SessionId", sessionId) + + h := &Handlers{ + userdataStore: store, + } // Define the temporary voucher data tempData := &dataserviceapi.TokenHoldings{ @@ -2163,33 +2015,16 @@ func TestSetVoucher(t *testing.T) { ContractAddress: "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9", } - expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "200", "6", "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9") + expectedData := fmt.Sprintf("%s,%s,%s,%s", tempData.TokenSymbol, tempData.Balance, tempData.TokenDecimals, tempData.ContractAddress) - // Define the expected active entries - activeEntries := map[utils.DataTyp][]byte{ - utils.DATA_ACTIVE_SYM: []byte(tempData.TokenSymbol), - utils.DATA_ACTIVE_BAL: []byte(tempData.Balance), - utils.DATA_ACTIVE_DECIMAL: []byte(tempData.TokenDecimals), - utils.DATA_ACTIVE_ADDRESS: []byte(tempData.ContractAddress), + // store the expectedData + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(expectedData)); err != nil { + t.Fatal(err) } - // Mocking ReadEntry calls for temporary data retrieval - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE).Return([]byte(expectedData), nil) - - // Mocking WriteEntry calls for setting active data - for key, value := range activeEntries { - mockDataStore.On("WriteEntry", ctx, sessionId, key, value).Return(nil) - } - - h := &Handlers{ - userdataStore: mockDataStore, - } - - res, err := h.SetVoucher(ctx, "someSym", []byte{}) + res, err := h.SetVoucher(ctx, "set_voucher", []byte{}) assert.NoError(t, err) assert.Equal(t, string(tempData.TokenSymbol), res.Content) - - mockDataStore.AssertExpectations(t) } From e29a24b376cff982367fe2c00470ee1af8eea5cd Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 2 Nov 2024 15:46:46 +0000 Subject: [PATCH 17/28] Add missing models files --- common/hex.go | 13 +++++++++++++ internal/handlers/handlerservice.go | 1 + internal/handlers/ussd/menuhandler.go | 20 ++++++++++---------- internal/models/tokenresponse.go | 18 ++++++++++++++++++ internal/models/vouchersresponse.go | 14 ++++++++++++++ 5 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 internal/models/tokenresponse.go create mode 100644 internal/models/vouchersresponse.go diff --git a/common/hex.go b/common/hex.go index f5aa7ed..971ecf1 100644 --- a/common/hex.go +++ b/common/hex.go @@ -2,6 +2,7 @@ package common import ( "encoding/hex" + "strings" ) func NormalizeHex(s string) (string, error) { @@ -16,3 +17,15 @@ func NormalizeHex(s string) (string, error) { } return hex.EncodeToString(r), nil } + +func IsSameHex(left string, right string) bool { + bl, err := NormalizeHex(left) + if err != nil { + return false + } + br, err := NormalizeHex(left) + if err != nil { + return false + } + return strings.Compare(bl, br) == 0 +} diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index 9afba13..7d8325c 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -10,6 +10,7 @@ import ( "git.defalsify.org/vise.git/resource" "git.grassecon.net/urdt/ussd/internal/handlers/ussd" + "git.grassecon.net/urdt/ussd/internal/utils" "git.grassecon.net/urdt/ussd/remote" ) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index dc77660..a7e9d88 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -233,11 +233,11 @@ func (h *Handlers) CheckPinMisMatch(ctx context.Context, sym string, input []byt return res, fmt.Errorf("missing session") } store := h.userdataStore - blockedNumber, err := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER) + blockedNumber, err := store.ReadEntry(ctx, sessionId, common.DATA_BLOCKED_NUMBER) if err != nil { return res, err } - temporaryPin, err := store.ReadEntry(ctx, string(blockedNumber), utils.DATA_TEMPORARY_VALUE) + temporaryPin, err := store.ReadEntry(ctx, string(blockedNumber), common.DATA_TEMPORARY_VALUE) if err != nil { return res, err } @@ -307,12 +307,12 @@ func (h *Handlers) SaveOthersTemporaryPin(ctx context.Context, sym string, input return res, fmt.Errorf("missing session") } temporaryPin := string(input) - blockedNumber, err := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER) + blockedNumber, err := store.ReadEntry(ctx, sessionId, common.DATA_BLOCKED_NUMBER) if err != nil { return res, err } - err = store.WriteEntry(ctx, string(blockedNumber), utils.DATA_TEMPORARY_VALUE, []byte(temporaryPin)) + err = store.WriteEntry(ctx, string(blockedNumber), common.DATA_TEMPORARY_VALUE, []byte(temporaryPin)) if err != nil { return res, err } @@ -841,15 +841,15 @@ func (h *Handlers) ResetOthersPin(ctx context.Context, sym string, input []byte) if !ok { return res, fmt.Errorf("missing session") } - blockedPhonenumber, err := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER) + blockedPhonenumber, err := store.ReadEntry(ctx, sessionId, common.DATA_BLOCKED_NUMBER) if err != nil { return res, err } - temporaryPin, err := store.ReadEntry(ctx, string(blockedPhonenumber), utils.DATA_TEMPORARY_VALUE) + temporaryPin, err := store.ReadEntry(ctx, string(blockedPhonenumber), common.DATA_TEMPORARY_VALUE) if err != nil { return res, err } - err = store.WriteEntry(ctx, string(blockedPhonenumber), utils.DATA_ACCOUNT_PIN, []byte(temporaryPin)) + err = store.WriteEntry(ctx, string(blockedPhonenumber), common.DATA_ACCOUNT_PIN, []byte(temporaryPin)) if err != nil { return res, nil } @@ -874,7 +874,7 @@ func (h *Handlers) ValidateBlockedNumber(ctx context.Context, sym string, input return res, fmt.Errorf("missing session") } blockedNumber := string(input) - _, err = store.ReadEntry(ctx, blockedNumber, utils.DATA_PUBLIC_KEY) + _, err = store.ReadEntry(ctx, blockedNumber, common.DATA_PUBLIC_KEY) if !isValidPhoneNumber(blockedNumber) { res.FlagSet = append(res.FlagSet, flag_unregistered_number) return res, nil @@ -888,7 +888,7 @@ func (h *Handlers) ValidateBlockedNumber(ctx context.Context, sym string, input return res, err } } - err = store.WriteEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER, []byte(blockedNumber)) + err = store.WriteEntry(ctx, sessionId, common.DATA_BLOCKED_NUMBER, []byte(blockedNumber)) if err != nil { return res, nil } @@ -1075,7 +1075,7 @@ func (h *Handlers) RetrieveBlockedNumber(ctx context.Context, sym string, input return res, fmt.Errorf("missing session") } store := h.userdataStore - blockedNumber, _ := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER) + blockedNumber, _ := store.ReadEntry(ctx, sessionId, common.DATA_BLOCKED_NUMBER) res.Content = string(blockedNumber) diff --git a/internal/models/tokenresponse.go b/internal/models/tokenresponse.go new file mode 100644 index 0000000..d243d93 --- /dev/null +++ b/internal/models/tokenresponse.go @@ -0,0 +1,18 @@ +package models + +type ApiResponse struct { + OK bool `json:"ok"` + Description string `json:"description"` + Result Result `json:"result"` +} + +type Result struct { + Holdings []Holding `json:"holdings"` +} + +type Holding struct { + ContractAddress string `json:"contractAddress"` + TokenSymbol string `json:"tokenSymbol"` + TokenDecimals string `json:"tokenDecimals"` + Balance string `json:"balance"` +} diff --git a/internal/models/vouchersresponse.go b/internal/models/vouchersresponse.go new file mode 100644 index 0000000..09b085d --- /dev/null +++ b/internal/models/vouchersresponse.go @@ -0,0 +1,14 @@ +package models + +import dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" + +type VoucherHoldingResponse struct { + Ok bool `json:"ok"` + Description string `json:"description"` + Result VoucherResult `json:"result"` +} + +// VoucherResult holds the list of token holdings +type VoucherResult struct { + Holdings []dataserviceapi.TokenHoldings `json:"holdings"` +} From 14bc11f4bd87574526b453339e4b079967216b83 Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 2 Nov 2024 16:38:29 +0000 Subject: [PATCH 18/28] Add transaction getter --- common/db.go | 2 +- common/vouchers.go | 9 +++++++++ remote/accountservice.go | 36 ++++++++++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/common/db.go b/common/db.go index 58fd3a1..06d9607 100644 --- a/common/db.go +++ b/common/db.go @@ -30,7 +30,7 @@ const ( DATA_PUBLIC_KEY_REVERSE DATA_ACTIVE_DECIMAL DATA_ACTIVE_ADDRESS - + DATA_TRANSACTIONS ) func typToBytes(typ DataTyp) []byte { diff --git a/common/vouchers.go b/common/vouchers.go index 9ca6277..cd76060 100644 --- a/common/vouchers.go +++ b/common/vouchers.go @@ -37,6 +37,15 @@ func ProcessVouchers(holdings []dataserviceapi.TokenHoldings) VoucherMetadata { return data } +//func StoreVouchers(db storage.PrefixDb, data VoucherMetadata) { +// value, err := db.Put(ctx, []byte(key)) +// if err != nil { +// return nil, fmt.Errorf("failed to get %s: %v", key, err) +// } +// data[key] = string(value) +// } +//} + // GetVoucherData retrieves and matches voucher data func GetVoucherData(ctx context.Context, db storage.PrefixDb, input string) (*dataserviceapi.TokenHoldings, error) { keys := []string{"sym", "bal", "deci", "addr"} diff --git a/remote/accountservice.go b/remote/accountservice.go index bc6a448..d0d7e9b 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -22,6 +22,7 @@ type AccountServiceInterface interface { CreateAccount(ctx context.Context) (*models.AccountResult, error) TrackAccountStatus(ctx context.Context, publicKey string) (*models.TrackStatusResult, error) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) + FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) } type AccountService struct { @@ -100,13 +101,18 @@ func (as *AccountService) CreateAccount(ctx context.Context) (*models.AccountRes return &r, nil } -// FetchVouchers retrieves the token holdings for a given public key from the custodial holdings API endpoint +// FetchVouchers retrieves the token holdings for a given public key from the data indexer API endpoint // Parameters: // - publicKey: The public key associated with the account. func (as *AccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { var r []dataserviceapi.TokenHoldings - req, err := http.NewRequest("GET", config.VoucherHoldingsURL, nil) + ep, err := url.JoinPath(config.VoucherHoldingsURL, publicKey) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", ep, nil) if err != nil { return nil, err } @@ -119,6 +125,32 @@ func (as *AccountService) FetchVouchers(ctx context.Context, publicKey string) ( return r, nil } + +// FetchTransactions retrieves the last 10 transactions for a given public key from the data indexer API endpoint +// Parameters: +// - publicKey: The public key associated with the account. +func (as *AccountService) FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) { + var r []dataserviceapi.Last10TxResponse + + ep, err := url.JoinPath(config.VoucherTransfersURL, publicKey) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", ep, nil) + if err != nil { + return nil, err + } + + _, err = doDataRequest(ctx, req, r) + if err != nil { + return nil, err + } + + return r, nil +} + + func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { var okResponse api.OKResponse var errResponse api.ErrResponse From 3a8a5f40baa56612e8435387542bbd2fcf16368b Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 2 Nov 2024 16:42:50 +0000 Subject: [PATCH 19/28] Add test service placeholders for fetchtransactions --- internal/testutil/mocks/servicemock.go | 5 +++++ internal/testutil/testservice/TestAccountService.go | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/internal/testutil/mocks/servicemock.go b/internal/testutil/mocks/servicemock.go index bec48fd..78ee2b0 100644 --- a/internal/testutil/mocks/servicemock.go +++ b/internal/testutil/mocks/servicemock.go @@ -33,3 +33,8 @@ func (m *MockAccountService) FetchVouchers(ctx context.Context, publicKey string args := m.Called(publicKey) return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) } + +func (m *MockAccountService) FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) { + args := m.Called(publicKey) + return args.Get(0).([]dataserviceapi.Last10TxResponse), args.Error(1) +} diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go index a9a3085..3c104bd 100644 --- a/internal/testutil/testservice/TestAccountService.go +++ b/internal/testutil/testservice/TestAccountService.go @@ -42,3 +42,7 @@ func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey stri }, }, nil } + +func (tas *TestAccountService) FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) { + return []dataserviceapi.Last10TxResponse{}, nil +} From 1d77ad98dc6e4d7be4a3f63561815c06d07039b2 Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 2 Nov 2024 23:33:52 +0000 Subject: [PATCH 20/28] Expose subprefix db --- common/storage.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 common/storage.go diff --git a/common/storage.go b/common/storage.go new file mode 100644 index 0000000..62a8a06 --- /dev/null +++ b/common/storage.go @@ -0,0 +1,13 @@ +package common + +import ( + "git.defalsify.org/vise.git/db" +) + +func StoreToDb(store *UserDataStore, prefix []byte) db.Db { + innerStore := store.Db + if pfx != nil { + innerStore = NewSubPrefixDb(innerStore, pfx) + } + return innerStore +} From dae12ac4989e40f64a48930b5348288c85af8369 Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 2 Nov 2024 23:41:08 +0000 Subject: [PATCH 21/28] Separate subprefix db export --- common/storage.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/common/storage.go b/common/storage.go index 62a8a06..145382d 100644 --- a/common/storage.go +++ b/common/storage.go @@ -2,12 +2,14 @@ package common import ( "git.defalsify.org/vise.git/db" + + "git.grassecon.net/urdt/ussd/internal/storage" ) -func StoreToDb(store *UserDataStore, prefix []byte) db.Db { - innerStore := store.Db - if pfx != nil { - innerStore = NewSubPrefixDb(innerStore, pfx) - } - return innerStore +func StoreToDb(store *UserDataStore) db.Db { + return store.Db +} + +func StoreToPrefixDb(store *UserDataStore, pfx []byte) storage.PrefixDb { + return storage.NewSubPrefixDb(store.Db, pfx) } From a237b615f2ee3148146883e9267ac3c4f77f35e7 Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 3 Nov 2024 01:44:57 +0000 Subject: [PATCH 22/28] Export models package --- common/user_store.go | 1 + internal/handlers/ussd/menuhandler_test.go | 2 +- internal/testutil/mocks/servicemock.go | 2 +- internal/testutil/testservice/TestAccountService.go | 2 +- {internal/models => models}/accountresponse.go | 0 {internal/models => models}/balanceresponse.go | 0 {internal/models => models}/tokenresponse.go | 0 {internal/models => models}/trackstatusresponse.go | 0 {internal/models => models}/vouchersresponse.go | 0 remote/accountservice.go | 2 +- 10 files changed, 5 insertions(+), 4 deletions(-) rename {internal/models => models}/accountresponse.go (100%) rename {internal/models => models}/balanceresponse.go (100%) rename {internal/models => models}/tokenresponse.go (100%) rename {internal/models => models}/trackstatusresponse.go (100%) rename {internal/models => models}/vouchersresponse.go (100%) diff --git a/common/user_store.go b/common/user_store.go index 4b8409f..29796e2 100644 --- a/common/user_store.go +++ b/common/user_store.go @@ -25,6 +25,7 @@ func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ } // WriteEntry adds an entry to the userdata store. +// BUG: this uses sessionId twice func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 86c905d..74e9f53 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -14,7 +14,7 @@ import ( "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" - "git.grassecon.net/urdt/ussd/internal/models" + "git.grassecon.net/urdt/ussd/models" "git.grassecon.net/urdt/ussd/internal/testutil/mocks" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" diff --git a/internal/testutil/mocks/servicemock.go b/internal/testutil/mocks/servicemock.go index 78ee2b0..a24e459 100644 --- a/internal/testutil/mocks/servicemock.go +++ b/internal/testutil/mocks/servicemock.go @@ -3,7 +3,7 @@ package mocks import ( "context" - "git.grassecon.net/urdt/ussd/internal/models" + "git.grassecon.net/urdt/ussd/models" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" "github.com/stretchr/testify/mock" ) diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go index 3c104bd..21f7a63 100644 --- a/internal/testutil/testservice/TestAccountService.go +++ b/internal/testutil/testservice/TestAccountService.go @@ -4,7 +4,7 @@ import ( "context" "encoding/json" - "git.grassecon.net/urdt/ussd/internal/models" + "git.grassecon.net/urdt/ussd/models" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" ) diff --git a/internal/models/accountresponse.go b/models/accountresponse.go similarity index 100% rename from internal/models/accountresponse.go rename to models/accountresponse.go diff --git a/internal/models/balanceresponse.go b/models/balanceresponse.go similarity index 100% rename from internal/models/balanceresponse.go rename to models/balanceresponse.go diff --git a/internal/models/tokenresponse.go b/models/tokenresponse.go similarity index 100% rename from internal/models/tokenresponse.go rename to models/tokenresponse.go diff --git a/internal/models/trackstatusresponse.go b/models/trackstatusresponse.go similarity index 100% rename from internal/models/trackstatusresponse.go rename to models/trackstatusresponse.go diff --git a/internal/models/vouchersresponse.go b/models/vouchersresponse.go similarity index 100% rename from internal/models/vouchersresponse.go rename to models/vouchersresponse.go diff --git a/remote/accountservice.go b/remote/accountservice.go index d0d7e9b..402add5 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -11,7 +11,7 @@ import ( dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" "github.com/grassrootseconomics/eth-custodial/pkg/api" "git.grassecon.net/urdt/ussd/config" - "git.grassecon.net/urdt/ussd/internal/models" + "git.grassecon.net/urdt/ussd/models" ) var ( From 0506a8c452f1c5daab3383d4c3248a0b0780dbdf Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 3 Nov 2024 14:34:26 +0000 Subject: [PATCH 23/28] Add voucherdata endpoint --- common/db.go | 6 ++++++ common/vouchers.go | 2 ++ config/config.go | 3 +++ models/vouchersresponse.go | 17 ++++++++++++----- remote/accountservice.go | 21 +++++++++++++++++++++ 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/common/db.go b/common/db.go index 06d9607..91891d9 100644 --- a/common/db.go +++ b/common/db.go @@ -2,6 +2,8 @@ package common import ( "encoding/binary" + + "git.defalsify.org/vise.git/logging" ) type DataTyp uint16 @@ -33,6 +35,10 @@ const ( DATA_TRANSACTIONS ) +var ( + logg = logging.NewVanilla().WithDomain("urdt-common") +) + func typToBytes(typ DataTyp) []byte { var b [2]byte binary.BigEndian.PutUint16(b[:], uint16(typ)) diff --git a/common/vouchers.go b/common/vouchers.go index cd76060..2fed043 100644 --- a/common/vouchers.go +++ b/common/vouchers.go @@ -84,6 +84,7 @@ func MatchVoucher(input, symbols, balances, decimals, addresses string) (symbol, decList := strings.Split(decimals, "\n") addrList := strings.Split(addresses, "\n") + logg.Tracef("found" , "symlist", symList, "syms", symbols, "input", input) for i, sym := range symList { parts := strings.SplitN(sym, ":", 2) @@ -136,6 +137,7 @@ func GetTemporaryVoucherData(ctx context.Context, store DataStore, sessionId str // UpdateVoucherData sets the active voucher data and clears the temporary voucher data in the DataStore. func UpdateVoucherData(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { + logg.TraceCtxf(ctx, "dtal", "data", data) // Active voucher data entries activeEntries := map[DataTyp][]byte{ DATA_ACTIVE_SYM: []byte(data.TokenSymbol), diff --git a/config/config.go b/config/config.go index a5c89a7..fbf518b 100644 --- a/config/config.go +++ b/config/config.go @@ -13,6 +13,7 @@ const ( trackPath = "/api/v2/account/status" voucherHoldingsPathPrefix = "/api/v1/holdings" voucherTransfersPathPrefix = "/api/v1/transfers/last10" + voucherDataPathPrefix = "/api/v1/token" ) var ( @@ -29,6 +30,7 @@ var ( TrackURL string VoucherHoldingsURL string VoucherTransfersURL string + VoucherDataURL string ) func setBase() error { @@ -62,6 +64,7 @@ func LoadConfig() error { TrackURL, _ = url.JoinPath(custodialURLBase, trackPath) VoucherHoldingsURL, _ = url.JoinPath(dataURLBase, voucherHoldingsPathPrefix) VoucherTransfersURL, _ = url.JoinPath(dataURLBase, voucherTransfersPathPrefix) + VoucherDataURL, _ = url.JoinPath(dataURLBase, voucherDataPathPrefix) return nil } diff --git a/models/vouchersresponse.go b/models/vouchersresponse.go index 09b085d..8cf3ec6 100644 --- a/models/vouchersresponse.go +++ b/models/vouchersresponse.go @@ -2,13 +2,20 @@ package models import dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" -type VoucherHoldingResponse struct { - Ok bool `json:"ok"` - Description string `json:"description"` - Result VoucherResult `json:"result"` -} +//type VoucherHoldingResponse struct { +// Ok bool `json:"ok"` +// Description string `json:"description"` +// Result VoucherResult `json:"result"` +//} // VoucherResult holds the list of token holdings type VoucherResult struct { Holdings []dataserviceapi.TokenHoldings `json:"holdings"` } + +type VoucherDataResult struct { + TokenName string `json:"tokenName"` + TokenSymbol string `json:"tokenSymbol"` + TokenDecimals string `json:"tokenDecimals"` + SinkAddress string `json:"sinkAddress"` +} diff --git a/remote/accountservice.go b/remote/accountservice.go index 402add5..73052f6 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -23,6 +23,7 @@ type AccountServiceInterface interface { TrackAccountStatus(ctx context.Context, publicKey string) (*models.TrackStatusResult, error) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) + VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) } type AccountService struct { @@ -151,6 +152,26 @@ func (as *AccountService) FetchTransactions(ctx context.Context, publicKey strin } +// VoucherData retrieves voucher metadata from the data indexer API endpoint. +// Parameters: +// - address: The voucher address. +func (as *AccountService) VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) { + var voucherDataResult models.VoucherDataResult + + ep, err := url.JoinPath(config.VoucherDataURL, address) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", ep, nil) + if err != nil { + return nil, err + } + + _, err = doCustodialRequest(ctx, req, &voucherDataResult) + return &voucherDataResult, err +} + func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { var okResponse api.OKResponse var errResponse api.ErrResponse From 7189235bee57b4fc703c5d7a2f43f0b4a660c397 Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 3 Nov 2024 15:14:17 +0000 Subject: [PATCH 24/28] Remove unused data type --- common/db.go | 1 - 1 file changed, 1 deletion(-) diff --git a/common/db.go b/common/db.go index 91891d9..1992476 100644 --- a/common/db.go +++ b/common/db.go @@ -25,7 +25,6 @@ const ( DATA_RECIPIENT DATA_AMOUNT DATA_TEMPORARY_VALUE - DATA_VOUCHER_LIST DATA_ACTIVE_SYM DATA_ACTIVE_BAL DATA_BLOCKED_NUMBER From 2c30ccc4058f821f7996442963defced49e4146e Mon Sep 17 00:00:00 2001 From: lash Date: Mon, 4 Nov 2024 02:23:30 +0000 Subject: [PATCH 25/28] Add voucherdata call to test accountservices --- common/storage.go | 39 ++++++++++++++++++- internal/testutil/mocks/servicemock.go | 5 +++ .../testservice/TestAccountService.go | 4 ++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/common/storage.go b/common/storage.go index 145382d..dff4774 100644 --- a/common/storage.go +++ b/common/storage.go @@ -1,8 +1,12 @@ package common import ( - "git.defalsify.org/vise.git/db" + "context" + "errors" + "git.defalsify.org/vise.git/db" + "git.defalsify.org/vise.git/resource" + "git.defalsify.org/vise.git/persist" "git.grassecon.net/urdt/ussd/internal/storage" ) @@ -13,3 +17,36 @@ func StoreToDb(store *UserDataStore) db.Db { func StoreToPrefixDb(store *UserDataStore, pfx []byte) storage.PrefixDb { return storage.NewSubPrefixDb(store.Db, pfx) } + +type StorageServices interface { + GetPersister(ctx context.Context) (*persist.Persister, error) + GetUserdataDb(ctx context.Context) (db.Db, error) + GetResource(ctx context.Context) (resource.Resource, error) + EnsureDbDir() error +} + +type StorageService struct { + svc *storage.MenuStorageService +} + +func NewStorageService(dbDir string) *StorageService { + return &StorageService{ + svc: storage.NewMenuStorageService(dbDir, ""), + } +} + +func(ss *StorageService) GetPersister(ctx context.Context) (*persist.Persister, error) { + return ss.svc.GetPersister(ctx) +} + +func(ss *StorageService) GetUserdataDb(ctx context.Context) (db.Db, error) { + return ss.svc.GetUserdataDb(ctx) +} + +func(ss *StorageService) GetResource(ctx context.Context) (resource.Resource, error) { + return nil, errors.New("not implemented") +} + +func(ss *StorageService) EnsureDbDir() error { + return ss.svc.EnsureDbDir() +} diff --git a/internal/testutil/mocks/servicemock.go b/internal/testutil/mocks/servicemock.go index a24e459..76803ba 100644 --- a/internal/testutil/mocks/servicemock.go +++ b/internal/testutil/mocks/servicemock.go @@ -38,3 +38,8 @@ func (m *MockAccountService) FetchTransactions(ctx context.Context, publicKey st args := m.Called(publicKey) return args.Get(0).([]dataserviceapi.Last10TxResponse), args.Error(1) } + +func(m MockAccountService) VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) { + args := m.Called(address) + return args.Get(0).(*models.VoucherDataResult), args.Error(1) +} diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go index 21f7a63..8752d6f 100644 --- a/internal/testutil/testservice/TestAccountService.go +++ b/internal/testutil/testservice/TestAccountService.go @@ -46,3 +46,7 @@ func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey stri func (tas *TestAccountService) FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) { return []dataserviceapi.Last10TxResponse{}, nil } + +func(m TestAccountService) VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) { + return &models.VoucherDataResult{}, nil +} From 88b50c5dd77852b2cd88097973162e1090cc2e89 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 4 Nov 2024 15:52:03 +0300 Subject: [PATCH 26/28] Remove admin number defination in env example --- .env.example | 4 --- internal/handlers/ussd/menuhandler.go | 3 +-- internal/handlers/ussd/menuhandler_test.go | 31 +++++++++++----------- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/.env.example b/.env.example index 4d86f8b..ab370a7 100644 --- a/.env.example +++ b/.env.example @@ -16,7 +16,3 @@ CREATE_ACCOUNT_URL=http://localhost:5003/api/v2/account/create TRACK_STATUS_URL=https://custodial.sarafu.africa/api/track/ BALANCE_URL=https://custodial.sarafu.africa/api/account/status/ TRACK_URL=http://localhost:5003/api/v2/account/status - - -#numbers with privileges to reset others pin -ADMIN_NUMBERS=254051722XXX,255012221XXX \ No newline at end of file diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index a7e9d88..6c1917d 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -20,8 +20,8 @@ import ( "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" "git.grassecon.net/urdt/ussd/common" - "git.grassecon.net/urdt/ussd/remote" "git.grassecon.net/urdt/ussd/internal/utils" + "git.grassecon.net/urdt/ussd/remote" "gopkg.in/leonelquinteros/gotext.v1" "git.grassecon.net/urdt/ussd/internal/storage" @@ -1390,7 +1390,6 @@ func (h *Handlers) SetVoucher(ctx context.Context, sym string, input []byte) (re return res, fmt.Errorf("missing session") } - // Get temporary data tempData, err := common.GetTemporaryVoucherData(ctx, h.userdataStore, sessionId) if err != nil { diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 2f2e94b..f4c9f7c 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -12,10 +12,10 @@ import ( "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" - "git.grassecon.net/urdt/ussd/models" "git.grassecon.net/urdt/ussd/internal/storage" "git.grassecon.net/urdt/ussd/internal/testutil/mocks" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" + "git.grassecon.net/urdt/ussd/models" "git.grassecon.net/urdt/ussd/common" "github.com/alecthomas/assert/v2" @@ -122,7 +122,7 @@ func TestCreateAccount(t *testing.T) { name: "Test account creation success", serverResponse: &models.AccountResult{ TrackingId: "1234567890", - PublicKey: "0xD3adB33f", + PublicKey: "0xD3adB33f", }, expectedResult: resource.Result{ FlagSet: []uint32{flag_account_created}, @@ -176,7 +176,7 @@ func TestSaveFirstname(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) - + fm, _ := NewFlagManager(flagsPath) flag_allow_update, _ := fm.GetFlag("flag_allow_update") @@ -215,7 +215,7 @@ func TestSaveFamilyname(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) - + fm, _ := NewFlagManager(flagsPath) flag_allow_update, _ := fm.GetFlag("flag_allow_update") @@ -254,7 +254,7 @@ func TestSaveYoB(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) - + fm, _ := NewFlagManager(flagsPath) flag_allow_update, _ := fm.GetFlag("flag_allow_update") @@ -265,7 +265,7 @@ func TestSaveYoB(t *testing.T) { // Define test data yob := "1980" - + if err := store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(yob)); err != nil { t.Fatal(err) } @@ -293,7 +293,7 @@ func TestSaveLocation(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) - + fm, _ := NewFlagManager(flagsPath) flag_allow_update, _ := fm.GetFlag("flag_allow_update") @@ -304,7 +304,7 @@ func TestSaveLocation(t *testing.T) { // Define test data location := "Kilifi" - + if err := store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(location)); err != nil { t.Fatal(err) } @@ -332,7 +332,7 @@ func TestSaveOfferings(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) - + fm, _ := NewFlagManager(flagsPath) flag_allow_update, _ := fm.GetFlag("flag_allow_update") @@ -371,7 +371,7 @@ func TestSaveGender(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) - + fm, _ := NewFlagManager(flagsPath) flag_allow_update, _ := fm.GetFlag("flag_allow_update") @@ -1746,9 +1746,9 @@ func TestFetchCustodialBalances(t *testing.T) { } tests := []struct { - name string + name string balanceResponse *models.BalanceResult - expectedResult resource.Result + expectedResult resource.Result }{ { name: "Test when fetch custodial balances is not a success", @@ -1807,16 +1807,15 @@ func TestSetDefaultVoucher(t *testing.T) { expectedResult resource.Result }{ { - name: "Test no vouchers available", - vouchersResp: []dataserviceapi.TokenHoldings { - }, + name: "Test no vouchers available", + vouchersResp: []dataserviceapi.TokenHoldings{}, expectedResult: resource.Result{ FlagSet: []uint32{flag_no_active_voucher}, }, }, { name: "Test set default voucher when no active voucher is set", - vouchersResp: []dataserviceapi.TokenHoldings { + vouchersResp: []dataserviceapi.TokenHoldings{ dataserviceapi.TokenHoldings{ ContractAddress: "0x123", TokenSymbol: "TOKEN1", From 92ea3df4aa149118e1ecebe729cc48d944b2d2dc Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 4 Nov 2024 17:38:55 +0300 Subject: [PATCH 27/28] Removeearly return statement --- remote/accountservice.go | 1 - 1 file changed, 1 deletion(-) diff --git a/remote/accountservice.go b/remote/accountservice.go index 73052f6..2e19de1 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -202,7 +202,6 @@ func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKRespons if len(okResponse.Result) == 0 { return nil, errors.New("Empty api result") } - return &okResponse, nil v, err := json.Marshal(okResponse.Result) if err != nil { From 266d3d06c3c86ec631b10011ca4e193ea1f367fe Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 4 Nov 2024 17:56:25 +0300 Subject: [PATCH 28/28] Check the flag_no_active_voucher before proceeding --- internal/handlers/ussd/menuhandler.go | 3 ++- services/registration/no_voucher | 2 +- services/registration/no_voucher_swa | 2 +- services/registration/select_voucher.vis | 1 + 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 6c1917d..ca4af09 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -1254,7 +1254,8 @@ func (h *Handlers) SetDefaultVoucher(ctx context.Context, sym string, input []by // Fetch vouchers from the API using the public key vouchersResp, err := h.accountService.FetchVouchers(ctx, string(publicKey)) if err != nil { - return res, err + res.FlagSet = append(res.FlagSet, flag_no_active_voucher) + return res, nil } // Return if there is no voucher diff --git a/services/registration/no_voucher b/services/registration/no_voucher index 332f00e..6303197 100644 --- a/services/registration/no_voucher +++ b/services/registration/no_voucher @@ -1 +1 @@ -You need a voucher to send \ No newline at end of file +You need a voucher to proceed \ No newline at end of file diff --git a/services/registration/no_voucher_swa b/services/registration/no_voucher_swa index 66e8f26..7291650 100644 --- a/services/registration/no_voucher_swa +++ b/services/registration/no_voucher_swa @@ -1 +1 @@ -Unahitaji sarafu kutuma \ No newline at end of file +Unahitaji sarafu kuendelea \ No newline at end of file diff --git a/services/registration/select_voucher.vis b/services/registration/select_voucher.vis index 08aa434..058d791 100644 --- a/services/registration/select_voucher.vis +++ b/services/registration/select_voucher.vis @@ -1,3 +1,4 @@ +CATCH no_voucher flag_no_active_voucher 1 LOAD get_vouchers 0 MAP get_vouchers MOUT back 0