add balance to voucher list #89
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							| @ -5,7 +5,7 @@ go 1.23.4 | |||||||
| require ( | require ( | ||||||
| 	git.defalsify.org/vise.git v0.3.2-0.20250528124150-03bf7bfc1b66 | 	git.defalsify.org/vise.git v0.3.2-0.20250528124150-03bf7bfc1b66 | ||||||
| 	git.grassecon.net/grassrootseconomics/common v0.9.0-beta.1.0.20250417111317-2953f4c2f32e | 	git.grassecon.net/grassrootseconomics/common v0.9.0-beta.1.0.20250417111317-2953f4c2f32e | ||||||
| 	git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250624090744-339ba854c997 | 	git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250630214912-814bef2b209a | ||||||
| 	git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2.0.20250408094335-e2d1f65bb306 | 	git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2.0.20250408094335-e2d1f65bb306 | ||||||
| 	git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 | 	git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 | ||||||
| 	github.com/alecthomas/assert/v2 v2.2.2 | 	github.com/alecthomas/assert/v2 v2.2.2 | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								go.sum
									
									
									
									
									
								
							| @ -12,6 +12,14 @@ git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250624074830- | |||||||
| git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250624074830-5aa032400c12/go.mod h1:y/vsN8UO0wSxZk3gv0y5df4RPKMJI6TIxjVcVCPF8T8= | git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250624074830-5aa032400c12/go.mod h1:y/vsN8UO0wSxZk3gv0y5df4RPKMJI6TIxjVcVCPF8T8= | ||||||
| git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250624090744-339ba854c997 h1:8bCKyYoV4YiVBvCZlRclc3aQlBYpWhgtM35mvniDFD8= | git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250624090744-339ba854c997 h1:8bCKyYoV4YiVBvCZlRclc3aQlBYpWhgtM35mvniDFD8= | ||||||
| git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250624090744-339ba854c997/go.mod h1:y/vsN8UO0wSxZk3gv0y5df4RPKMJI6TIxjVcVCPF8T8= | git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250624090744-339ba854c997/go.mod h1:y/vsN8UO0wSxZk3gv0y5df4RPKMJI6TIxjVcVCPF8T8= | ||||||
|  | git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250626065419-57ee409f9629 h1:ew3vCFrLS/7/8uULTTPCbsHzFntQ6X68SScnBEy3pl0= | ||||||
|  | git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250626065419-57ee409f9629/go.mod h1:y/vsN8UO0wSxZk3gv0y5df4RPKMJI6TIxjVcVCPF8T8= | ||||||
|  | git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250630213135-50ee455e7069 h1:re+hdr5NAC6JqhyvjMCkgX17fFi0u3Mawc6RBnBJW8I= | ||||||
|  | git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250630213135-50ee455e7069/go.mod h1:y/vsN8UO0wSxZk3gv0y5df4RPKMJI6TIxjVcVCPF8T8= | ||||||
|  | git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250630213606-12940bb5f284 h1:2zMU9jPd6xEO6oY9oxr84sdT9G3d09eyAkjVBAz9eco= | ||||||
|  | git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250630213606-12940bb5f284/go.mod h1:y/vsN8UO0wSxZk3gv0y5df4RPKMJI6TIxjVcVCPF8T8= | ||||||
|  | git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250630214912-814bef2b209a h1:KuhJ/WY4RCGmrXUA680ciaponM4vM5zBOJfnCpUo2fc= | ||||||
|  | git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250630214912-814bef2b209a/go.mod h1:y/vsN8UO0wSxZk3gv0y5df4RPKMJI6TIxjVcVCPF8T8= | ||||||
| git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2.0.20250408094335-e2d1f65bb306 h1:Jo+yWysWw/N5BJQtAyEMN8ePVvAyPHv+JG4lQti+1N4= | git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2.0.20250408094335-e2d1f65bb306 h1:Jo+yWysWw/N5BJQtAyEMN8ePVvAyPHv+JG4lQti+1N4= | ||||||
| git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2.0.20250408094335-e2d1f65bb306/go.mod h1:FdLwYtzsjOIcDiW4uDgDYnB4Wdzq12uJUe0QHSSPbSo= | git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2.0.20250408094335-e2d1f65bb306/go.mod h1:FdLwYtzsjOIcDiW4uDgDYnB4Wdzq12uJUe0QHSSPbSo= | ||||||
| git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 h1:DjJlBSz0S13acft5XZDWk7ZYnzElym0xLMYEVgyNJ+E= | git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 h1:DjJlBSz0S13acft5XZDWk7ZYnzElym0xLMYEVgyNJ+E= | ||||||
|  | |||||||
| @ -2575,55 +2575,10 @@ func (h *MenuHandlers) persistLanguageCode(ctx context.Context, code string) err | |||||||
| 	return h.persistInitialLanguageCode(ctx, sessionId, code) | 	return h.persistInitialLanguageCode(ctx, sessionId, code) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // constructAccountAlias retrieves and alias based on the first and family name
 |  | ||||||
| // and writes the result in DATA_ACCOUNT_ALIAS
 |  | ||||||
| func (h *MenuHandlers) constructAccountAlias(ctx context.Context) error { |  | ||||||
| 	var alias string |  | ||||||
| 	store := h.userdataStore |  | ||||||
| 	sessionId, ok := ctx.Value("SessionId").(string) |  | ||||||
| 	if !ok { |  | ||||||
| 		return fmt.Errorf("missing session") |  | ||||||
| 	} |  | ||||||
| 	firstName, err := store.ReadEntry(ctx, sessionId, storedb.DATA_FIRST_NAME) |  | ||||||
| 	if err != nil { |  | ||||||
| 		if db.IsNotFound(err) { |  | ||||||
| 			return nil |  | ||||||
| 		} |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	familyName, err := store.ReadEntry(ctx, sessionId, storedb.DATA_FAMILY_NAME) |  | ||||||
| 	if err != nil { |  | ||||||
| 		if db.IsNotFound(err) { |  | ||||||
| 			return nil |  | ||||||
| 		} |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	pubKey, err := store.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) |  | ||||||
| 	if err != nil { |  | ||||||
| 		if db.IsNotFound(err) { |  | ||||||
| 			return nil |  | ||||||
| 		} |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	aliasInput := fmt.Sprintf("%s%s", firstName, familyName) |  | ||||||
| 	aliasResult, err := h.accountService.RequestAlias(ctx, string(pubKey), aliasInput) |  | ||||||
| 	if err != nil { |  | ||||||
| 		logg.ErrorCtxf(ctx, "failed to retrieve alias", "alias", aliasInput, "error_alias_request", err) |  | ||||||
| 		return fmt.Errorf("Failed to retrieve alias: %s", err.Error()) |  | ||||||
| 	} |  | ||||||
| 	alias = aliasResult.Alias |  | ||||||
| 	//Store the alias
 |  | ||||||
| 	err = store.WriteEntry(ctx, sessionId, storedb.DATA_ACCOUNT_ALIAS, []byte(alias)) |  | ||||||
| 	if err != nil { |  | ||||||
| 		logg.ErrorCtxf(ctx, "failed to write account alias", "key", storedb.DATA_ACCOUNT_ALIAS, "value", alias, "error", err) |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // RequestCustomAlias requests an ENS based alias name based on a user's input,then saves it as temporary value
 | // RequestCustomAlias requests an ENS based alias name based on a user's input,then saves it as temporary value
 | ||||||
| func (h *MenuHandlers) RequestCustomAlias(ctx context.Context, sym string, input []byte) (resource.Result, error) { | func (h *MenuHandlers) RequestCustomAlias(ctx context.Context, sym string, input []byte) (resource.Result, error) { | ||||||
| 	var res resource.Result | 	var res resource.Result | ||||||
|  | 	var alias string | ||||||
| 	sessionId, ok := ctx.Value("SessionId").(string) | 	sessionId, ok := ctx.Value("SessionId").(string) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return res, fmt.Errorf("missing session") | 		return res, fmt.Errorf("missing session") | ||||||
| @ -2648,28 +2603,45 @@ func (h *MenuHandlers) RequestCustomAlias(ctx context.Context, sym string, input | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return res, err | 			return res, err | ||||||
| 		} | 		} | ||||||
| 		pubKey, err := store.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) | 		publicKey, err := store.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			if db.IsNotFound(err) { | 			if db.IsNotFound(err) { | ||||||
| 				return res, nil | 				return res, nil | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		sanitizedInput := sanitizeAliasHint(string(input)) | 		sanitizedInput := sanitizeAliasHint(string(input)) | ||||||
| 		aliasResult, err := h.accountService.RequestAlias(ctx, string(pubKey), sanitizedInput) | 		// Check if an alias already exists
 | ||||||
| 		if err != nil { | 		existingAlias, err := store.ReadEntry(ctx, sessionId, storedb.DATA_SUGGESTED_ALIAS) | ||||||
| 			res.FlagSet = append(res.FlagSet, flag_api_error) | 		if err == nil && len(existingAlias) > 0 { | ||||||
| 			logg.ErrorCtxf(ctx, "failed to retrieve alias", "alias", string(aliasHint), "error_alias_request", err) | 			logg.InfoCtxf(ctx, "Current alias", "alias", string(existingAlias)) | ||||||
| 			return res, nil | 			// Update existing alias
 | ||||||
|  | 			aliasResult, err := h.accountService.UpdateAlias(ctx, sanitizedInput, string(publicKey)) | ||||||
|  | 			if err != nil { | ||||||
|  | 				res.FlagSet = append(res.FlagSet, flag_api_error) | ||||||
|  | 				logg.ErrorCtxf(ctx, "failed to update alias", "alias", sanitizedInput, "error", err) | ||||||
|  | 				return res, nil | ||||||
|  | 			} | ||||||
|  | 			alias = aliasResult.Alias | ||||||
|  | 			logg.InfoCtxf(ctx, "Updated alias", "alias", alias) | ||||||
|  | 		} else { | ||||||
|  | 			logg.InfoCtxf(ctx, "Registering a new alias", "err", err) | ||||||
|  | 			// Register a new alias
 | ||||||
|  | 			aliasResult, err := h.accountService.RequestAlias(ctx, string(publicKey), sanitizedInput) | ||||||
|  | 			if err != nil { | ||||||
|  | 				res.FlagSet = append(res.FlagSet, flag_api_error) | ||||||
|  | 				logg.ErrorCtxf(ctx, "failed to retrieve alias", "alias", sanitizedInput, "error_alias_request", err) | ||||||
|  | 				return res, nil | ||||||
|  | 			} | ||||||
|  | 			res.FlagReset = append(res.FlagReset, flag_api_error) | ||||||
|  | 
 | ||||||
|  | 			alias = aliasResult.Alias | ||||||
|  | 			logg.InfoCtxf(ctx, "Suggested alias", "alias", alias) | ||||||
| 		} | 		} | ||||||
| 		res.FlagReset = append(res.FlagReset, flag_api_error) |  | ||||||
| 
 |  | ||||||
| 		alias := aliasResult.Alias |  | ||||||
| 		logg.InfoCtxf(ctx, "Suggested alias ", "alias", alias) |  | ||||||
| 
 |  | ||||||
| 		//Store the returned alias,wait for user to confirm it as new account alias
 | 		//Store the returned alias,wait for user to confirm it as new account alias
 | ||||||
|  | 		logg.InfoCtxf(ctx, "Final suggested alias", "alias", alias) | ||||||
| 		err = store.WriteEntry(ctx, sessionId, storedb.DATA_SUGGESTED_ALIAS, []byte(alias)) | 		err = store.WriteEntry(ctx, sessionId, storedb.DATA_SUGGESTED_ALIAS, []byte(alias)) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logg.ErrorCtxf(ctx, "failed to write account alias", "key", storedb.DATA_TEMPORARY_VALUE, "value", alias, "error", err) | 			logg.ErrorCtxf(ctx, "failed to write suggested alias", "key", storedb.DATA_SUGGESTED_ALIAS, "value", alias, "error", err) | ||||||
| 			return res, err | 			return res, err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @ -2697,7 +2669,8 @@ func (h *MenuHandlers) GetSuggestedAlias(ctx context.Context, sym string, input | |||||||
| 		return res, fmt.Errorf("missing session") | 		return res, fmt.Errorf("missing session") | ||||||
| 	} | 	} | ||||||
| 	suggestedAlias, err := store.ReadEntry(ctx, sessionId, storedb.DATA_SUGGESTED_ALIAS) | 	suggestedAlias, err := store.ReadEntry(ctx, sessionId, storedb.DATA_SUGGESTED_ALIAS) | ||||||
| 	if err != nil { | 	if err != nil && len(suggestedAlias) <= 0 { | ||||||
|  | 		logg.ErrorCtxf(ctx, "failed to read suggested alias", "key", storedb.DATA_SUGGESTED_ALIAS, "error", err) | ||||||
| 		return res, nil | 		return res, nil | ||||||
| 	} | 	} | ||||||
| 	res.Content = string(suggestedAlias) | 	res.Content = string(suggestedAlias) | ||||||
|  | |||||||
| @ -3175,97 +3175,6 @@ func TestResetUnregisteredNumber(t *testing.T) { | |||||||
| 	assert.Equal(t, expectedResult, res) | 	assert.Equal(t, expectedResult, res) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestConstructAccountAlias(t *testing.T) { |  | ||||||
| 	ctx, store := InitializeTestStore(t) |  | ||||||
| 	sessionId := "session123" |  | ||||||
| 	mockAccountService := new(mocks.MockAccountService) |  | ||||||
| 
 |  | ||||||
| 	ctx = context.WithValue(ctx, "SessionId", sessionId) |  | ||||||
| 
 |  | ||||||
| 	h := &MenuHandlers{ |  | ||||||
| 		userdataStore:  store, |  | ||||||
| 		accountService: mockAccountService, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	tests := []struct { |  | ||||||
| 		name          string |  | ||||||
| 		firstName     string |  | ||||||
| 		familyName    string |  | ||||||
| 		publicKey     string |  | ||||||
| 		expectedAlias string |  | ||||||
| 		aliasResponse *models.RequestAliasResult |  | ||||||
| 		aliasError    error |  | ||||||
| 		expectedError error |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			name:          "Valid alias construction", |  | ||||||
| 			firstName:     "John", |  | ||||||
| 			familyName:    "Doe", |  | ||||||
| 			publicKey:     "pubkey123", |  | ||||||
| 			expectedAlias: "JohnDoeAlias", |  | ||||||
| 			aliasResponse: &models.RequestAliasResult{Alias: "JohnDoeAlias"}, |  | ||||||
| 			aliasError:    nil, |  | ||||||
| 			expectedError: nil, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name:          "Account service fails to return alias", |  | ||||||
| 			firstName:     "Jane", |  | ||||||
| 			familyName:    "Smith", |  | ||||||
| 			publicKey:     "pubkey456", |  | ||||||
| 			expectedAlias: "", |  | ||||||
| 			aliasResponse: nil, |  | ||||||
| 			aliasError:    fmt.Errorf("service unavailable"), |  | ||||||
| 			expectedError: fmt.Errorf("Failed to retrieve alias: service unavailable"), |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for _, tt := range tests { |  | ||||||
| 		t.Run(tt.name, func(t *testing.T) { |  | ||||||
| 			if tt.firstName != "" { |  | ||||||
| 				err := store.WriteEntry(ctx, sessionId, storedb.DATA_FIRST_NAME, []byte(tt.firstName)) |  | ||||||
| 				require.NoError(t, err) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if tt.familyName != "" { |  | ||||||
| 				err := store.WriteEntry(ctx, sessionId, storedb.DATA_FAMILY_NAME, []byte(tt.familyName)) |  | ||||||
| 				require.NoError(t, err) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if tt.publicKey != "" { |  | ||||||
| 				err := store.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(tt.publicKey)) |  | ||||||
| 				require.NoError(t, err) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			aliasInput := fmt.Sprintf("%s%s", tt.firstName, tt.familyName) |  | ||||||
| 
 |  | ||||||
| 			// Mock service behavior
 |  | ||||||
| 			mockAccountService.On( |  | ||||||
| 				"RequestAlias", |  | ||||||
| 				tt.publicKey, |  | ||||||
| 				aliasInput, |  | ||||||
| 			).Return(tt.aliasResponse, tt.aliasError) |  | ||||||
| 
 |  | ||||||
| 			// Call the function under test
 |  | ||||||
| 			err := h.constructAccountAlias(ctx) |  | ||||||
| 
 |  | ||||||
| 			// Assertions
 |  | ||||||
| 			if tt.expectedError != nil { |  | ||||||
| 				assert.EqualError(t, err, tt.expectedError.Error()) |  | ||||||
| 			} else { |  | ||||||
| 				assert.NoError(t, err) |  | ||||||
| 				if tt.expectedAlias != "" { |  | ||||||
| 					storedAlias, err := store.ReadEntry(ctx, sessionId, storedb.DATA_ACCOUNT_ALIAS) |  | ||||||
| 					require.NoError(t, err) |  | ||||||
| 					assert.Equal(t, tt.expectedAlias, string(storedAlias)) |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// Ensure mock expectations were met
 |  | ||||||
| 			mockAccountService.AssertExpectations(t) |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestInsertProfileItems(t *testing.T) { | func TestInsertProfileItems(t *testing.T) { | ||||||
| 	ctx, store := InitializeTestStore(t) | 	ctx, store := InitializeTestStore(t) | ||||||
| 	sessionId := "session123" | 	sessionId := "session123" | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user