Compare commits

..

93 Commits

Author SHA1 Message Date
alfred-mk
7c2454422e remove misplaced CATCH statement
Some checks failed
release / docker (push) Has been cancelled
2025-05-23 16:54:05 +03:00
alfred-mk
95de1dad2b updated the go-vise package to commit hash a170e8a79da067e30b3c28a999a4d87fdd07ebaf 2025-05-23 16:53:10 +03:00
alfred-mk
d03c0c4c0e vouchers-input-selection (#75)
Some checks failed
release / docker (push) Has been cancelled
- Update the NEXT and PREV input selectors on the vouchers list
- Have the INCMPs before LOAD/RELOADs to prevent navigation inputs being passed to handler functions

Reviewed-on: #75
Reviewed-by: Mohamed Sohail <kamikazechaser@noreply.localhost>
Co-authored-by: alfred-mk <alfredmwaik@gmail.com>
Co-committed-by: alfred-mk <alfredmwaik@gmail.com>
2025-05-19 15:42:43 +02:00
alfred-mk
e914d059e2 upgraded vise to refresh error logline for more context
Some checks failed
release / docker (push) Has been cancelled
2025-05-07 20:26:54 +03:00
alfred-mk
7b1676bb37 fixes: recipient address and phone number (#74)
Some checks failed
release / docker (push) Has been cancelled
- Add functionality to checksum addresses...resolves #66
- Remove white spaces from the recipient input...resolves #70

Reviewed-on: #74
Reviewed-by: Mohamed Sohail <kamikazechaser@noreply.localhost>
Co-authored-by: alfred-mk <alfredmwaik@gmail.com>
Co-committed-by: alfred-mk <alfredmwaik@gmail.com>
2025-05-07 11:45:38 +02:00
carlos
db5d55d8e3 Merge pull request 'route-api-errors' (#46) from route-api-errors into master
Reviewed-on: #46
2025-04-29 13:55:54 +02:00
Carlosokumu
06cab56427 fix failing tests: menuhandlers missing the logdb 2025-04-29 13:25:31 +03:00
Carlosokumu
d0c181bca2 Merge branch 'master' into route-api-errors 2025-04-29 12:58:46 +03:00
e379129b3d Merge pull request 'logdb' (#56) from logdb into master
Some checks failed
release / docker (push) Has been cancelled
Reviewed-on: #56
2025-04-29 09:15:50 +02:00
Carlosokumu
29d35d1ec4 add write of the temporary and confirmed account pins to the log db 2025-04-28 15:49:40 +03:00
alfred-mk
687447e73e added the logdb to the testutil engine 2025-04-28 15:09:38 +03:00
alfred-mk
ec1ddefeb3 updated packages for sarafu-api and vise 2025-04-28 12:50:36 +03:00
alfred-mk
4166c9aed5 Merge branch 'master' into logdb 2025-04-28 12:38:27 +03:00
alfred-mk
78e82edfb5 added the logdn to the menuhandler tests 2025-04-28 12:26:06 +03:00
Carlosokumu
a5c4866b23 add required logdb to menuhandler 2025-04-28 11:50:25 +03:00
Carlosokumu
b52239e6be use direct key data type 2025-04-28 11:50:10 +03:00
Carlosokumu
5f02df64d7 upgrade visedriver dep 2025-04-28 11:40:28 +03:00
alfred-mk
0ba65fc48c use the updated phone and alias regexes from common 2025-04-28 11:39:37 +03:00
alfred-mk
ce8cc8e0fd use latest commit from sarafu-api 2025-04-28 11:38:45 +03:00
Carlosokumu
1499e4a29a check recipient before sending an sms 2025-04-28 11:38:44 +03:00
Carlosokumu
5f24ff3b1b feat: send invites when a recipient
is not resolved
2025-04-28 11:38:44 +03:00
Carlosokumu
6cdee7b58b update sarafu-api dep 2025-04-28 11:38:43 +03:00
alfred-mk
af5537abfc updated the description of DATA_SELF_PIN_RESET 2025-04-28 11:37:45 +03:00
alfred-mk
a6e569afb1 remove the verify_new_pin functionality that managed the unused flag_valid_pin 2025-04-28 11:37:44 +03:00
alfred-mk
446514d8ce remove unused function reset_valid_pin 2025-04-28 11:37:44 +03:00
alfred-mk
131d106f38 use a single confirm_pin_change node 2025-04-28 11:37:43 +03:00
alfred-mk
4d62f0222e use the same check for flag_invalid_pin to move to the invalid_pin node 2025-04-28 11:37:43 +03:00
alfred-mk
37cc3e1bc1 cleanup: remove extra space in all .vis files 2025-04-28 11:37:42 +03:00
alfred-mk
491e97d8af cleanup: remove extra space 2025-04-28 11:37:42 +03:00
alfred-mk
d4fefe3c39 update the order for the INCMP statement 2025-04-28 11:37:41 +03:00
alfred-mk
e8ff468c7b update the reset flags in TestCheckBlockedStatus 2025-04-28 11:37:41 +03:00
alfred-mk
965f343230 update the reset flags in TestConfirmPinChange 2025-04-28 11:37:40 +03:00
alfred-mk
3426d31a9e use the correct flag_invalid_pin in TestSaveTemporaryPin 2025-04-28 11:37:40 +03:00
alfred-mk
8b2b667307 updated the expected content for the alias in view profile 2025-04-28 11:37:39 +03:00
alfred-mk
c206fa1329 updated the menu flow for the admin reset others PIN in test 2025-04-28 11:37:39 +03:00
alfred-mk
ad395c4b1a remove code related to admins resetting a user's actual PIN 2025-04-28 11:37:38 +03:00
alfred-mk
af7e6cc603 add a space 2025-04-28 11:37:38 +03:00
alfred-mk
f90a188acc updated the flags set and reset in SaveTemporaryPin and VerifyCreatePin 2025-04-28 11:37:37 +03:00
alfred-mk
7a542d1f1c updated the description of the flag_incorrect_pin 2025-04-28 11:37:37 +03:00
alfred-mk
7d800d68a0 have the catch for create_pin above to catch accounts that do not have a PIN before the status on chain is checked 2025-04-28 11:37:36 +03:00
alfred-mk
850458b5d8 use a single pin_mismatch node for a confirmed PIN that does not match the original PIN 2025-04-28 11:37:36 +03:00
alfred-mk
ef8e3d5c35 allow the user to quit and move to invalid_pin node if the given input is invalid 2025-04-28 11:37:35 +03:00
alfred-mk
982eebf374 move to the top node when one selects back 2025-04-28 11:37:35 +03:00
alfred-mk
228d936a0e use the confirm_self_pin_reset to confirm the new PIN 2025-04-28 11:37:34 +03:00
alfred-mk
7c4d37b5b8 use the self_reset_pin node to reset PINs for accounts with a flag_account_pin_reset 2025-04-28 11:37:33 +03:00
alfred-mk
e6e8bb6671 set the DATA_SELF_PIN_RESET as 0 and reset the flag_account_pin_reset 2025-04-28 11:37:33 +03:00
alfred-mk
6385735b89 move back to the previous node if the admin user is not authorized 2025-04-28 11:34:27 +03:00
alfred-mk
70815aabd1 request the admin to authorize the PIN reset 2025-04-28 11:34:27 +03:00
alfred-mk
919899c704 move to the authorize_reset_others_pin if the given number is valid and registered 2025-04-28 11:34:26 +03:00
alfred-mk
9a2ad99d07 updated the ResetOthersPin and ValidateBlockedNumber for the updated reset other's PIN functionality 2025-04-28 11:34:26 +03:00
alfred-mk
2f4959e191 use the DATA_SELF_PIN_RESET to set the flag_account_pin_reset 2025-04-28 11:34:25 +03:00
alfred-mk
1b2f3bb046 added a DATA_SELF_PIN_RESET to track when a user's PIN is reset by an admin 2025-04-28 11:34:24 +03:00
carlos
19a2b28367 Merge pull request 'extra-sms' (#64) from extra-sms into master
Reviewed-on: #64
2025-04-28 10:33:25 +02:00
alfred-mk
25d124c58d use updated go-vise that removes rollback on missing key 2025-04-25 17:10:46 +03:00
alfred-mk
5b34ef28eb added the logDb to async and http 2025-04-25 09:33:08 +03:00
Carlosokumu
0370a3def4 use dedicated smsservice for triggering extra sms 2025-04-18 12:13:24 +03:00
Carlosokumu
7c0651d218 use dedicated sms package for triggering sms 2025-04-18 12:12:33 +03:00
Carlosokumu
a38ac06a3d trigger an address sms in the check_identifier handler 2025-04-18 10:56:41 +03:00
Carlosokumu
ac2a3721b2 remove dedicated address sms trigger 2025-04-18 10:55:02 +03:00
Carlosokumu
7ea3cb6b51 remove reload for check identifier to prevent double address sms trigger 2025-04-18 10:54:23 +03:00
Carlosokumu
0274133d48 add handler to send an address sms 2025-04-17 23:32:05 +03:00
Carlosokumu
5ff2e794ff feat: implement address and pin reset sms 2025-04-17 23:31:48 +03:00
Carlosokumu
08deeca500 register handler to trigger address sms 2025-04-17 23:31:22 +03:00
Carlosokumu
cea920c1f5 dep: upgrade sarafu-api dep to include address and pin reset sms 2025-04-17 23:30:54 +03:00
ade236747c Merge pull request 'use the updated phone and alias regexes from common' (#63) from update-recipient-validator into master
Reviewed-on: #63
2025-04-17 16:53:42 +02:00
alfred-mk
e1a3729e3b use the updated phone and alias regexes from common 2025-04-17 14:31:18 +03:00
Carlosokumu
f127fd7c0f initialize log db ,attach it to the menuhandler 2025-04-14 11:34:37 +03:00
Carlosokumu
79bf09f3d1 add logdb to menuhandler and associated write operations 2025-04-09 14:55:35 +03:00
Carlosokumu
f4804546d9 add log db struct with associated methods 2025-04-09 14:52:57 +03:00
Carlosokumu
3fff03a164 update visedriver dep 2025-04-09 14:50:28 +03:00
Carlosokumu
094866c129 add a logdb field to lhs and setter function 2025-04-09 14:49:41 +03:00
Carlosokumu
58242c8d55 fix failing test: TestManageVouchers 2025-04-02 10:53:36 +03:00
Carlosokumu
cab90ed89a set and reset flag_api_error flag 2025-04-02 10:48:04 +03:00
Carlosokumu
73c3486400 catch api call failure when manage vouchers is called 2025-04-02 10:47:33 +03:00
Carlosokumu
3c84fb5ae7 Merge branch 'master' into route-api-errors 2025-04-02 10:38:47 +03:00
Carlosokumu
04880b58a8 fix failing test 2025-04-01 12:49:10 +03:00
Carlosokumu
0458ac9498 fix failing test 2025-04-01 12:38:57 +03:00
Carlosokumu
a7e8c184f5 add some spacing 2025-04-01 11:59:31 +03:00
Carlosokumu
3615348efd add swahili template 2025-04-01 11:57:59 +03:00
Carlosokumu
d0be79d817 set account creation failed flag 2025-04-01 11:30:00 +03:00
Carlosokumu
7883063e53 feat: set and reset api call failure flags 2025-03-31 15:42:27 +03:00
Carlosokumu
f562ce8adf check for api call failure when setting the dafault voucher 2025-03-31 15:41:49 +03:00
Carlosokumu
cd2f4328a8 check for api call failure when checking transactions 2025-03-31 15:41:19 +03:00
Carlosokumu
95b9a6e486 catch api call failure when fetching voucher details 2025-03-28 16:09:53 +03:00
Carlosokumu
9674a04cbc add handler to reset api call failure flag,set flag when requesting an alias fails 2025-03-28 15:51:56 +03:00
Carlosokumu
6c46c097fb add explicit api call failure flag reset 2025-03-28 15:47:34 +03:00
Carlosokumu
c814c4ae5c register handler to reset api call failure flag 2025-03-28 15:46:57 +03:00
Carlosokumu
bbecec0310 catch api call error when requesting an alias 2025-03-28 15:46:21 +03:00
Carlosokumu
eaa89c29df Merge branch 'master' into route-api-errors 2025-03-28 15:22:40 +03:00
Carlosokumu
e832f46d22 return to top on retry 2025-03-26 14:40:54 +03:00
Carlosokumu
039117f40e add api call failure catch 2025-03-26 14:40:32 +03:00
Carlosokumu
3532f72fbd remove unneccessary catch 2025-03-26 14:39:37 +03:00
Carlosokumu
04c7e20457 set api call error flag to failing api calls 2025-03-26 14:38:47 +03:00
29 changed files with 701 additions and 405 deletions

View File

@@ -44,6 +44,7 @@ func main() {
var err error var err error
var gettextDir string var gettextDir string
var langs args.LangVar var langs args.LangVar
var logDbConnStr string
flag.BoolVar(&engineDebug, "d", false, "use engine debug output") flag.BoolVar(&engineDebug, "d", false, "use engine debug output")
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
@@ -55,6 +56,7 @@ func main() {
flag.UintVar(&port, "p", config.Port(), "http port") flag.UintVar(&port, "p", config.Port(), "http port")
flag.StringVar(&gettextDir, "gettext", "", "use gettext translations from given directory") flag.StringVar(&gettextDir, "gettext", "", "use gettext translations from given directory")
flag.Var(&langs, "language", "add symbol resolution for language") flag.Var(&langs, "language", "add symbol resolution for language")
flag.StringVar(&logDbConnStr, "log-c", "db-logs", "log db connection string")
flag.Parse() flag.Parse()
config.Apply(override) config.Apply(override)
@@ -77,10 +79,10 @@ func main() {
pfp := path.Join(scriptDir, "pp.csv") pfp := path.Join(scriptDir, "pp.csv")
cfg := engine.Config{ cfg := engine.Config{
Root: "root", Root: "root",
OutputSize: uint32(size), OutputSize: uint32(size),
FlagCount: uint32(128), FlagCount: uint32(128),
MenuSeparator: menuSeparator, MenuSeparator: menuSeparator,
ResetOnEmptyInput: true, ResetOnEmptyInput: true,
} }
@@ -100,6 +102,11 @@ func main() {
fmt.Fprintf(os.Stderr, "userdatadb: %v\n", err) fmt.Fprintf(os.Stderr, "userdatadb: %v\n", err)
os.Exit(1) os.Exit(1)
} }
logdb, err := menuStorageService.GetLogDb(ctx, userdataStore, logDbConnStr, "user-data")
if err != nil {
fmt.Fprintf(os.Stderr, "get log db error: %v\n", err)
os.Exit(1)
}
dbResource, ok := rs.(*resource.DbResource) dbResource, ok := rs.(*resource.DbResource)
if !ok { if !ok {
@@ -113,6 +120,7 @@ func main() {
os.Exit(1) os.Exit(1)
} }
lhs.SetDataStore(&userdataStore) lhs.SetDataStore(&userdataStore)
lhs.SetLogDb(&logdb)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "setdatastore: %v\n", err) fmt.Fprintf(os.Stderr, "setdatastore: %v\n", err)
os.Exit(1) os.Exit(1)

View File

@@ -56,6 +56,7 @@ func main() {
var err error var err error
var gettextDir string var gettextDir string
var langs args.LangVar var langs args.LangVar
var logDbConnStr string
flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&sessionId, "session-id", "075xx2123", "session id")
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
@@ -69,6 +70,7 @@ func main() {
flag.UintVar(&port, "p", config.Port(), "http port") flag.UintVar(&port, "p", config.Port(), "http port")
flag.StringVar(&gettextDir, "gettext", "", "use gettext translations from given directory") flag.StringVar(&gettextDir, "gettext", "", "use gettext translations from given directory")
flag.Var(&langs, "language", "add symbol resolution for language") flag.Var(&langs, "language", "add symbol resolution for language")
flag.StringVar(&logDbConnStr, "log-c", "db-logs", "log db connection string")
flag.Parse() flag.Parse()
config.Apply(override) config.Apply(override)
@@ -92,10 +94,10 @@ func main() {
pfp := path.Join(scriptDir, "pp.csv") pfp := path.Join(scriptDir, "pp.csv")
cfg := engine.Config{ cfg := engine.Config{
Root: "root", Root: "root",
OutputSize: uint32(size), OutputSize: uint32(size),
FlagCount: uint32(128), FlagCount: uint32(128),
MenuSeparator: menuSeparator, MenuSeparator: menuSeparator,
ResetOnEmptyInput: true, ResetOnEmptyInput: true,
} }
@@ -120,6 +122,12 @@ func main() {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintf(os.Stderr, err.Error())
os.Exit(1) os.Exit(1)
} }
logdb, err := menuStorageService.GetLogDb(ctx, userdataStore, logDbConnStr, "user-data")
if err != nil {
fmt.Fprintf(os.Stderr, "get log db error: %v\n", err)
os.Exit(1)
}
//defer userdataStore.Close(ctx) //defer userdataStore.Close(ctx)
dbResource, ok := rs.(*resource.DbResource) dbResource, ok := rs.(*resource.DbResource)
@@ -129,6 +137,7 @@ func main() {
lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs) lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs)
lhs.SetDataStore(&userdataStore) lhs.SetDataStore(&userdataStore)
lhs.SetLogDb(&logdb)
accountService := services.New(ctx, menuStorageService) accountService := services.New(ctx, menuStorageService)
hl, err := lhs.GetHandler(accountService) hl, err := lhs.GetHandler(accountService)

View File

@@ -43,6 +43,7 @@ func main() {
var err error var err error
var gettextDir string var gettextDir string
var langs args.LangVar var langs args.LangVar
var logDbConnStr string
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string") flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string")
@@ -55,6 +56,7 @@ func main() {
flag.UintVar(&port, "p", config.Port(), "http port") flag.UintVar(&port, "p", config.Port(), "http port")
flag.StringVar(&gettextDir, "gettext", "", "use gettext translations from given directory") flag.StringVar(&gettextDir, "gettext", "", "use gettext translations from given directory")
flag.Var(&langs, "language", "add symbol resolution for language") flag.Var(&langs, "language", "add symbol resolution for language")
flag.StringVar(&logDbConnStr, "log-c", "db-logs", "log db connection string")
flag.Parse() flag.Parse()
config.Apply(override) config.Apply(override)
@@ -78,10 +80,10 @@ func main() {
pfp := path.Join(scriptDir, "pp.csv") pfp := path.Join(scriptDir, "pp.csv")
cfg := engine.Config{ cfg := engine.Config{
Root: "root", Root: "root",
OutputSize: uint32(size), OutputSize: uint32(size),
FlagCount: uint32(128), FlagCount: uint32(128),
MenuSeparator: menuSeparator, MenuSeparator: menuSeparator,
ResetOnEmptyInput: true, ResetOnEmptyInput: true,
} }
@@ -103,6 +105,12 @@ func main() {
os.Exit(1) os.Exit(1)
} }
logdb, err := menuStorageService.GetLogDb(ctx, userdataStore, logDbConnStr, "user-data")
if err != nil {
fmt.Fprintf(os.Stderr, "get log db error: %v\n", err)
os.Exit(1)
}
dbResource, ok := rs.(*resource.DbResource) dbResource, ok := rs.(*resource.DbResource)
if !ok { if !ok {
os.Exit(1) os.Exit(1)
@@ -110,6 +118,7 @@ func main() {
lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs) lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs)
lhs.SetDataStore(&userdataStore) lhs.SetDataStore(&userdataStore)
lhs.SetLogDb(&logdb)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintf(os.Stderr, err.Error())

View File

@@ -36,6 +36,7 @@ func main() {
var err error var err error
var gettextDir string var gettextDir string
var langs args.LangVar var langs args.LangVar
var logDbConnStr string
flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&sessionId, "session-id", "075xx2123", "session id")
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
@@ -46,6 +47,7 @@ func main() {
flag.UintVar(&size, "s", 160, "max size of output") flag.UintVar(&size, "s", 160, "max size of output")
flag.StringVar(&gettextDir, "gettext", "", "use gettext translations from given directory") flag.StringVar(&gettextDir, "gettext", "", "use gettext translations from given directory")
flag.Var(&langs, "language", "add symbol resolution for language") flag.Var(&langs, "language", "add symbol resolution for language")
flag.StringVar(&logDbConnStr, "log-c", "db-logs", "log db connection string")
flag.Parse() flag.Parse()
config.Apply(override) config.Apply(override)
@@ -110,6 +112,12 @@ func main() {
os.Exit(1) os.Exit(1)
} }
logdb, err := menuStorageService.GetLogDb(ctx, userdatastore, logDbConnStr, "user-data")
if err != nil {
fmt.Fprintf(os.Stderr, "get log db error: %v\n", err)
os.Exit(1)
}
dbResource, ok := rs.(*resource.DbResource) dbResource, ok := rs.(*resource.DbResource)
if !ok { if !ok {
fmt.Fprintf(os.Stderr, "get dbresource error: %v\n", err) fmt.Fprintf(os.Stderr, "get dbresource error: %v\n", err)
@@ -118,6 +126,7 @@ func main() {
lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs) lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs)
lhs.SetDataStore(&userdatastore) lhs.SetDataStore(&userdatastore)
lhs.SetLogDb(&logdb)
lhs.SetPersister(pe) lhs.SetPersister(pe)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "localhandler service error: %v\n", err) fmt.Fprintf(os.Stderr, "localhandler service error: %v\n", err)

View File

@@ -38,7 +38,7 @@ func main() {
var stateDebug bool var stateDebug bool
var host string var host string
var port uint var port uint
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
flag.StringVar(&override.ResourceConn, "resource", "?", "resource connection string") flag.StringVar(&override.ResourceConn, "resource", "?", "resource connection string")
flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string") flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string")
@@ -81,9 +81,9 @@ func main() {
pfp := path.Join(scriptDir, "pp.csv") pfp := path.Join(scriptDir, "pp.csv")
cfg := engine.Config{ cfg := engine.Config{
Root: "root", Root: "root",
OutputSize: uint32(size), OutputSize: uint32(size),
FlagCount: uint32(128), FlagCount: uint32(128),
ResetOnEmptyInput: true, ResetOnEmptyInput: true,
} }
if stateDebug { if stateDebug {

View File

@@ -25,7 +25,7 @@ const (
defaultSSHHost string = "127.0.0.1" defaultSSHHost string = "127.0.0.1"
defaultSSHPort uint = 7122 defaultSSHPort uint = 7122
defaultHTTPHost string = "127.0.0.1" defaultHTTPHost string = "127.0.0.1"
defaultHTTPPort uint = 7123 defaultHTTPPort uint = 7123
defaultDomain = "sarafu.local" defaultDomain = "sarafu.local"
) )
@@ -52,6 +52,7 @@ func SearchDomains() []string {
return ParsedDomains return ParsedDomains
} }
func Language() string { func Language() string {
return viseconfig.DefaultLanguage return viseconfig.DefaultLanguage
} }

View File

@@ -7,7 +7,6 @@ import (
"os" "os"
"path" "path"
"git.defalsify.org/vise.git/engine"
"git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/logging"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config" "git.grassecon.net/grassrootseconomics/sarafu-vise/config"
@@ -17,9 +16,8 @@ import (
) )
var ( var (
logg = logging.NewVanilla().WithContextKey("SessionId") logg = logging.NewVanilla().WithContextKey("SessionId")
scriptDir = path.Join("services", "registration") scriptDir = path.Join("services", "registration")
menuSeparator = ": "
) )
func main() { func main() {
@@ -27,8 +25,6 @@ func main() {
override := config.NewOverride() override := config.NewOverride()
var sessionId string var sessionId string
var size uint
var engineDebug bool
flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&sessionId, "session-id", "075xx2123", "session id")
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
@@ -36,8 +32,6 @@ func main() {
flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string") flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string")
flag.StringVar(&override.StateConn, "state", "?", "state store connection string") flag.StringVar(&override.StateConn, "state", "?", "state store connection string")
flag.BoolVar(&engineDebug, "d", false, "use engine debug output")
flag.UintVar(&size, "s", 160, "max size of output")
flag.Parse() flag.Parse()
config.Apply(override) config.Apply(override)
@@ -56,23 +50,13 @@ func main() {
os.Exit(1) os.Exit(1)
} }
cfg := engine.Config{
Root: "root",
SessionId: sessionId,
OutputSize: uint32(size),
FlagCount: uint32(128),
MenuSeparator: menuSeparator,
EngineDebug: engineDebug,
ResetOnEmptyInput: true,
}
x := cmd.NewCmd(sessionId, flagParser) x := cmd.NewCmd(sessionId, flagParser)
x = x.WithEngine(cfg)
err = x.Parse(flag.Args()) err = x.Parse(flag.Args())
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "cmd parse fail: %v\n", err) fmt.Fprintf(os.Stderr, "cmd parse fail: %v\n", err)
os.Exit(1) os.Exit(1)
} }
logg.Infof("start command", "conn", conns, "subcmd", x) logg.Infof("start command", "conn", conns, "subcmd", x)
menuStorageService := storage.NewMenuStorageService(conns) menuStorageService := storage.NewMenuStorageService(conns)
@@ -86,4 +70,5 @@ func main() {
fmt.Fprintf(os.Stderr, "cmd exec error: %v\n", err) fmt.Fprintf(os.Stderr, "cmd exec error: %v\n", err)
os.Exit(1) os.Exit(1)
} }
} }

View File

@@ -24,7 +24,7 @@ func formatItem(k []byte, v []byte, sessionId string) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
s := fmt.Sprintf("%v\n\t%v\n", o.Label, string(v)) s := fmt.Sprintf("%v\t%v\n", o.Label, string(v))
return s, nil return s, nil
} }

34
go.mod
View File

@@ -3,10 +3,10 @@ module git.grassecon.net/grassrootseconomics/sarafu-vise
go 1.23.4 go 1.23.4
require ( require (
git.defalsify.org/vise.git v0.3.2-0.20250401123711-d481b04a6805 git.defalsify.org/vise.git v0.3.2-0.20250507135825-a170e8a79da0
git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d 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.20250411080608-34957e5b6ff8 git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250428082711-5d221b8d565f
git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2 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
github.com/gofrs/uuid v4.4.0+incompatible github.com/gofrs/uuid v4.4.0+incompatible
@@ -19,24 +19,50 @@ require (
) )
require ( require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/alecthomas/participle/v2 v2.0.0 // indirect github.com/alecthomas/participle/v2 v2.0.0 // indirect
github.com/alecthomas/repr v0.2.0 // indirect github.com/alecthomas/repr v0.2.0 // indirect
github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c // indirect github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c // indirect
github.com/bits-and-blooms/bitset v1.14.3 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
github.com/ethereum/go-ethereum v1.14.9 // indirect
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grassrootseconomics/eth-custodial v1.3.0-beta // indirect github.com/grassrootseconomics/eth-custodial v1.3.0-beta // indirect
github.com/grassrootseconomics/ethutils v1.3.1 // indirect
github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 // indirect github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 // indirect
github.com/hexops/gotextdiff v1.0.3 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect
github.com/holiman/uint256 v1.3.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/joho/godotenv v1.5.1 // indirect github.com/joho/godotenv v1.5.1 // indirect
github.com/lmittmann/w3 v0.17.1 // indirect
github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a // indirect github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/objx v0.5.2 // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/sync v0.10.0 // indirect golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.29.0 // indirect golang.org/x/sys v0.29.0 // indirect
golang.org/x/text v0.21.0 // indirect golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.7.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
) )

90
go.sum
View File

@@ -1,23 +1,21 @@
git.defalsify.org/vise.git v0.3.1 h1:A6FhMcur09ft/JzUPGXR+KpA17fltfeBnasyvLMZmq4= git.defalsify.org/vise.git v0.3.2-0.20250425131748-8b84f59792ce h1:Uke2jQ4wG97gQKnTzxPyBGyhosrU1IWnRNFHtKVrmrk=
git.defalsify.org/vise.git v0.3.1/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck= git.defalsify.org/vise.git v0.3.2-0.20250425131748-8b84f59792ce/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck=
git.defalsify.org/vise.git v0.3.2-0.20250401123711-d481b04a6805 h1:FnT39aqXcP5YWhwPDBABopSjCu2SlbPFoOVitSpAVxU= git.defalsify.org/vise.git v0.3.2-0.20250507135825-a170e8a79da0 h1:ByRD+b39zVOjOzOf3I1z2L6MSiMZCZT8y0P8MMAAorY=
git.defalsify.org/vise.git v0.3.2-0.20250401123711-d481b04a6805/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck= git.defalsify.org/vise.git v0.3.2-0.20250507135825-a170e8a79da0/go.mod h1:flN+Gu+0BX0F6trZc5VpJcO4e6mj/+HUw0Z/UqVTFhk=
git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d h1:5mzLas+jxTUtusOKx4XvU+n2QvrV/mH17MnJRy46siQ= git.defalsify.org/vise.git v0.3.2-0.20250507172020-cb22240f1cb9 h1:4kjbYw25MHZe9fqSbujPzpFXrYutFfVipvLrcWYnYks=
git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d/go.mod h1:wgQJZGIS6QuNLHqDhcsvehsbn5PvgV7aziRebMnJi60= git.defalsify.org/vise.git v0.3.2-0.20250507172020-cb22240f1cb9/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck=
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310093912-8145b4bd004b h1:xiTpaqWWoF5qcnarY/9ZkT6aVdnKwqztb2gzIahJn4w= git.grassecon.net/grassrootseconomics/common v0.9.0-beta.1.0.20250417111317-2953f4c2f32e h1:DcC9qkNl9ny3hxQmsMK6W81+5R/j4ZwYUbvewMI/rlc=
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250310093912-8145b4bd004b/go.mod h1:gOn89ipaDcDvmQXRMQYKUqcw/sJcwVOPVt2eC6Geip8= git.grassecon.net/grassrootseconomics/common v0.9.0-beta.1.0.20250417111317-2953f4c2f32e/go.mod h1:wgQJZGIS6QuNLHqDhcsvehsbn5PvgV7aziRebMnJi60=
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250401111804-2eed990921c5 h1:DwBZHP4sebfHxK8EU2nlA2CXU81+a7Kj/pnC5vDPcf4= git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250428082711-5d221b8d565f h1:OAHCP3YR1C5h1WFnnEnLs5kn6jTxQHQYWYtQaMZJIMY=
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250401111804-2eed990921c5/go.mod h1:gOn89ipaDcDvmQXRMQYKUqcw/sJcwVOPVt2eC6Geip8= git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250428082711-5d221b8d565f/go.mod h1:gOn89ipaDcDvmQXRMQYKUqcw/sJcwVOPVt2eC6Geip8=
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250401115503-5b41c8dc6440 h1:eWrBZMM3pBMCFyRl4rO/aaR+OmOMFJxogNyFAFry+EM= git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2.0.20250408094335-e2d1f65bb306 h1:Jo+yWysWw/N5BJQtAyEMN8ePVvAyPHv+JG4lQti+1N4=
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250401115503-5b41c8dc6440/go.mod h1:gOn89ipaDcDvmQXRMQYKUqcw/sJcwVOPVt2eC6Geip8= git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2.0.20250408094335-e2d1f65bb306/go.mod h1:FdLwYtzsjOIcDiW4uDgDYnB4Wdzq12uJUe0QHSSPbSo=
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250401122510-441e289854ad h1:tYjanaCf6mF+iXRtDx5gckQm5vhZYx9N/JlNIBZj1m0=
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250401122510-441e289854ad/go.mod h1:gOn89ipaDcDvmQXRMQYKUqcw/sJcwVOPVt2eC6Geip8=
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250411080608-34957e5b6ff8 h1:Emesd0rybSLhPwZwqdvLsk/P9ZsT+7CQwQV/mrjQp3o=
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250411080608-34957e5b6ff8/go.mod h1:gOn89ipaDcDvmQXRMQYKUqcw/sJcwVOPVt2eC6Geip8=
git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2 h1:YFztSsexCUgFo6M0tbngRwYdgJd3LQV3RO/Jw09u3+k=
git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2/go.mod h1:6B6ByxXOiRY0NR7K02Bf3fEu7z+2c/6q8PFVNjC5G8w=
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=
git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694/go.mod h1:DpibtYpnT3nG4Kn556hRAkdu4+CtiI/6MbnQHal51mQ= git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694/go.mod h1:DpibtYpnT3nG4Kn556hRAkdu4+CtiI/6MbnQHal51mQ=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk=
github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g= github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g=
@@ -26,21 +24,54 @@ github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c h1:H9Nm+I7Cg/YVPpEV1RzU3Wq2pjamPc/UtHDgItcb7lE= github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c h1:H9Nm+I7Cg/YVPpEV1RzU3Wq2pjamPc/UtHDgItcb7lE=
github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c/go.mod h1:rGod7o6KPeJ+hyBpHfhi4v7blx9sf+QsHsA7KAsdN6U= github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c/go.mod h1:rGod7o6KPeJ+hyBpHfhi4v7blx9sf+QsHsA7KAsdN6U=
github.com/bits-and-blooms/bitset v1.14.3 h1:Gd2c8lSNf9pKXom5JtD7AaKO8o7fGQ2LtFj1436qilA=
github.com/bits-and-blooms/bitset v1.14.3/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ=
github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M=
github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY=
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c h1:uQYC5Z1mdLRPrZhHjHxufI8+2UG/i25QG92j0Er9p6I=
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs=
github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI=
github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=
github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA=
github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
github.com/ethereum/go-ethereum v1.14.9 h1:J7iwXDrtUyE9FUjUYbd4c9tyzwMh6dTJsKzo9i6SrwA=
github.com/ethereum/go-ethereum v1.14.9/go.mod h1:QeW+MtTpRdBEm2pUFoonByee8zfHv7kGp0wK0odvU1I=
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 h1:8NfxH2iXvJ60YRB8ChToFTUzl8awsc3cJ8CbLjGIl/A=
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk=
github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grassrootseconomics/eth-custodial v1.3.0-beta h1:twrMBhl89GqDUL9PlkzQxMP/6OST1BByrNDj+rqXDmU= github.com/grassrootseconomics/eth-custodial v1.3.0-beta h1:twrMBhl89GqDUL9PlkzQxMP/6OST1BByrNDj+rqXDmU=
github.com/grassrootseconomics/eth-custodial v1.3.0-beta/go.mod h1:7uhRcdnJplX4t6GKCEFkbeDhhjlcaGJeJqevbcvGLZo= github.com/grassrootseconomics/eth-custodial v1.3.0-beta/go.mod h1:7uhRcdnJplX4t6GKCEFkbeDhhjlcaGJeJqevbcvGLZo=
github.com/grassrootseconomics/ethutils v1.3.1 h1:LlQO90HjJkl7ejC8fv6jP7RJUrAm1j4VMMCYfsoIrhU=
github.com/grassrootseconomics/ethutils v1.3.1/go.mod h1:Wuv1VEZrkLIXqTSEYI3Nh9HG/ZHOUQ+U+xvWJ8QtjgQ=
github.com/grassrootseconomics/ussd-data-service v1.2.0-beta h1:fn1gwbWIwHVEBtUC2zi5OqTlfI/5gU1SMk0fgGixIXk= github.com/grassrootseconomics/ussd-data-service v1.2.0-beta h1:fn1gwbWIwHVEBtUC2zi5OqTlfI/5gU1SMk0fgGixIXk=
github.com/grassrootseconomics/ussd-data-service v1.2.0-beta/go.mod h1:omfI0QtUwIdpu9gMcUqLMCG8O1XWjqJGBx1qUMiGWC0= github.com/grassrootseconomics/ussd-data-service v1.2.0-beta/go.mod h1:omfI0QtUwIdpu9gMcUqLMCG8O1XWjqJGBx1qUMiGWC0=
github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo=
github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs=
github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
@@ -55,8 +86,13 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lmittmann/w3 v0.17.1 h1:zdXIimmNmYfqOFur+Jqc9Yqwtq6jwnsQufbTOnSAtW4=
github.com/lmittmann/w3 v0.17.1/go.mod h1:WVUGMbL83WYBu4Sge3SVlW3qIG4VaHe+S8+UUnwz9Eg=
github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a h1:0Q3H0YXzMHiciXtRcM+j0jiCe8WKPQHoRgQiRTnfcLY= github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a h1:0Q3H0YXzMHiciXtRcM+j0jiCe8WKPQHoRgQiRTnfcLY=
github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a/go.mod h1:CdTTBOYzS5E4mWS1N8NWP6AHI19MP0A2B18n3hLzRMk= github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a/go.mod h1:CdTTBOYzS5E4mWS1N8NWP6AHI19MP0A2B18n3hLzRMk=
github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY=
github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU=
github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU=
github.com/pashagolub/pgxmock/v4 v4.3.0 h1:DqT7fk0OCK6H0GvqtcMsLpv8cIwWqdxWgfZNLeHCb/s= github.com/pashagolub/pgxmock/v4 v4.3.0 h1:DqT7fk0OCK6H0GvqtcMsLpv8cIwWqdxWgfZNLeHCb/s=
github.com/pashagolub/pgxmock/v4 v4.3.0/go.mod h1:9VoVHXwS3XR/yPtKGzwQvwZX1kzGB9sM8SviDcHDa3A= github.com/pashagolub/pgxmock/v4 v4.3.0/go.mod h1:9VoVHXwS3XR/yPtKGzwQvwZX1kzGB9sM8SviDcHDa3A=
github.com/peteole/testdata-loader v0.3.0 h1:8jckE9KcyNHgyv/VPoaljvKZE0Rqr8+dPVYH6rfNr9I= github.com/peteole/testdata-loader v0.3.0 h1:8jckE9KcyNHgyv/VPoaljvKZE0Rqr8+dPVYH6rfNr9I=
@@ -66,6 +102,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
@@ -73,18 +111,32 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4=
github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -93,3 +145,5 @@ gopkg.in/leonelquinteros/gotext.v1 v1.3.1/go.mod h1:X1WlGDeAFIYsW6GjgMm4VwUwZ2Xj
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=

View File

@@ -29,9 +29,11 @@ import (
"git.grassecon.net/grassrootseconomics/sarafu-api/models" "git.grassecon.net/grassrootseconomics/sarafu-api/models"
"git.grassecon.net/grassrootseconomics/sarafu-api/remote" "git.grassecon.net/grassrootseconomics/sarafu-api/remote"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config" "git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"git.grassecon.net/grassrootseconomics/sarafu-vise/internal/sms"
"git.grassecon.net/grassrootseconomics/sarafu-vise/profile" "git.grassecon.net/grassrootseconomics/sarafu-vise/profile"
"git.grassecon.net/grassrootseconomics/sarafu-vise/store" "git.grassecon.net/grassrootseconomics/sarafu-vise/store"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
"github.com/grassrootseconomics/ethutils"
dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api"
) )
@@ -77,18 +79,28 @@ type MenuHandlers struct {
flagManager *FlagManager flagManager *FlagManager
accountService remote.AccountService accountService remote.AccountService
prefixDb storedb.PrefixDb prefixDb storedb.PrefixDb
smsService sms.SmsService
logDb store.LogDb
profile *profile.Profile profile *profile.Profile
ReplaceSeparatorFunc func(string) string ReplaceSeparatorFunc func(string) string
} }
// NewHandlers creates a new instance of the Handlers struct with the provided dependencies. // NewHandlers creates a new instance of the Handlers struct with the provided dependencies.
func NewMenuHandlers(appFlags *FlagManager, userdataStore db.Db, accountService remote.AccountService, replaceSeparatorFunc func(string) string) (*MenuHandlers, error) { func NewMenuHandlers(appFlags *FlagManager, userdataStore db.Db, logdb db.Db, accountService remote.AccountService, replaceSeparatorFunc func(string) string) (*MenuHandlers, error) {
if userdataStore == nil { if userdataStore == nil {
return nil, fmt.Errorf("cannot create handler with nil userdata store") return nil, fmt.Errorf("cannot create handler with nil userdata store")
} }
userDb := &store.UserDataStore{ userDb := &store.UserDataStore{
Db: userdataStore, Db: userdataStore,
} }
smsservice := sms.SmsService{
Accountservice: accountService,
Userdatastore: *userDb,
}
logDb := store.LogDb{
Db: logdb,
}
// Instantiate the SubPrefixDb with "DATATYPE_USERDATA" prefix // Instantiate the SubPrefixDb with "DATATYPE_USERDATA" prefix
prefix := storedb.ToBytes(db.DATATYPE_USERDATA) prefix := storedb.ToBytes(db.DATATYPE_USERDATA)
@@ -98,7 +110,9 @@ func NewMenuHandlers(appFlags *FlagManager, userdataStore db.Db, accountService
userdataStore: userDb, userdataStore: userDb,
flagManager: appFlags, flagManager: appFlags,
accountService: accountService, accountService: accountService,
smsService: smsservice,
prefixDb: prefixDb, prefixDb: prefixDb,
logDb: logDb,
profile: &profile.Profile{Max: 6}, profile: &profile.Profile{Max: 6},
ReplaceSeparatorFunc: replaceSeparatorFunc, ReplaceSeparatorFunc: replaceSeparatorFunc,
} }
@@ -186,10 +200,16 @@ func (h *MenuHandlers) SetLanguage(ctx context.Context, sym string, input []byte
// handles the account creation when no existing account is present for the session and stores associated data in the user data store. // handles the account creation when no existing account is present for the session and stores associated data in the user data store.
func (h *MenuHandlers) createAccountNoExist(ctx context.Context, sessionId string, res *resource.Result) error { func (h *MenuHandlers) createAccountNoExist(ctx context.Context, sessionId string, res *resource.Result) error {
flag_account_created, _ := h.flagManager.GetFlag("flag_account_created") flag_account_created, _ := h.flagManager.GetFlag("flag_account_created")
flag_account_creation_failed, _ := h.flagManager.GetFlag("flag_account_creation_failed")
r, err := h.accountService.CreateAccount(ctx) r, err := h.accountService.CreateAccount(ctx)
if err != nil { if err != nil {
return err res.FlagSet = append(res.FlagSet, flag_account_creation_failed)
logg.ErrorCtxf(ctx, "failed to create an account", "error", err)
return nil
} }
res.FlagReset = append(res.FlagReset, flag_account_creation_failed)
trackingId := r.TrackingId trackingId := r.TrackingId
publicKey := r.PublicKey publicKey := r.PublicKey
@@ -199,11 +219,16 @@ func (h *MenuHandlers) createAccountNoExist(ctx context.Context, sessionId strin
storedb.DATA_ACCOUNT_ALIAS: "", storedb.DATA_ACCOUNT_ALIAS: "",
} }
store := h.userdataStore store := h.userdataStore
logdb := h.logDb
for key, value := range data { for key, value := range data {
err = store.WriteEntry(ctx, sessionId, key, []byte(value)) err = store.WriteEntry(ctx, sessionId, key, []byte(value))
if err != nil { if err != nil {
return err return err
} }
err = logdb.WriteLogEntry(ctx, sessionId, key, []byte(value))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write log entry", "key", key, "value", value)
}
} }
publicKeyNormalized, err := hex.NormalizeHex(publicKey) publicKeyNormalized, err := hex.NormalizeHex(publicKey)
if err != nil { if err != nil {
@@ -213,6 +238,12 @@ func (h *MenuHandlers) createAccountNoExist(ctx context.Context, sessionId strin
if err != nil { if err != nil {
return err return err
} }
err = logdb.WriteLogEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write log entry", "key", storedb.DATA_PUBLIC_KEY_REVERSE, "value", sessionId)
}
res.FlagSet = append(res.FlagSet, flag_account_created) res.FlagSet = append(res.FlagSet, flag_account_created)
return nil return nil
} }
@@ -382,12 +413,19 @@ func (h *MenuHandlers) SaveTemporaryPin(ctx context.Context, sym string, input [
} }
store := h.userdataStore store := h.userdataStore
logdb := h.logDb
err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(hashedPIN)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(hashedPIN))
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to write temporaryAccountPIN entry with", "key", storedb.DATA_TEMPORARY_VALUE, "value", accountPIN, "error", err) logg.ErrorCtxf(ctx, "failed to write temporaryAccountPIN entry with", "key", storedb.DATA_TEMPORARY_VALUE, "value", accountPIN, "error", err)
return res, err return res, err
} }
err = logdb.WriteLogEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(hashedPIN))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write temporaryAccountPIN log entry", "key", storedb.DATA_TEMPORARY_VALUE, "value", accountPIN, "error", err)
}
return res, nil return res, nil
} }
@@ -399,6 +437,14 @@ func (h *MenuHandlers) ResetInvalidPIN(ctx context.Context, sym string, input []
return res, nil return res, nil
} }
// ResetApiCallFailure resets the api call failure flag
func (h *MenuHandlers) ResetApiCallFailure(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result
flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error")
res.FlagReset = append(res.FlagReset, flag_api_error)
return res, nil
}
// ConfirmPinChange validates user's new PIN. If input matches the temporary PIN, saves it as the new account PIN. // ConfirmPinChange validates user's new PIN. If input matches the temporary PIN, saves it as the new account PIN.
func (h *MenuHandlers) ConfirmPinChange(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *MenuHandlers) ConfirmPinChange(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
@@ -415,6 +461,7 @@ func (h *MenuHandlers) ConfirmPinChange(ctx context.Context, sym string, input [
} }
store := h.userdataStore store := h.userdataStore
logdb := h.logDb
hashedTemporaryPin, err := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) hashedTemporaryPin, err := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE)
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to read hashedTemporaryPin entry with", "key", storedb.DATA_TEMPORARY_VALUE, "error", err) logg.ErrorCtxf(ctx, "failed to read hashedTemporaryPin entry with", "key", storedb.DATA_TEMPORARY_VALUE, "error", err)
@@ -438,6 +485,12 @@ func (h *MenuHandlers) ConfirmPinChange(ctx context.Context, sym string, input [
logg.ErrorCtxf(ctx, "failed to write DATA_ACCOUNT_PIN entry with", "key", storedb.DATA_ACCOUNT_PIN, "hashedPIN value", hashedTemporaryPin, "error", err) logg.ErrorCtxf(ctx, "failed to write DATA_ACCOUNT_PIN entry with", "key", storedb.DATA_ACCOUNT_PIN, "hashedPIN value", hashedTemporaryPin, "error", err)
return res, err return res, err
} }
err = logdb.WriteLogEntry(ctx, sessionId, storedb.DATA_ACCOUNT_PIN, []byte(hashedTemporaryPin))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write AccountPIN log entry", "key", storedb.DATA_ACCOUNT_PIN, "value", hashedTemporaryPin, "error", err)
}
// set the DATA_SELF_PIN_RESET as 0 // set the DATA_SELF_PIN_RESET as 0
err = store.WriteEntry(ctx, sessionId, storedb.DATA_SELF_PIN_RESET, []byte("0")) err = store.WriteEntry(ctx, sessionId, storedb.DATA_SELF_PIN_RESET, []byte("0"))
if err != nil { if err != nil {
@@ -458,6 +511,7 @@ func (h *MenuHandlers) ValidateBlockedNumber(ctx context.Context, sym string, in
flag_unregistered_number, _ := h.flagManager.GetFlag("flag_unregistered_number") flag_unregistered_number, _ := h.flagManager.GetFlag("flag_unregistered_number")
store := h.userdataStore store := h.userdataStore
logdb := h.logDb
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")
@@ -493,6 +547,11 @@ func (h *MenuHandlers) ValidateBlockedNumber(ctx context.Context, sym string, in
return res, nil return res, nil
} }
err = logdb.WriteLogEntry(ctx, sessionId, storedb.DATA_BLOCKED_NUMBER, []byte(formattedNumber))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write blocked number log entry", "key", storedb.DATA_BLOCKED_NUMBER, "value", formattedNumber, "error", err)
}
return res, nil return res, nil
} }
@@ -502,7 +561,10 @@ func (h *MenuHandlers) ValidateBlockedNumber(ctx context.Context, sym string, in
// 3. Resetting the DATA_INCORRECT_PIN_ATTEMPTS to 0 for the blocked phone number // 3. Resetting the DATA_INCORRECT_PIN_ATTEMPTS to 0 for the blocked phone number
func (h *MenuHandlers) ResetOthersPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *MenuHandlers) ResetOthersPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
store := h.userdataStore store := h.userdataStore
smsservice := h.smsService
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")
@@ -524,7 +586,15 @@ func (h *MenuHandlers) ResetOthersPin(ctx context.Context, sym string, input []b
logg.ErrorCtxf(ctx, "failed to reset incorrect PIN attempts", "key", storedb.DATA_INCORRECT_PIN_ATTEMPTS, "error", err) logg.ErrorCtxf(ctx, "failed to reset incorrect PIN attempts", "key", storedb.DATA_INCORRECT_PIN_ATTEMPTS, "error", err)
return res, err return res, err
} }
blockedPhoneStr := string(blockedPhonenumber)
//Trigger an SMS to inform a user that the blocked account has been reset
if phone.IsValidPhoneNumber(blockedPhoneStr) {
err = smsservice.SendPINResetSMS(ctx, sessionId, blockedPhoneStr)
if err != nil {
logg.DebugCtxf(ctx, "Failed to send PIN reset SMS", "error", err)
return res, nil
}
}
return res, nil return res, nil
} }
@@ -608,6 +678,8 @@ func (h *MenuHandlers) VerifyCreatePin(ctx context.Context, sym string, input []
} }
store := h.userdataStore store := h.userdataStore
logdb := h.logDb
hashedTemporaryPin, err := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) hashedTemporaryPin, err := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE)
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to read hashedTemporaryPin entry with", "key", storedb.DATA_TEMPORARY_VALUE, "error", err) logg.ErrorCtxf(ctx, "failed to read hashedTemporaryPin entry with", "key", storedb.DATA_TEMPORARY_VALUE, "error", err)
@@ -634,6 +706,11 @@ func (h *MenuHandlers) VerifyCreatePin(ctx context.Context, sym string, input []
return res, err return res, err
} }
err = logdb.WriteLogEntry(ctx, sessionId, storedb.DATA_ACCOUNT_PIN, []byte(hashedTemporaryPin))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write DATA_ACCOUNT_PIN log entry", "key", storedb.DATA_ACCOUNT_PIN, "value", hashedTemporaryPin, "error", err)
}
return res, nil return res, nil
} }
@@ -646,7 +723,10 @@ func (h *MenuHandlers) SaveFirstname(ctx context.Context, sym string, input []by
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
firstName := string(input) firstName := string(input)
store := h.userdataStore store := h.userdataStore
logdb := h.logDb
flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update")
flag_firstname_set, _ := h.flagManager.GetFlag("flag_firstname_set") flag_firstname_set, _ := h.flagManager.GetFlag("flag_firstname_set")
@@ -664,6 +744,11 @@ func (h *MenuHandlers) SaveFirstname(ctx context.Context, sym string, input []by
return res, err return res, err
} }
res.FlagSet = append(res.FlagSet, flag_firstname_set) res.FlagSet = append(res.FlagSet, flag_firstname_set)
err = logdb.WriteLogEntry(ctx, sessionId, storedb.DATA_FIRST_NAME, []byte(temporaryFirstName))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write firtname db log entry", "key", storedb.DATA_FIRST_NAME, "value", temporaryFirstName)
}
} else { } else {
if firstNameSet { if firstNameSet {
err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(firstName)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(firstName))
@@ -689,6 +774,7 @@ func (h *MenuHandlers) SaveFamilyname(ctx context.Context, sym string, input []b
} }
store := h.userdataStore store := h.userdataStore
logdb := h.logDb
familyName := string(input) familyName := string(input)
flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update")
@@ -708,6 +794,11 @@ func (h *MenuHandlers) SaveFamilyname(ctx context.Context, sym string, input []b
return res, err return res, err
} }
res.FlagSet = append(res.FlagSet, flag_familyname_set) res.FlagSet = append(res.FlagSet, flag_familyname_set)
err = logdb.WriteLogEntry(ctx, sessionId, storedb.DATA_FAMILY_NAME, []byte(temporaryFamilyName))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write firtname db log entry", "key", storedb.DATA_FAMILY_NAME, "value", temporaryFamilyName)
}
} else { } else {
if familyNameSet { if familyNameSet {
err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(familyName)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(familyName))
@@ -764,6 +855,8 @@ func (h *MenuHandlers) SaveYob(ctx context.Context, sym string, input []byte) (r
} }
yob := string(input) yob := string(input)
store := h.userdataStore store := h.userdataStore
logdb := h.logDb
flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update")
flag_yob_set, _ := h.flagManager.GetFlag("flag_yob_set") flag_yob_set, _ := h.flagManager.GetFlag("flag_yob_set")
@@ -782,6 +875,11 @@ func (h *MenuHandlers) SaveYob(ctx context.Context, sym string, input []byte) (r
return res, err return res, err
} }
res.FlagSet = append(res.FlagSet, flag_yob_set) res.FlagSet = append(res.FlagSet, flag_yob_set)
err = logdb.WriteLogEntry(ctx, sessionId, storedb.DATA_YOB, []byte(temporaryYob))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write yob db log entry", "key", storedb.DATA_YOB, "value", temporaryYob)
}
} else { } else {
if yobSet { if yobSet {
err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(yob)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(yob))
@@ -807,6 +905,7 @@ func (h *MenuHandlers) SaveLocation(ctx context.Context, sym string, input []byt
} }
location := string(input) location := string(input)
store := h.userdataStore store := h.userdataStore
logdb := h.logDb
flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update")
flag_location_set, _ := h.flagManager.GetFlag("flag_location_set") flag_location_set, _ := h.flagManager.GetFlag("flag_location_set")
@@ -825,6 +924,11 @@ func (h *MenuHandlers) SaveLocation(ctx context.Context, sym string, input []byt
return res, err return res, err
} }
res.FlagSet = append(res.FlagSet, flag_location_set) res.FlagSet = append(res.FlagSet, flag_location_set)
err = logdb.WriteLogEntry(ctx, sessionId, storedb.DATA_LOCATION, []byte(temporaryLocation))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write location db log entry", "key", storedb.DATA_LOCATION, "value", temporaryLocation)
}
} else { } else {
if locationSet { if locationSet {
err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(location)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(location))
@@ -852,6 +956,7 @@ func (h *MenuHandlers) SaveGender(ctx context.Context, sym string, input []byte)
} }
gender := strings.Split(symbol, "_")[1] gender := strings.Split(symbol, "_")[1]
store := h.userdataStore store := h.userdataStore
logdb := h.logDb
flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update")
flag_gender_set, _ := h.flagManager.GetFlag("flag_gender_set") flag_gender_set, _ := h.flagManager.GetFlag("flag_gender_set")
@@ -870,6 +975,12 @@ func (h *MenuHandlers) SaveGender(ctx context.Context, sym string, input []byte)
return res, err return res, err
} }
res.FlagSet = append(res.FlagSet, flag_gender_set) res.FlagSet = append(res.FlagSet, flag_gender_set)
err = logdb.WriteLogEntry(ctx, sessionId, storedb.DATA_GENDER, []byte(temporaryGender))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write gender db log entry", "key", storedb.DATA_TEMPORARY_VALUE, "value", temporaryGender)
}
} else { } else {
if genderSet { if genderSet {
err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(gender)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(gender))
@@ -896,6 +1007,7 @@ func (h *MenuHandlers) SaveOfferings(ctx context.Context, sym string, input []by
offerings := string(input) offerings := string(input)
store := h.userdataStore store := h.userdataStore
logdb := h.logDb
flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update")
flag_offerings_set, _ := h.flagManager.GetFlag("flag_offerings_set") flag_offerings_set, _ := h.flagManager.GetFlag("flag_offerings_set")
@@ -915,6 +1027,11 @@ func (h *MenuHandlers) SaveOfferings(ctx context.Context, sym string, input []by
return res, err return res, err
} }
res.FlagSet = append(res.FlagSet, flag_offerings_set) res.FlagSet = append(res.FlagSet, flag_offerings_set)
err = logdb.WriteLogEntry(ctx, sessionId, storedb.DATA_FIRST_NAME, []byte(temporaryOfferings))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write offerings db log entry", "key", storedb.DATA_OFFERINGS, "value", offerings)
}
} else { } else {
if offeringsSet { if offeringsSet {
err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(offerings)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(offerings))
@@ -1214,17 +1331,30 @@ func (h *MenuHandlers) ResetAccountAuthorized(ctx context.Context, sym string, i
return res, nil return res, nil
} }
// CheckIdentifier retrieves the PublicKey from the JSON data file. // CheckIdentifier retrieves the Public key from the userdatastore under the key: DATA_PUBLIC_KEY and triggers an sms that
// will be sent to the associated session id
func (h *MenuHandlers) CheckIdentifier(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *MenuHandlers) CheckIdentifier(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
smsservice := h.smsService
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")
} }
store := h.userdataStore store := h.userdataStore
publicKey, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) publicKey, err := store.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY)
if err != nil {
logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", storedb.DATA_PUBLIC_KEY, "error", err)
return res, err
}
res.Content = string(publicKey) res.Content = string(publicKey)
//trigger an address sms to be delivered to the associated session id
err = smsservice.SendAddressSMS(ctx)
if err != nil {
logg.DebugCtxf(ctx, "Failed to trigger an address sms", "error", err)
return res, nil
}
return res, nil return res, nil
} }
@@ -1325,7 +1455,7 @@ func (h *MenuHandlers) CheckAccountStatus(ctx context.Context, sym string, input
if err != nil { if err != nil {
res.FlagSet = append(res.FlagSet, flag_api_error) res.FlagSet = append(res.FlagSet, flag_api_error)
logg.ErrorCtxf(ctx, "failed on TrackAccountStatus", "error", err) logg.ErrorCtxf(ctx, "failed on TrackAccountStatus", "error", err)
return res, err return res, nil
} }
res.FlagReset = append(res.FlagReset, flag_api_error) res.FlagReset = append(res.FlagReset, flag_api_error)
@@ -1491,8 +1621,10 @@ func (h *MenuHandlers) ValidateRecipient(ctx context.Context, sym string, input
} }
flag_invalid_recipient, _ := h.flagManager.GetFlag("flag_invalid_recipient") flag_invalid_recipient, _ := h.flagManager.GetFlag("flag_invalid_recipient")
flag_invalid_recipient_with_invite, _ := h.flagManager.GetFlag("flag_invalid_recipient_with_invite") flag_invalid_recipient_with_invite, _ := h.flagManager.GetFlag("flag_invalid_recipient_with_invite")
flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error")
recipient := string(input) // remove white spaces
recipient := strings.ReplaceAll(string(input), " ", "")
if recipient != "0" { if recipient != "0" {
recipientType, err := identity.CheckRecipient(recipient) recipientType, err := identity.CheckRecipient(recipient)
@@ -1542,8 +1674,11 @@ func (h *MenuHandlers) ValidateRecipient(ctx context.Context, sym string, input
} }
case "address": case "address":
// checksum the address
address := ethutils.ChecksumAddress(recipient)
// Save the valid Ethereum address as the recipient // Save the valid Ethereum address as the recipient
err = store.WriteEntry(ctx, sessionId, storedb.DATA_RECIPIENT, []byte(recipient)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_RECIPIENT, []byte(address))
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to write recipient entry with", "key", storedb.DATA_RECIPIENT, "value", recipient, "error", err) logg.ErrorCtxf(ctx, "failed to write recipient entry with", "key", storedb.DATA_RECIPIENT, "value", recipient, "error", err)
return res, err return res, err
@@ -1564,10 +1699,13 @@ func (h *MenuHandlers) ValidateRecipient(ctx context.Context, sym string, input
logg.InfoCtxf(ctx, "Resolving with fqdn alias", "alias", fqdn) logg.InfoCtxf(ctx, "Resolving with fqdn alias", "alias", fqdn)
AliasAddress, err = h.accountService.CheckAliasAddress(ctx, fqdn) AliasAddress, err = h.accountService.CheckAliasAddress(ctx, fqdn)
if err == nil { if err == nil {
res.FlagReset = append(res.FlagReset, flag_api_error)
AliasAddressResult = AliasAddress.Address AliasAddressResult = AliasAddress.Address
continue continue
} else { } else {
res.FlagSet = append(res.FlagSet, flag_api_error)
logg.ErrorCtxf(ctx, "failed to resolve alias", "alias", recipient, "error_alias_check", err) logg.ErrorCtxf(ctx, "failed to resolve alias", "alias", recipient, "error_alias_check", err)
return res, nil
} }
} }
} }
@@ -1621,6 +1759,7 @@ func (h *MenuHandlers) TransactionReset(ctx context.Context, sym string, input [
func (h *MenuHandlers) InviteValidRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *MenuHandlers) InviteValidRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
store := h.userdataStore store := h.userdataStore
smsservice := h.smsService
sessionId, ok := ctx.Value("SessionId").(string) sessionId, ok := ctx.Value("SessionId").(string)
if !ok { if !ok {
@@ -1642,7 +1781,7 @@ func (h *MenuHandlers) InviteValidRecipient(ctx context.Context, sym string, inp
return res, nil return res, nil
} }
_, err = h.accountService.SendUpsellSMS(ctx, sessionId, string(recipient)) _, err = smsservice.Accountservice.SendUpsellSMS(ctx, sessionId, string(recipient))
if err != nil { if err != nil {
res.Content = l.Get("Your invite request for %s to Sarafu Network failed. Please try again later.", string(recipient)) res.Content = l.Get("Your invite request for %s to Sarafu Network failed. Please try again later.", string(recipient))
return res, nil return res, nil
@@ -1880,6 +2019,7 @@ func (h *MenuHandlers) InitiateTransaction(ctx context.Context, sym string, inpu
func (h *MenuHandlers) ManageVouchers(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *MenuHandlers) ManageVouchers(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
userStore := h.userdataStore userStore := h.userdataStore
logdb := h.logDb
sessionId, ok := ctx.Value("SessionId").(string) sessionId, ok := ctx.Value("SessionId").(string)
if !ok { if !ok {
@@ -1887,6 +2027,7 @@ func (h *MenuHandlers) ManageVouchers(ctx context.Context, sym string, input []b
} }
flag_no_active_voucher, _ := h.flagManager.GetFlag("flag_no_active_voucher") flag_no_active_voucher, _ := h.flagManager.GetFlag("flag_no_active_voucher")
flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error")
publicKey, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) publicKey, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY)
if err != nil { if err != nil {
@@ -1897,9 +2038,10 @@ func (h *MenuHandlers) ManageVouchers(ctx context.Context, sym string, input []b
// Fetch vouchers from API // Fetch vouchers from API
vouchersResp, err := h.accountService.FetchVouchers(ctx, string(publicKey)) vouchersResp, err := h.accountService.FetchVouchers(ctx, string(publicKey))
if err != nil { if err != nil {
res.FlagSet = append(res.FlagSet, flag_no_active_voucher) res.FlagSet = append(res.FlagSet, flag_api_error)
return res, nil return res, nil
} }
res.FlagReset = append(res.FlagReset, flag_api_error)
if len(vouchersResp) == 0 { if len(vouchersResp) == 0 {
res.FlagSet = append(res.FlagSet, flag_no_active_voucher) res.FlagSet = append(res.FlagSet, flag_no_active_voucher)
@@ -1934,6 +2076,10 @@ func (h *MenuHandlers) ManageVouchers(ctx context.Context, sym string, input []b
logg.ErrorCtxf(ctx, "Failed to write active voucher data", "key", key, "error", err) logg.ErrorCtxf(ctx, "Failed to write active voucher data", "key", key, "error", err)
return res, err return res, err
} }
err = logdb.WriteLogEntry(ctx, sessionId, key, []byte(value))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write voucher db log entry", "key", key, "value", value)
}
} }
logg.InfoCtxf(ctx, "Default voucher set", "symbol", defaultSym, "balance", defaultBal, "decimals", defaultDec, "address", defaultAddr) logg.InfoCtxf(ctx, "Default voucher set", "symbol", defaultSym, "balance", defaultBal, "decimals", defaultDec, "address", defaultAddr)
@@ -2035,10 +2181,6 @@ func (h *MenuHandlers) ViewVoucher(ctx context.Context, sym string, input []byte
flag_incorrect_voucher, _ := h.flagManager.GetFlag("flag_incorrect_voucher") flag_incorrect_voucher, _ := h.flagManager.GetFlag("flag_incorrect_voucher")
inputStr := string(input) inputStr := string(input)
if inputStr == "0" || inputStr == "99" {
res.FlagReset = append(res.FlagReset, flag_incorrect_voucher)
return res, nil
}
metadata, err := store.GetVoucherData(ctx, h.userdataStore, sessionId, inputStr) metadata, err := store.GetVoucherData(ctx, h.userdataStore, sessionId, inputStr)
if err != nil { if err != nil {
@@ -2110,6 +2252,7 @@ func (h *MenuHandlers) GetVoucherDetails(ctx context.Context, sym string, input
res.FlagSet = append(res.FlagSet, flag_api_error) res.FlagSet = append(res.FlagSet, flag_api_error)
return res, nil return res, nil
} }
res.FlagReset = append(res.FlagReset, flag_api_error)
res.Content = fmt.Sprintf( res.Content = fmt.Sprintf(
"Name: %s\nSymbol: %s\nCommodity: %s\nLocation: %s", voucherData.TokenName, voucherData.TokenSymbol, voucherData.TokenCommodity, voucherData.TokenLocation, "Name: %s\nSymbol: %s\nCommodity: %s\nLocation: %s", voucherData.TokenName, voucherData.TokenSymbol, voucherData.TokenCommodity, voucherData.TokenLocation,
@@ -2130,6 +2273,7 @@ func (h *MenuHandlers) CheckTransactions(ctx context.Context, sym string, input
flag_api_error, _ := h.flagManager.GetFlag("flag_api_error") flag_api_error, _ := h.flagManager.GetFlag("flag_api_error")
userStore := h.userdataStore userStore := h.userdataStore
logdb := h.logDb
publicKey, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) publicKey, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY)
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", storedb.DATA_PUBLIC_KEY, "error", err) logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", storedb.DATA_PUBLIC_KEY, "error", err)
@@ -2143,6 +2287,7 @@ func (h *MenuHandlers) CheckTransactions(ctx context.Context, sym string, input
logg.ErrorCtxf(ctx, "failed on FetchTransactions", "error", err) logg.ErrorCtxf(ctx, "failed on FetchTransactions", "error", err)
return res, err return res, err
} }
res.FlagReset = append(res.FlagReset, flag_api_error)
// Return if there are no transactions // Return if there are no transactions
if len(transactionsResp) == 0 { if len(transactionsResp) == 0 {
@@ -2169,6 +2314,10 @@ func (h *MenuHandlers) CheckTransactions(ctx context.Context, sym string, input
logg.ErrorCtxf(ctx, "failed to write to prefixDb", "error", err) logg.ErrorCtxf(ctx, "failed to write to prefixDb", "error", err)
return res, err return res, err
} }
err = logdb.WriteLogEntry(ctx, sessionId, key, []byte(value))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write tx db log entry", "key", key, "value", value)
}
} }
res.FlagReset = append(res.FlagReset, flag_no_transfers) res.FlagReset = append(res.FlagReset, flag_no_transfers)
@@ -2380,6 +2529,8 @@ func (h *MenuHandlers) RequestCustomAlias(ctx context.Context, sym string, input
return res, nil return res, nil
} }
flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error")
store := h.userdataStore store := h.userdataStore
aliasHint, err := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) aliasHint, err := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE)
if err != nil { if err != nil {
@@ -2403,9 +2554,12 @@ func (h *MenuHandlers) RequestCustomAlias(ctx context.Context, sym string, input
sanitizedInput := sanitizeAliasHint(string(input)) sanitizedInput := sanitizeAliasHint(string(input))
aliasResult, err := h.accountService.RequestAlias(ctx, string(pubKey), sanitizedInput) aliasResult, err := h.accountService.RequestAlias(ctx, string(pubKey), sanitizedInput)
if err != nil { if err != nil {
res.FlagSet = append(res.FlagSet, flag_api_error)
logg.ErrorCtxf(ctx, "failed to retrieve alias", "alias", string(aliasHint), "error_alias_request", err) logg.ErrorCtxf(ctx, "failed to retrieve alias", "alias", string(aliasHint), "error_alias_request", err)
return res, fmt.Errorf("Failed to retrieve alias: %s", err.Error()) return res, nil
} }
res.FlagReset = append(res.FlagReset, flag_api_error)
alias := aliasResult.Alias alias := aliasResult.Alias
logg.InfoCtxf(ctx, "Suggested alias ", "alias", alias) logg.InfoCtxf(ctx, "Suggested alias ", "alias", alias)
@@ -2451,6 +2605,7 @@ func (h *MenuHandlers) GetSuggestedAlias(ctx context.Context, sym string, input
func (h *MenuHandlers) ConfirmNewAlias(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *MenuHandlers) ConfirmNewAlias(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
store := h.userdataStore store := h.userdataStore
logdb := h.logDb
flag_alias_set, _ := h.flagManager.GetFlag("flag_alias_set") flag_alias_set, _ := h.flagManager.GetFlag("flag_alias_set")
@@ -2469,6 +2624,11 @@ func (h *MenuHandlers) ConfirmNewAlias(ctx context.Context, sym string, input []
return res, err return res, err
} }
err = logdb.WriteLogEntry(ctx, sessionId, storedb.DATA_ACCOUNT_ALIAS, []byte(newAlias))
if err != nil {
logg.DebugCtxf(ctx, "Failed to write account alias db log entry", "key", storedb.DATA_ACCOUNT_ALIAS, "value", newAlias)
}
res.FlagSet = append(res.FlagSet, flag_alias_set) res.FlagSet = append(res.FlagSet, flag_alias_set)
return res, nil return res, nil
} }

View File

@@ -62,6 +62,25 @@ func InitializeTestStore(t *testing.T) (context.Context, *store.UserDataStore) {
return ctx, store return ctx, store
} }
// InitializeTestLogdbStore sets up and returns an in-memory database and logdb store.
func InitializeTestLogdbStore(t *testing.T) (context.Context, *store.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
logdb := &store.UserDataStore{Db: db}
t.Cleanup(func() {
db.Close(ctx) // Ensure the DB is closed after each test
})
return ctx, logdb
}
func InitializeTestSubPrefixDb(t *testing.T, ctx context.Context) *storedb.SubPrefixDb { func InitializeTestSubPrefixDb(t *testing.T, ctx context.Context) *storedb.SubPrefixDb {
db := memdb.NewMemDb() db := memdb.NewMemDb()
err := db.Connect(ctx, "") err := db.Connect(ctx, "")
@@ -76,6 +95,7 @@ func InitializeTestSubPrefixDb(t *testing.T, ctx context.Context) *storedb.SubPr
func TestNewMenuHandlers(t *testing.T) { func TestNewMenuHandlers(t *testing.T) {
_, store := InitializeTestStore(t) _, store := InitializeTestStore(t)
_, logdb := InitializeTestLogdbStore(t)
fm, err := NewFlagManager(flagsPath) fm, err := NewFlagManager(flagsPath)
if err != nil { if err != nil {
@@ -86,7 +106,7 @@ func TestNewMenuHandlers(t *testing.T) {
// Test case for valid UserDataStore // Test case for valid UserDataStore
t.Run("Valid UserDataStore", func(t *testing.T) { t.Run("Valid UserDataStore", func(t *testing.T) {
handlers, err := NewMenuHandlers(fm, store, &accountService, mockReplaceSeparator) handlers, err := NewMenuHandlers(fm, store, logdb, &accountService, mockReplaceSeparator)
if err != nil { if err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
@@ -110,7 +130,7 @@ func TestNewMenuHandlers(t *testing.T) {
// Test case for nil UserDataStore // Test case for nil UserDataStore
t.Run("Nil UserDataStore", func(t *testing.T) { t.Run("Nil UserDataStore", func(t *testing.T) {
handlers, err := NewMenuHandlers(fm, nil, &accountService, mockReplaceSeparator) handlers, err := NewMenuHandlers(fm, nil, logdb, &accountService, mockReplaceSeparator)
if err == nil { if err == nil {
t.Fatal("expected an error, got none") t.Fatal("expected an error, got none")
} }
@@ -192,8 +212,13 @@ func TestInit(t *testing.T) {
func TestCreateAccount(t *testing.T) { func TestCreateAccount(t *testing.T) {
sessionId := "session123" sessionId := "session123"
ctx, store := InitializeTestStore(t) ctx, userStore := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
_, logdb := InitializeTestLogdbStore(t)
logDb := store.LogDb{
Db: logdb,
}
fm, err := NewFlagManager(flagsPath) fm, err := NewFlagManager(flagsPath)
if err != nil { if err != nil {
@@ -201,6 +226,8 @@ func TestCreateAccount(t *testing.T) {
} }
flag_account_created, err := fm.GetFlag("flag_account_created") flag_account_created, err := fm.GetFlag("flag_account_created")
flag_account_creation_failed, _ := fm.GetFlag("flag_account_creation_failed")
if err != nil { if err != nil {
t.Logf(err.Error()) t.Logf(err.Error())
} }
@@ -217,7 +244,8 @@ func TestCreateAccount(t *testing.T) {
PublicKey: "0xD3adB33f", PublicKey: "0xD3adB33f",
}, },
expectedResult: resource.Result{ expectedResult: resource.Result{
FlagSet: []uint32{flag_account_created}, FlagSet: []uint32{flag_account_created},
FlagReset: []uint32{flag_account_creation_failed},
}, },
}, },
} }
@@ -226,8 +254,9 @@ func TestCreateAccount(t *testing.T) {
mockAccountService := new(mocks.MockAccountService) mockAccountService := new(mocks.MockAccountService)
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: userStore,
accountService: mockAccountService, accountService: mockAccountService,
logDb: logDb,
flagManager: fm, flagManager: fm,
} }
@@ -265,8 +294,13 @@ func TestWithPersister_PanicWhenAlreadySet(t *testing.T) {
func TestSaveFirstname(t *testing.T) { func TestSaveFirstname(t *testing.T) {
sessionId := "session123" sessionId := "session123"
ctx, store := InitializeTestStore(t) ctx, userStore := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
_, logdb := InitializeTestLogdbStore(t)
logDb := store.LogDb{
Db: logdb,
}
fm, _ := NewFlagManager(flagsPath) fm, _ := NewFlagManager(flagsPath)
@@ -282,7 +316,7 @@ func TestSaveFirstname(t *testing.T) {
// Define test data // Define test data
firstName := "John" firstName := "John"
if err := store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(firstName)); err != nil { if err := userStore.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(firstName)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -290,9 +324,10 @@ func TestSaveFirstname(t *testing.T) {
// Create the MenuHandlers instance with the mock store // Create the MenuHandlers instance with the mock store
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: userStore,
flagManager: fm, flagManager: fm,
st: mockState, st: mockState,
logDb: logDb,
} }
// Call the method // Call the method
@@ -303,14 +338,19 @@ func TestSaveFirstname(t *testing.T) {
assert.Equal(t, expectedResult, res) assert.Equal(t, expectedResult, res)
// Verify that the DATA_FIRST_NAME entry has been updated with the temporary value // Verify that the DATA_FIRST_NAME entry has been updated with the temporary value
storedFirstName, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_FIRST_NAME) storedFirstName, _ := userStore.ReadEntry(ctx, sessionId, storedb.DATA_FIRST_NAME)
assert.Equal(t, firstName, string(storedFirstName)) assert.Equal(t, firstName, string(storedFirstName))
} }
func TestSaveFamilyname(t *testing.T) { func TestSaveFamilyname(t *testing.T) {
sessionId := "session123" sessionId := "session123"
ctx, store := InitializeTestStore(t) ctx, userStore := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
_, logdb := InitializeTestLogdbStore(t)
logDb := store.LogDb{
Db: logdb,
}
fm, _ := NewFlagManager(flagsPath) fm, _ := NewFlagManager(flagsPath)
@@ -328,15 +368,16 @@ func TestSaveFamilyname(t *testing.T) {
// Define test data // Define test data
familyName := "Doeee" familyName := "Doeee"
if err := store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(familyName)); err != nil { if err := userStore.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(familyName)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
// Create the MenuHandlers instance with the mock store // Create the MenuHandlers instance with the mock store
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: userStore,
st: mockState, st: mockState,
flagManager: fm, flagManager: fm,
logDb: logDb,
} }
// Call the method // Call the method
@@ -347,14 +388,19 @@ func TestSaveFamilyname(t *testing.T) {
assert.Equal(t, expectedResult, res) assert.Equal(t, expectedResult, res)
// Verify that the DATA_FAMILY_NAME entry has been updated with the temporary value // Verify that the DATA_FAMILY_NAME entry has been updated with the temporary value
storedFamilyName, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_FAMILY_NAME) storedFamilyName, _ := userStore.ReadEntry(ctx, sessionId, storedb.DATA_FAMILY_NAME)
assert.Equal(t, familyName, string(storedFamilyName)) assert.Equal(t, familyName, string(storedFamilyName))
} }
func TestSaveYoB(t *testing.T) { func TestSaveYoB(t *testing.T) {
sessionId := "session123" sessionId := "session123"
ctx, store := InitializeTestStore(t) ctx, userStore := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
_, logdb := InitializeTestLogdbStore(t)
logDb := store.LogDb{
Db: logdb,
}
fm, _ := NewFlagManager(flagsPath) fm, _ := NewFlagManager(flagsPath)
@@ -370,7 +416,7 @@ func TestSaveYoB(t *testing.T) {
// Define test data // Define test data
yob := "1980" yob := "1980"
if err := store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(yob)); err != nil { if err := userStore.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(yob)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -378,9 +424,10 @@ func TestSaveYoB(t *testing.T) {
// Create the MenuHandlers instance with the mock store // Create the MenuHandlers instance with the mock store
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: userStore,
flagManager: fm, flagManager: fm,
st: mockState, st: mockState,
logDb: logDb,
} }
// Call the method // Call the method
@@ -391,14 +438,19 @@ func TestSaveYoB(t *testing.T) {
assert.Equal(t, expectedResult, res) assert.Equal(t, expectedResult, res)
// Verify that the DATA_YOB entry has been updated with the temporary value // Verify that the DATA_YOB entry has been updated with the temporary value
storedYob, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_YOB) storedYob, _ := userStore.ReadEntry(ctx, sessionId, storedb.DATA_YOB)
assert.Equal(t, yob, string(storedYob)) assert.Equal(t, yob, string(storedYob))
} }
func TestSaveLocation(t *testing.T) { func TestSaveLocation(t *testing.T) {
sessionId := "session123" sessionId := "session123"
ctx, store := InitializeTestStore(t) ctx, userStore := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
_, logdb := InitializeTestLogdbStore(t)
logDb := store.LogDb{
Db: logdb,
}
fm, _ := NewFlagManager(flagsPath) fm, _ := NewFlagManager(flagsPath)
@@ -414,7 +466,7 @@ func TestSaveLocation(t *testing.T) {
// Define test data // Define test data
location := "Kilifi" location := "Kilifi"
if err := store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(location)); err != nil { if err := userStore.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(location)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -422,9 +474,10 @@ func TestSaveLocation(t *testing.T) {
// Create the MenuHandlers instance with the mock store // Create the MenuHandlers instance with the mock store
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: userStore,
flagManager: fm, flagManager: fm,
st: mockState, st: mockState,
logDb: logDb,
} }
// Call the method // Call the method
@@ -435,14 +488,19 @@ func TestSaveLocation(t *testing.T) {
assert.Equal(t, expectedResult, res) assert.Equal(t, expectedResult, res)
// Verify that the DATA_LOCATION entry has been updated with the temporary value // Verify that the DATA_LOCATION entry has been updated with the temporary value
storedLocation, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_LOCATION) storedLocation, _ := userStore.ReadEntry(ctx, sessionId, storedb.DATA_LOCATION)
assert.Equal(t, location, string(storedLocation)) assert.Equal(t, location, string(storedLocation))
} }
func TestSaveOfferings(t *testing.T) { func TestSaveOfferings(t *testing.T) {
sessionId := "session123" sessionId := "session123"
ctx, store := InitializeTestStore(t) ctx, userStore := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
_, logdb := InitializeTestLogdbStore(t)
logDb := store.LogDb{
Db: logdb,
}
fm, _ := NewFlagManager(flagsPath) fm, _ := NewFlagManager(flagsPath)
@@ -458,7 +516,7 @@ func TestSaveOfferings(t *testing.T) {
// Define test data // Define test data
offerings := "Bananas" offerings := "Bananas"
if err := store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(offerings)); err != nil { if err := userStore.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(offerings)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -466,9 +524,10 @@ func TestSaveOfferings(t *testing.T) {
// Create the MenuHandlers instance with the mock store // Create the MenuHandlers instance with the mock store
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: userStore,
flagManager: fm, flagManager: fm,
st: mockState, st: mockState,
logDb: logDb,
} }
// Call the method // Call the method
@@ -479,14 +538,19 @@ func TestSaveOfferings(t *testing.T) {
assert.Equal(t, expectedResult, res) assert.Equal(t, expectedResult, res)
// Verify that the DATA_OFFERINGS entry has been updated with the temporary value // Verify that the DATA_OFFERINGS entry has been updated with the temporary value
storedOfferings, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_OFFERINGS) storedOfferings, _ := userStore.ReadEntry(ctx, sessionId, storedb.DATA_OFFERINGS)
assert.Equal(t, offerings, string(storedOfferings)) assert.Equal(t, offerings, string(storedOfferings))
} }
func TestSaveGender(t *testing.T) { func TestSaveGender(t *testing.T) {
sessionId := "session123" sessionId := "session123"
ctx, store := InitializeTestStore(t) ctx, userStore := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
_, logdb := InitializeTestLogdbStore(t)
logDb := store.LogDb{
Db: logdb,
}
fm, _ := NewFlagManager(flagsPath) fm, _ := NewFlagManager(flagsPath)
@@ -526,16 +590,17 @@ func TestSaveGender(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if err := store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)); err != nil { if err := userStore.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol) mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol)
// Create the MenuHandlers instance with the mock store // Create the MenuHandlers instance with the mock store
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: userStore,
st: mockState, st: mockState,
flagManager: fm, flagManager: fm,
logDb: logDb,
} }
expectedResult := resource.Result{} expectedResult := resource.Result{}
@@ -550,7 +615,7 @@ func TestSaveGender(t *testing.T) {
assert.Equal(t, expectedResult, res) assert.Equal(t, expectedResult, res)
// Verify that the DATA_GENDER entry has been updated with the temporary value // Verify that the DATA_GENDER entry has been updated with the temporary value
storedGender, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_GENDER) storedGender, _ := userStore.ReadEntry(ctx, sessionId, storedb.DATA_GENDER)
assert.Equal(t, tt.expectedGender, string(storedGender)) assert.Equal(t, tt.expectedGender, string(storedGender))
}) })
} }
@@ -558,9 +623,15 @@ func TestSaveGender(t *testing.T) {
func TestSaveTemporaryPin(t *testing.T) { func TestSaveTemporaryPin(t *testing.T) {
sessionId := "session123" sessionId := "session123"
ctx, store := InitializeTestStore(t)
ctx, userdatastore := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
_, logdb := InitializeTestLogdbStore(t)
logDb := store.LogDb{
Db: logdb,
}
fm, err := NewFlagManager(flagsPath) fm, err := NewFlagManager(flagsPath)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@@ -571,7 +642,8 @@ func TestSaveTemporaryPin(t *testing.T) {
// Create the MenuHandlers instance with the mock flag manager // Create the MenuHandlers instance with the mock flag manager
h := &MenuHandlers{ h := &MenuHandlers{
flagManager: fm, flagManager: fm,
userdataStore: store, userdataStore: userdatastore,
logDb: logDb,
} }
// Define test cases // Define test cases
@@ -612,9 +684,15 @@ func TestSaveTemporaryPin(t *testing.T) {
func TestCheckIdentifier(t *testing.T) { func TestCheckIdentifier(t *testing.T) {
sessionId := "session123" sessionId := "session123"
ctx, store := InitializeTestStore(t) ctx, userdatastore := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
_, logdb := InitializeTestLogdbStore(t)
logDb := store.LogDb{
Db: logdb,
}
// Define test cases // Define test cases
tests := []struct { tests := []struct {
name string name string
@@ -634,14 +712,15 @@ func TestCheckIdentifier(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
err := store.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(tt.publicKey)) err := userdatastore.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(tt.publicKey))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
// Create the MenuHandlers instance with the mock store // Create the MenuHandlers instance with the mock store
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: userdatastore,
logDb: logDb,
} }
// Call the method // Call the method
@@ -1637,40 +1716,64 @@ func TestValidateRecipient(t *testing.T) {
// Define test cases // Define test cases
tests := []struct { tests := []struct {
name string name string
input []byte input []byte
expectedResult resource.Result expectError bool
expectedRecipient []byte
expectedResult resource.Result
}{ }{
{ {
name: "Test with invalid recepient", name: "Test with invalid recepient",
input: []byte("7?1234"), input: []byte("7?1234"),
expectError: true,
expectedResult: resource.Result{ expectedResult: resource.Result{
FlagSet: []uint32{flag_invalid_recipient}, FlagSet: []uint32{flag_invalid_recipient},
Content: "7?1234", Content: "7?1234",
}, },
}, },
{ {
name: "Test with valid unregistered recepient", name: "Test with valid unregistered recepient",
input: []byte("0712345678"), input: []byte("0712345678"),
expectError: true,
expectedResult: resource.Result{ expectedResult: resource.Result{
FlagSet: []uint32{flag_invalid_recipient_with_invite}, FlagSet: []uint32{flag_invalid_recipient_with_invite},
Content: "0712345678", Content: "0712345678",
}, },
}, },
{ {
name: "Test with valid registered recepient", name: "Test with valid registered recepient",
input: []byte("0711223344"), input: []byte("0711223344"),
expectedResult: resource.Result{}, expectError: false,
expectedRecipient: []byte(publicKey),
expectedResult: resource.Result{},
}, },
{ {
name: "Test with address", name: "Test with address",
input: []byte("0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9"), input: []byte("0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9"),
expectedResult: resource.Result{}, expectError: false,
expectedRecipient: []byte("0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9"),
expectedResult: resource.Result{},
}, },
{ {
name: "Test with alias recepient", name: "Test with alias recepient",
input: []byte("alias123.sarafu.local"), input: []byte("alias123.sarafu.local"),
expectedResult: resource.Result{}, expectError: false,
expectedRecipient: []byte("0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9"),
expectedResult: resource.Result{},
},
{
name: "Test for checksummed address",
input: []byte("0x5523058cdffe5f3c1eadadd5015e55c6e00fb439"),
expectError: false,
expectedRecipient: []byte("0x5523058cdFfe5F3c1EaDADD5015E55C6E00fb439"),
expectedResult: resource.Result{},
},
{
name: "Test with valid registered recepient that has white spaces",
input: []byte("0711 22 33 44"),
expectError: false,
expectedRecipient: []byte(publicKey),
expectedResult: resource.Result{},
}, },
} }
@@ -1703,6 +1806,12 @@ func TestValidateRecipient(t *testing.T) {
t.Error(err) t.Error(err)
} }
if !tt.expectError {
storedRecipientAddress, err := store.ReadEntry(ctx, sessionId, storedb.DATA_RECIPIENT)
assert.NoError(t, err)
assert.Equal(t, tt.expectedRecipient, storedRecipientAddress)
}
// Assert that the Result FlagSet has the required flags after language switch // 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") assert.Equal(t, res, tt.expectedResult, "Result should contain flag(s) that have been reset")
}) })
@@ -1950,8 +2059,13 @@ func TestManageVouchers(t *testing.T) {
sessionId := "session123" sessionId := "session123"
publicKey := "0X13242618721" publicKey := "0X13242618721"
ctx, store := InitializeTestStore(t) ctx, userStore := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
_, logdb := InitializeTestLogdbStore(t)
logDb := store.LogDb{
Db: logdb,
}
fm, err := NewFlagManager(flagsPath) fm, err := NewFlagManager(flagsPath)
if err != nil { if err != nil {
@@ -1961,8 +2075,13 @@ func TestManageVouchers(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
flag_api_error, err := fm.GetFlag("flag_api_call_error")
err = store.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(publicKey)) if err != nil {
t.Fatal(err)
}
err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(publicKey))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -1981,7 +2100,8 @@ func TestManageVouchers(t *testing.T) {
expectedVoucherSymbols: []byte(""), expectedVoucherSymbols: []byte(""),
expectedUpdatedAddress: []byte(""), expectedUpdatedAddress: []byte(""),
expectedResult: resource.Result{ expectedResult: resource.Result{
FlagSet: []uint32{flag_no_active_voucher}, FlagSet: []uint32{flag_no_active_voucher},
FlagReset: []uint32{flag_api_error},
}, },
}, },
{ {
@@ -1997,7 +2117,7 @@ func TestManageVouchers(t *testing.T) {
expectedVoucherSymbols: []byte("1:TOKEN1"), expectedVoucherSymbols: []byte("1:TOKEN1"),
expectedUpdatedAddress: []byte("0x123"), expectedUpdatedAddress: []byte("0x123"),
expectedResult: resource.Result{ expectedResult: resource.Result{
FlagReset: []uint32{flag_no_active_voucher}, FlagReset: []uint32{flag_api_error, flag_no_active_voucher},
}, },
}, },
{ {
@@ -2010,7 +2130,7 @@ func TestManageVouchers(t *testing.T) {
expectedVoucherSymbols: []byte("1:SRF\n2:MILO"), expectedVoucherSymbols: []byte("1:SRF\n2:MILO"),
expectedUpdatedAddress: []byte("0xd4c288865Ce"), expectedUpdatedAddress: []byte("0xd4c288865Ce"),
expectedResult: resource.Result{ expectedResult: resource.Result{
FlagReset: []uint32{flag_no_active_voucher}, FlagReset: []uint32{flag_api_error, flag_no_active_voucher},
}, },
}, },
} }
@@ -2020,20 +2140,21 @@ func TestManageVouchers(t *testing.T) {
mockAccountService := new(mocks.MockAccountService) mockAccountService := new(mocks.MockAccountService)
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: userStore,
accountService: mockAccountService, accountService: mockAccountService,
flagManager: fm, flagManager: fm,
logDb: logDb,
} }
mockAccountService.On("FetchVouchers", string(publicKey)).Return(tt.vouchersResp, nil) mockAccountService.On("FetchVouchers", string(publicKey)).Return(tt.vouchersResp, nil)
// Store active voucher if needed // Store active voucher if needed
if tt.storedActiveVoucher != "" { if tt.storedActiveVoucher != "" {
err := store.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_SYM, []byte(tt.storedActiveVoucher)) err := userStore.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_SYM, []byte(tt.storedActiveVoucher))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = store.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_ADDRESS, []byte("0x41c188D45rfg6ds")) err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_ADDRESS, []byte("0x41c188D45rfg6ds"))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -2045,12 +2166,12 @@ func TestManageVouchers(t *testing.T) {
if tt.storedActiveVoucher != "" { if tt.storedActiveVoucher != "" {
// Validate stored voucher symbols // Validate stored voucher symbols
voucherData, err := store.ReadEntry(ctx, sessionId, storedb.DATA_VOUCHER_SYMBOLS) voucherData, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_VOUCHER_SYMBOLS)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, tt.expectedVoucherSymbols, voucherData) assert.Equal(t, tt.expectedVoucherSymbols, voucherData)
// Validate stored active contract address // Validate stored active contract address
updatedAddress, err := store.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_ADDRESS) updatedAddress, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_ADDRESS)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, tt.expectedUpdatedAddress, updatedAddress) assert.Equal(t, tt.expectedUpdatedAddress, updatedAddress)
@@ -2161,6 +2282,8 @@ func TestGetVoucherDetails(t *testing.T) {
if err != nil { if err != nil {
t.Logf(err.Error()) t.Logf(err.Error())
} }
flag_api_error, _ := fm.GetFlag("flag_api_call_error")
mockAccountService := new(mocks.MockAccountService) mockAccountService := new(mocks.MockAccountService)
sessionId := "session123" sessionId := "session123"
@@ -2188,8 +2311,8 @@ func TestGetVoucherDetails(t *testing.T) {
"Name: %s\nSymbol: %s\nCommodity: %s\nLocation: %s", tokenDetails.TokenName, tokenDetails.TokenSymbol, tokenDetails.TokenCommodity, tokenDetails.TokenLocation, "Name: %s\nSymbol: %s\nCommodity: %s\nLocation: %s", tokenDetails.TokenName, tokenDetails.TokenSymbol, tokenDetails.TokenCommodity, tokenDetails.TokenLocation,
) )
mockAccountService.On("VoucherData", string(tokA_AAddress)).Return(tokenDetails, nil) mockAccountService.On("VoucherData", string(tokA_AAddress)).Return(tokenDetails, nil)
res, err := h.GetVoucherDetails(ctx, "SessionId", []byte("")) res, err := h.GetVoucherDetails(ctx, "SessionId", []byte(""))
expectedResult.FlagReset = append(expectedResult.FlagReset, flag_api_error)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, expectedResult, res) assert.Equal(t, expectedResult, res)
} }
@@ -2308,7 +2431,7 @@ func TestCheckBlockedStatus(t *testing.T) {
{ {
name: "Currently blocked account", name: "Currently blocked account",
currentWrongPinAttempts: "4", currentWrongPinAttempts: "4",
expectedResult: resource.Result{ expectedResult: resource.Result{
FlagReset: []uint32{flag_account_pin_reset}, FlagReset: []uint32{flag_account_pin_reset},
}, },
}, },
@@ -2377,8 +2500,14 @@ func TestCheckTransactions(t *testing.T) {
sessionId := "session123" sessionId := "session123"
publicKey := "0X13242618721" publicKey := "0X13242618721"
ctx, store := InitializeTestStore(t) ctx, userStore := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
_, logdb := InitializeTestLogdbStore(t)
logDb := store.LogDb{
Db: logdb,
}
spdb := InitializeTestSubPrefixDb(t, ctx) spdb := InitializeTestSubPrefixDb(t, ctx)
fm, err := NewFlagManager(flagsPath) fm, err := NewFlagManager(flagsPath)
@@ -2387,13 +2516,14 @@ func TestCheckTransactions(t *testing.T) {
} }
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: userStore,
accountService: mockAccountService, accountService: mockAccountService,
prefixDb: spdb, prefixDb: spdb,
logDb: logDb,
flagManager: fm, flagManager: fm,
} }
err = store.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(publicKey)) err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(publicKey))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@@ -27,6 +27,7 @@ type LocalHandlerService struct {
DbRs *resource.DbResource DbRs *resource.DbResource
Pe *persist.Persister Pe *persist.Persister
UserdataStore *db.Db UserdataStore *db.Db
LogDb *db.Db
Cfg engine.Config Cfg engine.Config
Rs resource.Resource Rs resource.Resource
first resource.EntryFunc first resource.EntryFunc
@@ -57,12 +58,16 @@ func (ls *LocalHandlerService) SetDataStore(db *db.Db) {
ls.UserdataStore = db ls.UserdataStore = db
} }
func (ls *LocalHandlerService) SetLogDb(db *db.Db) {
ls.LogDb = db
}
func (ls *LocalHandlerService) GetHandler(accountService remote.AccountService) (*application.MenuHandlers, error) { func (ls *LocalHandlerService) GetHandler(accountService remote.AccountService) (*application.MenuHandlers, error) {
replaceSeparatorFunc := func(input string) string { replaceSeparatorFunc := func(input string) string {
return strings.ReplaceAll(input, ":", ls.Cfg.MenuSeparator) return strings.ReplaceAll(input, ":", ls.Cfg.MenuSeparator)
} }
appHandlers, err := application.NewMenuHandlers(ls.Parser, *ls.UserdataStore, accountService, replaceSeparatorFunc) appHandlers, err := application.NewMenuHandlers(ls.Parser, *ls.UserdataStore, *ls.LogDb, accountService, replaceSeparatorFunc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -124,6 +129,7 @@ func (ls *LocalHandlerService) GetHandler(accountService remote.AccountService)
ls.DbRs.AddLocalFunc("get_suggested_alias", appHandlers.GetSuggestedAlias) ls.DbRs.AddLocalFunc("get_suggested_alias", appHandlers.GetSuggestedAlias)
ls.DbRs.AddLocalFunc("confirm_new_alias", appHandlers.ConfirmNewAlias) ls.DbRs.AddLocalFunc("confirm_new_alias", appHandlers.ConfirmNewAlias)
ls.DbRs.AddLocalFunc("check_account_created", appHandlers.CheckAccountCreated) ls.DbRs.AddLocalFunc("check_account_created", appHandlers.CheckAccountCreated)
ls.DbRs.AddLocalFunc("reset_api_call_failure", appHandlers.ResetApiCallFailure)
ls.first = appHandlers.Init ls.first = appHandlers.Init

View File

@@ -3,45 +3,23 @@ package cmd
import ( import (
"context" "context"
"fmt" "fmt"
"regexp"
"strings"
"git.defalsify.org/vise.git/db"
"git.defalsify.org/vise.git/engine"
"git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/logging"
"git.defalsify.org/vise.git/persist"
"git.defalsify.org/vise.git/resource"
"git.defalsify.org/vise.git/state"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application" "git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application"
"git.grassecon.net/grassrootseconomics/visedriver/storage" "git.grassecon.net/grassrootseconomics/visedriver/storage"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
) )
var argc map[string]int = map[string]int{
"reset": 0,
"admin": 1,
"clone": 1,
"overwrite": 2,
}
var ( var (
logg = logging.NewVanilla().WithDomain("cmd").WithContextKey("SessionId") logg = logging.NewVanilla().WithDomain("cmd").WithContextKey("SessionId")
cloneTargetRegex = `^\+000`
) )
type Cmd struct { type Cmd struct {
sessionId string sessionId string
conn storage.ConnData conn storage.ConnData
flagParser *application.FlagManager flagParser *application.FlagManager
cmd int cmd int
enable bool enable bool
param string exec func(ctx context.Context, ss storage.StorageService) error
exec func(ctx context.Context, ss storage.StorageService) error
engineConfig *engine.Config
st *state.State
key string
value string
} }
func NewCmd(sessionId string, flagParser *application.FlagManager) *Cmd { func NewCmd(sessionId string, flagParser *application.FlagManager) *Cmd {
@@ -51,115 +29,10 @@ func NewCmd(sessionId string, flagParser *application.FlagManager) *Cmd {
} }
} }
func (c *Cmd) WithEngine(engineConfig engine.Config) *Cmd {
c.engineConfig = &engineConfig
return c
}
func (c *Cmd) Exec(ctx context.Context, ss storage.StorageService) error { func (c *Cmd) Exec(ctx context.Context, ss storage.StorageService) error {
return c.exec(ctx, ss) return c.exec(ctx, ss)
} }
func (c *Cmd) engine(ctx context.Context, rs resource.Resource, pe *persist.Persister) (engine.Engine, error) {
if c.engineConfig == nil {
return nil, fmt.Errorf("engine config missing")
}
en := engine.NewEngine(*c.engineConfig, rs)
st := pe.GetState()
if st == nil {
return nil, fmt.Errorf("persister state fail")
}
en = en.WithState(st)
st.UseDebug()
ca := pe.GetMemory()
if ca == nil {
return nil, fmt.Errorf("persister cache fail")
}
en = en.WithMemory(ca)
logg.DebugCtxf(ctx, "state loaded", "state", st)
return en, nil
}
func (c *Cmd) execClone(ctx context.Context, ss storage.StorageService) error {
re := regexp.MustCompile(cloneTargetRegex)
if !re.MatchString(c.param) {
return fmt.Errorf("Clone sessionId must match target: %s", c.param)
}
pe, err := ss.GetPersister(ctx)
if err != nil {
return fmt.Errorf("get persister error: %v", err)
}
err = pe.Load(c.engineConfig.SessionId)
if err != nil {
return fmt.Errorf("persister load error: %v", err)
}
/// TODO consider DRY with devtools/store/dump
store, err := ss.GetUserdataDb(ctx)
if err != nil {
return fmt.Errorf("store retrieve error: %v", err)
}
store.SetSession(c.engineConfig.SessionId)
store.SetPrefix(db.DATATYPE_USERDATA)
dmp, err := store.Dump(ctx, []byte(""))
if err != nil {
return fmt.Errorf("store dump fail: %v\n", err.Error())
}
for true {
store.SetSession(c.engineConfig.SessionId)
k, v := dmp.Next(ctx)
if k == nil {
break
}
store.SetSession(c.param)
err = store.Put(ctx, k, v)
if err != nil {
return fmt.Errorf("user data store clone failed on key: %x", k)
}
}
return pe.Save(c.param)
}
func (c *Cmd) execReset(ctx context.Context, ss storage.StorageService) error {
pe, err := ss.GetPersister(ctx)
if err != nil {
return fmt.Errorf("get persister error: %v", err)
}
rs, err := ss.GetResource(ctx)
if err != nil {
return fmt.Errorf("get resource error: %v", err)
}
dbResource, ok := rs.(*resource.DbResource)
if !ok {
return fmt.Errorf("get dbresource error: %v", err)
}
err = pe.Load(c.engineConfig.SessionId)
if err != nil {
return fmt.Errorf("persister load error: %v", err)
}
en, err := c.engine(ctx, dbResource, pe)
if err != nil {
return err
}
_, err = en.(*engine.DefaultEngine).Reset(ctx, false)
if err != nil {
return err
}
st := pe.GetState()
logg.DebugCtxf(ctx, "state after reset", "state", st)
err = pe.Save(c.engineConfig.SessionId)
if err != nil {
return err
}
return nil
}
func (c *Cmd) execAdmin(ctx context.Context, ss storage.StorageService) error { func (c *Cmd) execAdmin(ctx context.Context, ss storage.StorageService) error {
pe, err := ss.GetPersister(ctx) pe, err := ss.GetPersister(ctx)
if err != nil { if err != nil {
@@ -190,51 +63,6 @@ func (c *Cmd) execAdmin(ctx context.Context, ss storage.StorageService) error {
return nil return nil
} }
func (c *Cmd) execOverwrite(ctx context.Context, ss storage.StorageService) error {
store, err := ss.GetUserdataDb(ctx)
if err != nil {
return fmt.Errorf("failed to get userdata store: %v", err)
}
// Map of symbolic keys to their DataTyp constants
symbolicKeys := map[string]storedb.DataTyp{
"first_name": storedb.DATA_FIRST_NAME,
"family_name": storedb.DATA_FAMILY_NAME,
"yob": storedb.DATA_YOB,
"location": storedb.DATA_LOCATION,
"gender": storedb.DATA_GENDER,
"offerings": storedb.DATA_OFFERINGS,
}
// Lookup symbolic key
dtype, ok := symbolicKeys[strings.ToLower(c.key)]
if !ok {
return fmt.Errorf("unknown key '%s'. Available keys: %v", c.key, keysOf(symbolicKeys))
}
k := storedb.ToBytes(dtype)
store.SetPrefix(db.DATATYPE_USERDATA)
store.SetSession(c.sessionId)
err = store.Put(ctx, k, []byte(c.value))
if err != nil {
return fmt.Errorf("failed to overwrite entry for key %s: %v", c.key, err)
}
logg.InfoCtxf(ctx, "overwrote data", "sessionId", c.sessionId, "key", c.key, "value", c.value)
return nil
}
// keysOf returns a list of keys from the symbolic map for error messages
func keysOf(m map[string]storedb.DataTyp) []string {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
}
func (c *Cmd) parseCmdAdmin(cmd string, param string, more []string) (bool, error) { func (c *Cmd) parseCmdAdmin(cmd string, param string, more []string) (bool, error) {
if cmd == "admin" { if cmd == "admin" {
if param == "1" { if param == "1" {
@@ -248,56 +76,13 @@ func (c *Cmd) parseCmdAdmin(cmd string, param string, more []string) (bool, erro
return false, nil return false, nil
} }
func (c *Cmd) parseCmdReset(cmd string, param string, more []string) (bool, error) {
if cmd == "reset" {
c.enable = false
c.exec = c.execReset
return true, nil
}
return false, nil
}
func (c *Cmd) parseCmdClone(cmd string, param string, more []string) (bool, error) {
if cmd == "clone" {
c.enable = false
c.param = param
c.exec = c.execClone
return true, nil
}
return false, nil
}
func (c *Cmd) parseCmdOverwrite(cmd string, param string, more []string) (bool, error) {
if cmd == "overwrite" {
if len(more) < 1 {
return false, fmt.Errorf("overwrite requires key and value")
}
c.key = param
c.value = more[0]
c.exec = c.execOverwrite
return true, nil
}
return false, nil
}
func (c *Cmd) Parse(args []string) error { func (c *Cmd) Parse(args []string) error {
var param string if len(args) < 2 {
if len(args) < 1 {
return fmt.Errorf("Wrong number of arguments: %v", args) return fmt.Errorf("Wrong number of arguments: %v", args)
} }
cmd := args[0] cmd := args[0]
param := args[1]
n, ok := argc[cmd] args = args[2:]
if !ok {
return fmt.Errorf("invalid command: %v", cmd)
}
if n > 0 {
if len(args) < n+1 {
return fmt.Errorf("Wrong number of arguments, need: %d", n)
}
param = args[1]
args = args[2:]
}
r, err := c.parseCmdAdmin(cmd, param, args) r, err := c.parseCmdAdmin(cmd, param, args)
if err != nil { if err != nil {
@@ -307,29 +92,5 @@ func (c *Cmd) Parse(args []string) error {
return nil return nil
} }
r, err = c.parseCmdReset(cmd, param, args)
if err != nil {
return err
}
if r {
return nil
}
r, err = c.parseCmdClone(cmd, param, args)
if err != nil {
return err
}
if r {
return nil
}
r, err = c.parseCmdOverwrite(cmd, param, args)
if err != nil {
return err
}
if r {
return nil
}
return fmt.Errorf("unknown subcommand: %s", cmd) return fmt.Errorf("unknown subcommand: %s", cmd)
} }

96
internal/sms/sms.go Normal file
View File

@@ -0,0 +1,96 @@
package sms
import (
"context"
"fmt"
"git.defalsify.org/vise.git/logging"
"git.grassecon.net/grassrootseconomics/common/phone"
"git.grassecon.net/grassrootseconomics/sarafu-api/remote"
"git.grassecon.net/grassrootseconomics/sarafu-vise/store"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
)
var (
logg = logging.NewVanilla().WithDomain("smsservice")
)
type SmsService struct {
Accountservice remote.AccountService
Userdatastore store.UserDataStore
}
// SendUpsellSMS will send an invitation SMS to an unregistered phone number
func (smsservice *SmsService) SendUpsellSMS(ctx context.Context, inviterPhone, inviteePhone string) error {
if !phone.IsValidPhoneNumber(inviterPhone) {
return fmt.Errorf("invalid inviter phone number %v", inviterPhone)
}
if !phone.IsValidPhoneNumber(inviteePhone) {
return fmt.Errorf("Invalid invitee phone number %v", inviteePhone)
}
_, err := smsservice.Accountservice.SendUpsellSMS(ctx, inviterPhone, inviteePhone)
if err != nil {
return fmt.Errorf("Failed to send upsell sms: %v", err)
}
return nil
}
// sendPINResetSMS will send an SMS to a user's phonenumber in the event that the associated account's PIN has been reset.
func (smsService *SmsService) SendPINResetSMS(ctx context.Context, adminPhoneNumber, blockedPhoneNumber string) error {
formattedAdminPhone, err := phone.FormatPhoneNumber(adminPhoneNumber)
if err != nil {
return fmt.Errorf("failed to format admin phone number: %w", err)
}
formattedBlockedPhone, err := phone.FormatPhoneNumber(blockedPhoneNumber)
if err != nil {
return fmt.Errorf("failed to format blocked phone number: %w", err)
}
if !phone.IsValidPhoneNumber(formattedAdminPhone) {
return fmt.Errorf("invalid admin phone number")
}
if !phone.IsValidPhoneNumber(formattedBlockedPhone) {
return fmt.Errorf("invalid blocked phone number")
}
err = smsService.Accountservice.SendPINResetSMS(ctx, formattedAdminPhone, formattedBlockedPhone)
if err != nil {
return fmt.Errorf("failed to send pin reset sms: %v", err)
}
return nil
}
// SendAddressSMS will triger an SMS when a user navigates to the my address node.The SMS will be sent to the associated phonenumber.
func (smsService *SmsService) SendAddressSMS(ctx context.Context) error {
store := smsService.Userdatastore
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return fmt.Errorf("missing session")
}
publicKey, err := store.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY)
if err != nil {
logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", storedb.DATA_PUBLIC_KEY, "error", err)
return err
}
originPhone, err := phone.FormatPhoneNumber(sessionId)
if err != nil {
logg.DebugCtxf(ctx, "Failed to format origin phonenumber", "sessionid", sessionId)
return nil
}
if !phone.IsValidPhoneNumber(originPhone) {
logg.InfoCtxf(ctx, "Invalid origin phone number", "origin phonenumber", originPhone)
return fmt.Errorf("invalid origin phone number")
}
err = smsService.Accountservice.SendAddressSMS(ctx, string(publicKey), originPhone)
if err != nil {
logg.DebugCtxf(ctx, "Failed to send address sms", "error", err)
return fmt.Errorf("Failed to send address sms: %v", err)
}
return nil
}

View File

@@ -10,9 +10,9 @@ import (
func TestInsertOrShift(t *testing.T) { func TestInsertOrShift(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
profile Profile profile Profile
index int index int
value string value string
expected []string expected []string
}{ }{
{ {

View File

@@ -1,5 +1,4 @@
LOAD check_identifier 0 LOAD check_identifier 0
RELOAD check_identifier
MAP check_identifier MAP check_identifier
MOUT back 0 MOUT back 0
MOUT quit 9 MOUT quit 9

View File

@@ -1 +1 @@
Failed to connect to the custodial service.Please try again. Failed to connect to the custodial service .Please try again.

View File

@@ -1,5 +1,7 @@
LOAD reset_api_call_failure 6
RELOAD reset_api_call_failure
MOUT retry 1 MOUT retry 1
MOUT quit 9 MOUT quit 9
HALT HALT
INCMP _ 1 INCMP ^ 1
INCMP quit 9 INCMP quit 9

View File

@@ -0,0 +1 @@
Imeshindwa kuunganisha kwenye huduma ya uangalizi. Tafadhali jaribu tena.

View File

@@ -1,5 +1,6 @@
LOAD check_transactions 0 LOAD check_transactions 0
RELOAD check_transactions RELOAD check_transactions
CATCH api_failure flag_api_call_error 1
CATCH no_transfers flag_no_transfers 1 CATCH no_transfers flag_no_transfers 1
LOAD authorize_account 6 LOAD authorize_account 6
MOUT back 0 MOUT back 0

View File

@@ -2,9 +2,9 @@ LOAD clear_temporary_value 2
RELOAD clear_temporary_value RELOAD clear_temporary_value
LOAD manage_vouchers 160 LOAD manage_vouchers 160
RELOAD manage_vouchers RELOAD manage_vouchers
CATCH api_failure flag_api_call_error 1
LOAD check_balance 128 LOAD check_balance 128
RELOAD check_balance RELOAD check_balance
CATCH api_failure flag_api_call_error 1
MAP check_balance MAP check_balance
MOUT send 1 MOUT send 1
MOUT vouchers 2 MOUT vouchers 2

View File

@@ -5,4 +5,5 @@ HALT
INCMP _ 0 INCMP _ 0
LOAD request_custom_alias 0 LOAD request_custom_alias 0
RELOAD request_custom_alias RELOAD request_custom_alias
CATCH api_failure flag_api_call_error 1
INCMP confirm_new_alias * INCMP confirm_new_alias *

View File

@@ -3,14 +3,14 @@ LOAD get_vouchers 0
MAP get_vouchers MAP get_vouchers
MOUT back 0 MOUT back 0
MOUT quit 99 MOUT quit 99
MNEXT next 11 MNEXT next 88
MPREV prev 22 MPREV prev 98
HALT HALT
INCMP > 88
INCMP < 98
INCMP _ 0
INCMP quit 99
LOAD view_voucher 80 LOAD view_voucher 80
RELOAD view_voucher RELOAD view_voucher
CATCH . flag_incorrect_voucher 1 CATCH . flag_incorrect_voucher 1
INCMP _ 0
INCMP quit 99
INCMP > 11
INCMP < 22
INCMP view_voucher * INCMP view_voucher *

View File

@@ -5,6 +5,7 @@ MOUT back 0
HALT HALT
LOAD validate_recipient 50 LOAD validate_recipient 50
RELOAD validate_recipient RELOAD validate_recipient
CATCH api_failure flag_api_call_error 1
CATCH invalid_recipient flag_invalid_recipient 1 CATCH invalid_recipient flag_invalid_recipient 1
CATCH invite_recipient flag_invalid_recipient_with_invite 1 CATCH invite_recipient flag_invalid_recipient_with_invite 1
INCMP _ 0 INCMP _ 0

View File

@@ -1,5 +1,7 @@
CATCH no_voucher flag_no_active_voucher 1 CATCH no_voucher flag_no_active_voucher 1
LOAD get_voucher_details 0 LOAD get_voucher_details 0
RELOAD get_voucher_details
CATCH api_failure flag_api_call_error 1
MAP get_voucher_details MAP get_voucher_details
MOUT back 0 MOUT back 0
HALT HALT

View File

@@ -181,8 +181,8 @@ func (s *SshRunner) GetEngine(sessionId string) (engine.Engine, func(), error) {
accountService := services.New(ctx, menuStorageService) accountService := services.New(ctx, menuStorageService)
_, err = lhs.GetHandler(accountService) _, err = lhs.GetHandler(accountService)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "get accounts service handler: %v\n", err) fmt.Fprintf(os.Stderr, "get accounts service handler: %v\n", err)
os.Exit(1) os.Exit(1)
} }
en := lhs.GetEngine(lhs.Cfg, rs, pe) en := lhs.GetEngine(lhs.Cfg, rs, pe)
closer := func() { closer := func() {

27
store/log_db.go Normal file
View File

@@ -0,0 +1,27 @@
package store
import (
"context"
visedb "git.defalsify.org/vise.git/db"
"git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
)
type LogDb struct {
visedb.Db
}
func (db *LogDb) WriteLogEntry(ctx context.Context, sessionId string, typ db.DataTyp, v []byte) error {
db.SetPrefix(visedb.DATATYPE_USERDATA)
db.SetSession(sessionId)
k := storedb.ToBytes(typ)
return db.Put(ctx, k, v)
}
func (db *LogDb) ReadLogEntry(ctx context.Context, sessionId string, typ db.DataTyp) ([]byte, error) {
db.SetPrefix(visedb.DATATYPE_USERDATA)
db.SetSession(sessionId)
k := storedb.ToBytes(typ)
return db.Get(ctx, k)
}

View File

@@ -113,6 +113,12 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool, *persist.Pe
os.Exit(1) os.Exit(1)
} }
logdb, err := menuStorageService.GetLogDb(ctx, userDataStore, "test-db-logs", "user-data")
if err != nil {
fmt.Fprintf(os.Stderr, "get log db error: %v\n", err)
os.Exit(1)
}
dbResource, ok := rs.(*resource.DbResource) dbResource, ok := rs.(*resource.DbResource)
if !ok { if !ok {
fmt.Fprintf(os.Stderr, "dbresource cast error") fmt.Fprintf(os.Stderr, "dbresource cast error")
@@ -121,6 +127,7 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool, *persist.Pe
lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs) lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs)
lhs.SetDataStore(&userDataStore) lhs.SetDataStore(&userDataStore)
lhs.SetLogDb(&logdb)
lhs.SetPersister(pe) lhs.SetPersister(pe)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintf(os.Stderr, err.Error())
@@ -154,6 +161,7 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool, *persist.Pe
en := lhs.GetEngine(lhs.Cfg, rs, pe) en := lhs.GetEngine(lhs.Cfg, rs, pe)
cleanFn := func() { cleanFn := func() {
logdb.Close(ctx)
err := en.Finish(ctx) err := en.Finish(ctx)
if err != nil { if err != nil {
logg.Errorf(err.Error()) logg.Errorf(err.Error())