Compare commits

...

24 Commits

Author SHA1 Message Date
Carlosokumu
bee9ad5ff5 Merge remote-tracking branch 'refs/remotes/origin/api-context' into api-context 2024-10-24 17:39:11 +03:00
Carlosokumu
6e7b46666e ensure mod match with master 2024-10-24 17:34:42 +03:00
Carlosokumu
383f074cae update method signatures 2024-10-24 17:32:08 +03:00
Carlosokumu
d678a639b8 Merge branch 'master' into api-context 2024-10-24 17:07:11 +03:00
453fea569a Merge pull request 'api-structs' (#117) from api-structs into master
Reviewed-on: urdt/ussd#117
2024-10-24 15:53:46 +02:00
carlos
5c75e35fe0 Delete coverage.html
delete cover.html
2024-10-24 15:45:52 +02:00
carlos
cff50538fa Delete cover.out
delete cover.out
2024-10-24 15:45:29 +02:00
carlos
69a4530269 Delete services/registration/locale/swa/default.mo
remove dev file
2024-10-24 15:41:47 +02:00
Carlosokumu
db19e38717 Merge remote-tracking branch 'refs/remotes/origin/api-structs' into api-structs 2024-10-24 16:37:07 +03:00
Carlosokumu
c796bbdcfc correct create endpoint 2024-10-24 16:36:09 +03:00
Carlosokumu
2b34a0900c check for status code and unmarshal on errResponse 2024-10-24 16:35:53 +03:00
Carlosokumu
57a49819f4 Merge branch 'master' into api-structs 2024-10-24 16:22:41 +03:00
Carlosokumu
abc01b7cee change to local setup endpoint 2024-10-24 16:21:34 +03:00
d19c20a9d7 Merge branch 'master' into api-structs 2024-10-24 15:19:06 +02:00
0c6144d262 Merge pull request 'send-menu-update' (#131) from send-menu-update into master
Reviewed-on: urdt/ussd#131
2024-10-24 15:15:11 +02:00
alfred-mk
ec4e44a27c Merge branch 'master' into send-menu-update 2024-10-24 15:58:59 +03:00
69eb57f794 Merge branch 'master' into api-context 2024-10-24 14:51:25 +02:00
2347d64acc Merge pull request 'check-balance-update' (#132) from check-balance-update into master
Reviewed-on: urdt/ussd#132
2024-10-24 14:50:59 +02:00
alfred-mk
39c0560abe Updated the test 2024-10-24 15:21:48 +03:00
alfred-mk
75459f852b Return the full balance string 2024-10-24 15:12:57 +03:00
alfred-mk
6200728435 Updated the menuhander test 2024-10-24 14:45:15 +03:00
alfred-mk
579b46db65 Replace the public key with the sessionId 2024-10-24 14:34:12 +03:00
Carlosokumu
b41e52af63 pass context.Context 2024-10-23 12:45:54 +03:00
Carlosokumu
fb32dde136 run go mod tidy 2024-10-23 12:45:10 +03:00
8 changed files with 65 additions and 66 deletions

2
go.mod
View File

@@ -44,3 +44,5 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@@ -1,6 +1,7 @@
package server
import (
"context"
"encoding/json"
"errors"
"fmt"
@@ -14,16 +15,15 @@ import (
)
var (
okResponse api.OKResponse
errResponse api.ErrResponse
EMPTY_RESPONSE = 0
okResponse api.OKResponse
errResponse api.ErrResponse
)
type AccountServiceInterface interface {
CheckBalance(publicKey string) (*models.BalanceResponse, error)
CreateAccount() (*api.OKResponse, error)
CheckAccountStatus(trackingId string) (*models.TrackStatusResponse, error)
TrackAccountStatus(publicKey string) (*api.OKResponse, error)
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)
TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error)
}
type AccountService struct {
@@ -41,7 +41,7 @@ type TestAccountService 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(trackingId string) (*models.TrackStatusResponse, error) {
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
@@ -62,7 +62,7 @@ func (as *AccountService) CheckAccountStatus(trackingId string) (*models.TrackSt
}
func (as *AccountService) TrackAccountStatus(publicKey string) (*api.OKResponse, error) {
func (as *AccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) {
var err error
// Construct the URL with the path parameter
url := fmt.Sprintf("%s/%s", config.TrackURL, publicKey)
@@ -85,15 +85,18 @@ func (as *AccountService) TrackAccountStatus(publicKey string) (*api.OKResponse,
errResponse.Description = err.Error()
return nil, err
}
err = json.Unmarshal([]byte(body), &okResponse)
if err != nil {
if resp.StatusCode >= http.StatusBadRequest {
err := json.Unmarshal([]byte(body), &errResponse)
if err != nil {
return nil, err
}
return nil, errors.New(errResponse.Description)
}
if len(okResponse.Result) == EMPTY_RESPONSE {
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
@@ -103,7 +106,7 @@ func (as *AccountService) TrackAccountStatus(publicKey string) (*api.OKResponse,
// 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(publicKey string) (*models.BalanceResponse, error) {
func (as *AccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) {
resp, err := http.Get(config.BalanceURL + publicKey)
if err != nil {
return nil, err
@@ -127,7 +130,7 @@ func (as *AccountService) CheckBalance(publicKey string) (*models.BalanceRespons
// 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() (*api.OKResponse, error) {
func (as *AccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) {
var err error
// Create a new request
@@ -149,21 +152,24 @@ func (as *AccountService) CreateAccount() (*api.OKResponse, error) {
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(body), &okResponse)
if err != nil {
if resp.StatusCode >= http.StatusBadRequest {
err := json.Unmarshal([]byte(body), &errResponse)
if err != nil {
return nil, err
}
return nil, errors.New(errResponse.Description)
}
if len(okResponse.Result) == EMPTY_RESPONSE {
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
}
func (tas *TestAccountService) CreateAccount() (*api.OKResponse, error) {
func (tas *TestAccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) {
return &api.OKResponse{
Ok: true,
Description: "Account creation request received successfully",
@@ -172,7 +178,7 @@ func (tas *TestAccountService) CreateAccount() (*api.OKResponse, error) {
}
func (tas *TestAccountService) CheckBalance(publicKey string) (*models.BalanceResponse, error) {
func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) {
balanceResponse := &models.BalanceResponse{
Ok: true,
Result: struct {
@@ -186,7 +192,7 @@ func (tas *TestAccountService) CheckBalance(publicKey string) (*models.BalanceRe
return balanceResponse, nil
}
func (tas *TestAccountService) TrackAccountStatus(publicKey string) (*api.OKResponse, error) {
func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) {
return &api.OKResponse{
Ok: true,
Description: "Account creation succeeded",
@@ -196,7 +202,7 @@ func (tas *TestAccountService) TrackAccountStatus(publicKey string) (*api.OKResp
}, nil
}
func (tas *TestAccountService) CheckAccountStatus(trackingId string) (*models.TrackStatusResponse, error) {
func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) {
trackResponse := &models.TrackStatusResponse{
Ok: true,
Result: struct {

View File

@@ -140,7 +140,7 @@ 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()
okResponse, err := h.accountService.CreateAccount(ctx)
if err != nil {
return err
}
@@ -544,7 +544,7 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b
if err != nil {
return res, err
}
okResponse, err = h.accountService.TrackAccountStatus(string(publicKey))
okResponse, err = h.accountService.TrackAccountStatus(ctx, string(publicKey))
if err != nil {
res.FlagSet = append(res.FlagSet, flag_api_error)
return res, err
@@ -641,13 +641,17 @@ func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) (
return res, fmt.Errorf("missing session")
}
code := codeFromCtx(ctx)
l := gotext.NewLocale(translationDir, code)
l.AddDomain("default")
store := h.userdataStore
publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY)
if err != nil {
return res, err
}
balanceResponse, err := h.accountService.CheckBalance(string(publicKey))
balanceResponse, err := h.accountService.CheckBalance(ctx, string(publicKey))
if err != nil {
return res, nil
}
@@ -657,7 +661,8 @@ func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) (
}
res.FlagReset = append(res.FlagReset, flag_api_error)
balance := balanceResponse.Result.Balance
res.Content = balance
res.Content = l.Get("Balance: %s\n", balance)
return res, nil
}
@@ -679,7 +684,7 @@ func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input
return res, err
}
balanceResponse, err := h.accountService.CheckBalance(string(publicKey))
balanceResponse, err := h.accountService.CheckBalance(ctx, string(publicKey))
if err != nil {
return res, nil
}
@@ -797,7 +802,7 @@ func (h *Handlers) MaxAmount(ctx context.Context, sym string, input []byte) (res
store := h.userdataStore
publicKey, _ := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY)
balanceResp, err := h.accountService.CheckBalance(string(publicKey))
balanceResp, err := h.accountService.CheckBalance(ctx, string(publicKey))
if err != nil {
return res, nil
}
@@ -827,7 +832,7 @@ func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte)
amountStr := string(input)
balanceRes, err := h.accountService.CheckBalance(string(publicKey))
balanceRes, err := h.accountService.CheckBalance(ctx, string(publicKey))
balanceStr := balanceRes.Result.Balance
if !balanceRes.Ok {
@@ -897,7 +902,7 @@ func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) (
return res, nil
}
// GetSender retrieves the public key from the Gdbm Db
// GetSender returns the sessionId (phoneNumber)
func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result
@@ -906,10 +911,7 @@ func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (res
return res, fmt.Errorf("missing session")
}
store := h.userdataStore
publicKey, _ := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY)
res.Content = string(publicKey)
res.Content = string(sessionId)
return res, nil
}
@@ -946,13 +948,12 @@ func (h *Handlers) InitiateTransaction(ctx context.Context, sym string, input []
// TODO
// Use the amount, recipient and sender to call the API and initialize the transaction
store := h.userdataStore
publicKey, _ := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY)
amount, _ := store.ReadEntry(ctx, sessionId, utils.DATA_AMOUNT)
recipient, _ := store.ReadEntry(ctx, sessionId, utils.DATA_RECIPIENT)
res.Content = l.Get("Your request has been sent. %s will receive %s from %s.", string(recipient), string(amount), string(publicKey))
res.Content = l.Get("Your request has been sent. %s will receive %s from %s.", string(recipient), string(amount), string(sessionId))
account_authorized_flag, err := h.flagManager.GetFlag("flag_account_authorized")
if err != nil {

View File

@@ -516,12 +516,8 @@ func TestGetSender(t *testing.T) {
mockStore := new(mocks.MockUserDataStore)
// Define test data
sessionId := "session123"
sessionId := "254712345678"
ctx := context.WithValue(context.Background(), "SessionId", sessionId)
publicKey := "0xcasgatweksalw1018221"
// Set up the expected behavior of the mock
mockStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil)
// Create the Handlers instance with the mock store
h := &Handlers{
@@ -529,11 +525,10 @@ func TestGetSender(t *testing.T) {
}
// Call the method
res, _ := h.GetSender(ctx, "max_amount", []byte("check_balance"))
//Assert that the public key from readentry operation is what was set as the result content.
assert.Equal(t, publicKey, res.Content)
res, _ := h.GetSender(ctx, "get_sender", []byte(""))
//Assert that the sessionId is what was set as the result content.
assert.Equal(t, sessionId, res.Content)
}
func TestGetAmount(t *testing.T) {
@@ -1297,7 +1292,7 @@ func TestResetInvalidAmount(t *testing.T) {
}
func TestInitiateTransaction(t *testing.T) {
sessionId := "session123"
sessionId := "254712345678"
fm, err := NewFlagManager(flagsPath)
@@ -1320,30 +1315,26 @@ func TestInitiateTransaction(t *testing.T) {
tests := []struct {
name string
input []byte
PublicKey []byte
Recipient []byte
Amount []byte
status string
expectedResult resource.Result
}{
{
name: "Test amount reset",
PublicKey: []byte("0x1241527192"),
Amount: []byte("0.002CELO"),
name: "Test initiate transaction",
Amount: []byte("0.002 CELO"),
Recipient: []byte("0x12415ass27192"),
expectedResult: resource.Result{
FlagReset: []uint32{account_authorized_flag},
Content: "Your request has been sent. 0x12415ass27192 will receive 0.002CELO from 0x1241527192.",
Content: "Your request has been sent. 0x12415ass27192 will receive 0.002 CELO from 254712345678.",
},
},
}
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_PUBLIC_KEY).Return(tt.PublicKey, nil)
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("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, []byte("")).Return(nil)
// Call the method under test
res, _ := h.InitiateTransaction(ctx, "transaction_reset_amount", tt.input)
@@ -1356,10 +1347,8 @@ func TestInitiateTransaction(t *testing.T) {
// Assert that expectations were met
mockDataStore.AssertExpectations(t)
})
}
}
func TestQuit(t *testing.T) {
@@ -1638,7 +1627,6 @@ func TestValidateRecipient(t *testing.T) {
}
func TestCheckBalance(t *testing.T) {
sessionId := "session123"
publicKey := "0X13242618721"
fm, _ := NewFlagManager(flagsPath)
@@ -1668,7 +1656,7 @@ func TestCheckBalance(t *testing.T) {
},
},
{
name: "Test when checking a balance is a success",
name: "Test when checking a balance is a success",
balanceResonse: &models.BalanceResponse{
Ok: true,
Result: struct {
@@ -1680,7 +1668,7 @@ func TestCheckBalance(t *testing.T) {
},
},
expectedResult: resource.Result{
Content: "0.003 CELO",
Content: "Balance: 0.003 CELO\n",
FlagReset: []uint32{flag_api_error},
},
},
@@ -1713,10 +1701,8 @@ func TestCheckBalance(t *testing.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 TestGetProfile(t *testing.T) {

View File

@@ -1,6 +1,8 @@
package mocks
import (
"context"
"git.grassecon.net/urdt/ussd/internal/models"
"github.com/grassrootseconomics/eth-custodial/pkg/api"
"github.com/stretchr/testify/mock"
@@ -11,22 +13,22 @@ type MockAccountService struct {
mock.Mock
}
func (m *MockAccountService) CreateAccount() (*api.OKResponse, error) {
func (m *MockAccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) {
args := m.Called()
return args.Get(0).(*api.OKResponse), args.Error(1)
}
func (m *MockAccountService) CheckBalance(publicKey string) (*models.BalanceResponse, error) {
func (m *MockAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) {
args := m.Called(publicKey)
return args.Get(0).(*models.BalanceResponse), args.Error(1)
}
func (m *MockAccountService) CheckAccountStatus(trackingId string) (*models.TrackStatusResponse, error) {
func (m *MockAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) {
args := m.Called(trackingId)
return args.Get(0).(*models.TrackStatusResponse), args.Error(1)
}
func (m *MockAccountService) TrackAccountStatus(publicKey string) (*api.OKResponse, error) {
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)
}

View File

@@ -7,6 +7,8 @@ msgstr "Ombi lako limetumwa. %s atapokea %s kutoka kwa %s."
msgid "Thank you for using Sarafu. Goodbye!"
msgstr "Asante kwa kutumia huduma ya Sarafu. Kwaheri!"
msgid "For more help,please call: 0757628885"
msgstr "Kwa usaidizi zaidi,piga: 0757628885"
msgid "Balance: %s\n"
msgstr "Salio: %s\n"

View File

@@ -1 +1 @@
Balance: {{.check_balance}}
{{.check_balance}}

View File

@@ -1 +1 @@
Salio: {{.check_balance}}
{{.check_balance}}