From 1a997e8b261594fbaca8ab1ced450d610fb3c451 Mon Sep 17 00:00:00 2001
From: alfred-mk <alfredmwaik@gmail.com>
Date: Mon, 26 Aug 2024 15:53:07 +0300
Subject: [PATCH] updated the file structure to have external functions on a
 different package

---
 cmd/main.go                                   | 820 +-----------------
 .../server}/accountstatus.go                  |   5 +-
 .../server}/balancecheck.go                   |   2 +-
 .../server}/createaccount.go                  |   2 +-
 internal/handlers/ussd/menuhandler.go         | 780 +++++++++++++++++
 5 files changed, 817 insertions(+), 792 deletions(-)
 rename internal/{server/handlers => handlers/server}/accountstatus.go (96%)
 rename internal/{server/handlers => handlers/server}/balancecheck.go (97%)
 rename internal/{server/handlers => handlers/server}/createaccount.go (97%)
 create mode 100644 internal/handlers/ussd/menuhandler.go

diff --git a/cmd/main.go b/cmd/main.go
index 61f015f..75a7a8c 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -1,774 +1,21 @@
 package main
 
 import (
-	"bytes"
 	"context"
-	"encoding/json"
 	"flag"
 	"fmt"
 	"os"
 	"path"
-	"regexp"
-	"time"
 
 	"git.defalsify.org/vise.git/cache"
 	"git.defalsify.org/vise.git/engine"
-	"git.defalsify.org/vise.git/lang"
 	"git.defalsify.org/vise.git/persist"
 	"git.defalsify.org/vise.git/resource"
 	"git.defalsify.org/vise.git/state"
 	"git.grassecon.net/urdt/ussd/internal/models"
-	"git.grassecon.net/urdt/ussd/internal/server/handlers"
-	"git.grassecon.net/urdt/ussd/internal/utils"
+	"git.grassecon.net/urdt/ussd/internal/handlers/ussd"
 )
 
-type fsData struct {
-	path string
-	st   *state.State
-}
-
-func codeFromCtx(ctx context.Context) string {
-	var code string
-	engine.Logg.DebugCtxf(ctx, "in msg", "ctx", ctx, "val", code)
-	if ctx.Value("Language") != nil {
-		lang := ctx.Value("Language").(lang.Language)
-		code = lang.Code
-	}
-	return code
-}
-
-func (fsd *fsData) save_firstname(cxt context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-	if len(input) > 0 {
-		name := string(input)
-		accountData["FirstName"] = name
-		updatedJsonData, err := json.Marshal(accountData)
-		if err != nil {
-			return res, err
-		}
-
-		err = os.WriteFile(fp, updatedJsonData, 0644)
-		if err != nil {
-			return res, err
-		}
-	}
-
-	return res, nil
-}
-
-func (fsd *fsData) save_familyname(cxt context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-	if len(input) > 0 {
-		//Save name
-		secondname := string(input)
-		accountData["FamilyName"] = secondname
-		updatedJsonData, err := json.Marshal(accountData)
-		if err != nil {
-			return res, err
-		}
-
-		err = os.WriteFile(fp, updatedJsonData, 0644)
-		if err != nil {
-			return res, err
-		}
-	}
-
-	return res, nil
-}
-func (fsd *fsData) save_yob(cxt context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-	if len(input) > 0 {
-		yob := string(input)
-		accountData["YOB"] = yob
-		updatedJsonData, err := json.Marshal(accountData)
-		if err != nil {
-			return res, err
-		}
-
-		err = os.WriteFile(fp, updatedJsonData, 0644)
-		if err != nil {
-			return res, err
-		}
-	}
-
-	return res, nil
-}
-
-func (fsd *fsData) save_location(cxt context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-	if len(input) > 0 {
-		location := string(input)
-		accountData["Location"] = location
-		updatedJsonData, err := json.Marshal(accountData)
-		if err != nil {
-			return res, err
-		}
-
-		err = os.WriteFile(fp, updatedJsonData, 0644)
-		if err != nil {
-			return res, err
-		}
-
-	}
-
-	return res, nil
-}
-
-func (fsd *fsData) save_gender(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-	if len(input) > 0 {
-		gender := string(input)
-
-		switch gender {
-		case "1":
-			gender = "Male"
-		case "2":
-			gender = "Female"
-		case "3":
-			gender = "Other"
-		}
-		accountData["Gender"] = gender
-		updatedJsonData, err := json.Marshal(accountData)
-		if err != nil {
-			return res, err
-		}
-
-		err = os.WriteFile(fp, updatedJsonData, 0644)
-		if err != nil {
-			return res, err
-		}
-	}
-	return res, nil
-}
-
-func (fsd *fsData) save_offerings(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-	if len(input) > 0 {
-		offerings := string(input)
-		accountData["Offerings"] = offerings
-		updatedJsonData, err := json.Marshal(accountData)
-		if err != nil {
-			return res, err
-		}
-		err = os.WriteFile(fp, updatedJsonData, 0644)
-		if err != nil {
-			return res, err
-		}
-	}
-	return res, nil
-}
-
-func (fsd *fsData) set_language(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	inputStr := string(input)
-	res := resource.Result{}
-	switch inputStr {
-	case "0":
-		res.FlagSet = []uint32{state.FLAG_LANG}
-		res.Content = "eng"
-	case "1":
-		res.FlagSet = []uint32{state.FLAG_LANG}
-		res.Content = "swa"
-	default:
-	}
-
-	res.FlagSet = append(res.FlagSet, models.USERFLAG_LANGUAGE_SET)
-
-	return res, nil
-}
-
-func (fsd *fsData) create_account(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-	f, err := os.OpenFile(fp, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
-	if err != nil {
-		return res, err
-	}
-	f.Close()
-	accountResp, err := handlers.CreateAccount()
-	if err != nil {
-		fmt.Println("Failed to create account:", err)
-		return res, err
-	}
-
-	accountData := map[string]string{
-		"TrackingId":  accountResp.Result.TrackingId,
-		"PublicKey":   accountResp.Result.PublicKey,
-		"CustodialId": accountResp.Result.CustodialId.String(),
-		"Status":      "PENDING",
-	}
-
-	jsonData, err := json.Marshal(accountData)
-	if err != nil {
-		return res, err
-	}
-
-	err = os.WriteFile(fp, jsonData, 0644)
-	if err != nil {
-		return res, err
-	}
-	res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_CREATED)
-	return res, err
-}
-
-func (fsd *fsData) reset_unlock_for_update(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	res.FlagReset = append(res.FlagReset, models.USERFLAG_UNLOCKFORUPDATE)
-	return res, nil
-}
-
-func (fsd *fsData) reset_account_unlocked(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
-	return res, nil
-}
-
-func (fsd *fsData) check_identifier(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-
-	res.Content = accountData["PublicKey"]
-
-	return res, nil
-}
-
-func (fsd *fsData) unlock(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	pin := string(input)
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-
-	if len(input) > 1 {
-		if pin != accountData["AccountPIN"] {
-			res.FlagSet = append(res.FlagSet, models.USERFLAG_INCORRECTPIN)
-			res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
-			return res, nil
-		}
-		if fsd.st.MatchFlag(models.USERFLAG_ACCOUNT_UNLOCKED, false) {
-			res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTPIN)
-			res.FlagSet = append(res.FlagSet, models.USERFLAG_UNLOCKFORUPDATE)
-			res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_UNLOCKED)
-		} else {
-			res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
-		}
-	}
-	return res, nil
-}
-
-func (fsd *fsData) reset_incorrect_pin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTPIN)
-	return res, nil
-}
-
-func (fsd *fsData) check_account_status(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-
-	//status, err := checkAccountStatus(accountData["TrackingId"])
-	status, err := handlers.CheckAccountStatus(accountData["TrackingId"])
-
-	if err != nil {
-		fmt.Println("Error checking account status:", err)
-		return res, nil
-	}
-
-	accountData["Status"] = status
-
-	if status == "SUCCESS" {
-		res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_SUCCESS)
-		res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_PENDING)
-	} else {
-		res.FlagReset = append(res.FlagSet, models.USERFLAG_ACCOUNT_SUCCESS)
-		res.FlagSet = append(res.FlagReset, models.USERFLAG_ACCOUNT_PENDING)
-	}
-
-	updatedJsonData, err := json.Marshal(accountData)
-	if err != nil {
-		return res, err
-	}
-
-	err = os.WriteFile(fp, updatedJsonData, 0644)
-	if err != nil {
-		return res, err
-	}
-
-	return res, nil
-}
-
-func (fsd *fsData) quit(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	switch codeFromCtx(ctx) {
-	case "swa":
-		res.Content = "Asante kwa kutumia huduma ya Sarafu. Kwaheri!"
-	default:
-		res.Content = "Thank you for using Sarafu. Goodbye!"
-	}
-	res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
-	return res, nil
-}
-
-func (fsd *fsData) verify_yob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	date := string(input)
-
-	dateRegex := regexp.MustCompile(`^\d{2}/\d{2}/\d{4}$`)
-	isCorrectFormat := dateRegex.MatchString(date)
-	if !isCorrectFormat {
-		res.FlagSet = append(res.FlagSet, models.USERFLAG_INCORRECTDATEFORMAT)
-	} else {
-		res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTDATEFORMAT)
-	}
-
-	return res, nil
-}
-
-func (fsd *fsData) reset_incorrect_yob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTDATEFORMAT)
-	return res, nil
-}
-
-func (fsd *fsData) check_balance(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-
-	fp := fsd.path + "_data"
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-	balance, err := handlers.CheckBalance(accountData["PublicKey"])
-	if err != nil {
-		return res, nil
-	}
-	res.Content = balance
-
-	return res, nil
-}
-
-func (fsd *fsData) validate_recipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	recipient := string(input)
-
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-
-	if recipient != "0" {
-		// mimic invalid number check
-		if recipient == "000" {
-			res.FlagSet = append(res.FlagSet, models.USERFLAG_INVALID_RECIPIENT)
-			res.Content = recipient
-
-			return res, nil
-		}
-
-		accountData["Recipient"] = recipient
-
-		updatedJsonData, err := json.Marshal(accountData)
-		if err != nil {
-			return res, err
-		}
-
-		err = os.WriteFile(fp, updatedJsonData, 0644)
-		if err != nil {
-			return res, err
-		}
-	}
-
-	return res, nil
-}
-
-func (fsd *fsData) transaction_reset(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-
-	// reset the recipient
-	accountData["Recipient"] = ""
-
-	updatedJsonData, err := json.Marshal(accountData)
-	if err != nil {
-		return res, err
-	}
-
-	err = os.WriteFile(fp, updatedJsonData, 0644)
-	if err != nil {
-		return res, err
-	}
-
-	res.FlagReset = append(res.FlagReset, models.USERFLAG_INVALID_RECIPIENT, models.USERFLAG_INVALID_RECIPIENT_WITH_INVITE)
-
-	return res, nil
-}
-
-func (fsd *fsData) reset_transaction_amount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-
-	// reset the amount
-	accountData["Amount"] = ""
-
-	updatedJsonData, err := json.Marshal(accountData)
-	if err != nil {
-		return res, err
-	}
-
-	err = os.WriteFile(fp, updatedJsonData, 0644)
-	if err != nil {
-		return res, err
-	}
-
-	res.FlagReset = append(res.FlagReset, models.USERFLAG_INVALID_AMOUNT)
-
-	return res, nil
-}
-
-func (fsd *fsData) max_amount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-
-	// mimic a max amount
-	res.Content = "10.00"
-
-	return res, nil
-}
-
-func (fsd *fsData) validate_amount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	amount := string(input)
-
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-
-	if amount != "0" {
-		// mimic invalid amount
-		if amount == "00" {
-			res.FlagSet = append(res.FlagSet, models.USERFLAG_INVALID_AMOUNT)
-			res.Content = amount
-
-			return res, nil
-		}
-
-		res.Content = amount
-
-		accountData["Amount"] = amount
-
-		updatedJsonData, err := json.Marshal(accountData)
-		if err != nil {
-			return res, err
-		}
-
-		err = os.WriteFile(fp, updatedJsonData, 0644)
-		if err != nil {
-			return res, err
-		}
-
-		return res, nil
-	}
-
-	return res, nil
-}
-
-func (fsd *fsData) get_recipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-
-	res.Content = accountData["Recipient"]
-
-	return res, nil
-}
-
-func (fsd *fsData) get_profile_info(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-	name := accountData["FirstName"] + " " + accountData["FamilyName"]
-	gender := accountData["Gender"]
-	yob := accountData["YOB"]
-	location := accountData["Location"]
-	offerings := accountData["Offerings"]
-
-	layout := "02/01/2006"
-
-	birthdate, err := time.Parse(layout, yob)
-	if err != nil {
-		return res, err
-	}
-
-	currentDate := time.Now()
-	formattedDate := currentDate.Format(layout)
-	today, err := time.Parse(layout, formattedDate)
-	if err != nil {
-		return res, nil
-	}
-	age := utils.CalculateAge(birthdate, today)
-
-	formattedData := fmt.Sprintf("Name: %s\nGender: %s\nAge: %d\nLocation: %s\nYou provide: %s\n", name, gender, age, location, offerings)
-	res.Content = formattedData
-
-	return res, nil
-}
-
-func (fsd *fsData) get_sender(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-
-	res.Content = accountData["PublicKey"]
-
-	return res, nil
-}
-
-func (fsd *fsData) quit_with_balance(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-	balance, err := handlers.CheckBalance(accountData["PublicKey"])
-	if err != nil {
-		return res, nil
-	}
-	res.Content = fmt.Sprintf("Your account balance is: %s", balance)
-	res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
-	return res, nil
-}
-
-func (fsd *fsData) save_pin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	accountPIN := string(input)
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-
-	accountData["AccountPIN"] = accountPIN
-
-	updatedJsonData, err := json.Marshal(accountData)
-	if err != nil {
-		return res, err
-	}
-
-	err = os.WriteFile(fp, updatedJsonData, 0644)
-	if err != nil {
-		return res, err
-	}
-
-	return res, nil
-}
-
-func (fsd *fsData) verify_pin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
-	res := resource.Result{}
-	fp := fsd.path + "_data"
-
-	jsonData, err := os.ReadFile(fp)
-	if err != nil {
-		return res, err
-	}
-
-	var accountData map[string]string
-	err = json.Unmarshal(jsonData, &accountData)
-	if err != nil {
-		return res, err
-	}
-
-	if bytes.Equal(input, []byte(accountData["AccountPIN"])) {
-		res.FlagSet = []uint32{models.USERFLAG_VALIDPIN}
-		res.FlagReset = []uint32{models.USERFLAG_PINMISMATCH}
-	} else {
-		res.FlagSet = []uint32{models.USERFLAG_PINMISMATCH}
-	}
-
-	return res, nil
-}
-
 var (
 	scriptDir = path.Join("services", "registration")
 )
@@ -824,39 +71,38 @@ func main() {
 	}
 
 	fp := path.Join(dp, sessionId)
-	fs := &fsData{
-		path: fp,
-		st:   &st,
-	}
-	rfs.AddLocalFunc("select_language", fs.set_language)
-	rfs.AddLocalFunc("create_account", fs.create_account)
-	rfs.AddLocalFunc("save_pin", fs.save_pin)
-	rfs.AddLocalFunc("verify_pin", fs.verify_pin)
-	rfs.AddLocalFunc("check_identifier", fs.check_identifier)
-	rfs.AddLocalFunc("check_account_status", fs.check_account_status)
-	rfs.AddLocalFunc("unlock_account", fs.unlock)
-	rfs.AddLocalFunc("quit", fs.quit)
-	rfs.AddLocalFunc("check_balance", fs.check_balance)
-	rfs.AddLocalFunc("validate_recipient", fs.validate_recipient)
-	rfs.AddLocalFunc("transaction_reset", fs.transaction_reset)
-	rfs.AddLocalFunc("max_amount", fs.max_amount)
-	rfs.AddLocalFunc("validate_amount", fs.validate_amount)
-	rfs.AddLocalFunc("reset_transaction_amount", fs.reset_transaction_amount)
-	rfs.AddLocalFunc("get_recipient", fs.get_recipient)
-	rfs.AddLocalFunc("get_sender", fs.get_sender)
-	rfs.AddLocalFunc("reset_incorrect", fs.reset_incorrect_pin)
-	rfs.AddLocalFunc("save_firstname", fs.save_firstname)
-	rfs.AddLocalFunc("save_familyname", fs.save_familyname)
-	rfs.AddLocalFunc("save_gender", fs.save_gender)
-	rfs.AddLocalFunc("save_location", fs.save_location)
-	rfs.AddLocalFunc("save_yob", fs.save_yob)
-	rfs.AddLocalFunc("save_offerings", fs.save_offerings)
-	rfs.AddLocalFunc("quit_with_balance", fs.quit_with_balance)
-	rfs.AddLocalFunc("reset_unlocked", fs.reset_account_unlocked)
-	rfs.AddLocalFunc("reset_unlock_for_update", fs.reset_unlock_for_update)
-	rfs.AddLocalFunc("get_profile_info", fs.get_profile_info)
-	rfs.AddLocalFunc("verify_yob", fs.verify_yob)
-	rfs.AddLocalFunc("reset_incorrect_date_format", fs.reset_incorrect_yob)
+
+	ussdHandlers := ussd.NewHandlers(fp, &st)
+
+	rfs.AddLocalFunc("select_language", ussdHandlers.SetLanguage)
+	rfs.AddLocalFunc("create_account", ussdHandlers.CreateAccount)
+	rfs.AddLocalFunc("save_pin", ussdHandlers.SavePin)
+	rfs.AddLocalFunc("verify_pin", ussdHandlers.VerifyPin)
+	rfs.AddLocalFunc("check_identifier", ussdHandlers.CheckIdentifier)
+	rfs.AddLocalFunc("check_account_status", ussdHandlers.CheckAccountStatus)
+	rfs.AddLocalFunc("unlock_account", ussdHandlers.Unlock)
+	rfs.AddLocalFunc("quit", ussdHandlers.Quit)
+	rfs.AddLocalFunc("check_balance", ussdHandlers.CheckBalance)
+	rfs.AddLocalFunc("validate_recipient", ussdHandlers.ValidateRecipient)
+	rfs.AddLocalFunc("transaction_reset", ussdHandlers.TransactionReset)
+	rfs.AddLocalFunc("max_amount", ussdHandlers.MaxAmount)
+	rfs.AddLocalFunc("validate_amount", ussdHandlers.ValidateAmount)
+	rfs.AddLocalFunc("reset_transaction_amount", ussdHandlers.ResetTransactionAmount)
+	rfs.AddLocalFunc("get_recipient", ussdHandlers.GetRecipient)
+	rfs.AddLocalFunc("get_sender", ussdHandlers.GetSender)
+	rfs.AddLocalFunc("reset_incorrect", ussdHandlers.ResetIncorrectPin)
+	rfs.AddLocalFunc("save_firstname", ussdHandlers.SaveFirstname)
+	rfs.AddLocalFunc("save_familyname", ussdHandlers.SaveFamilyname)
+	rfs.AddLocalFunc("save_gender", ussdHandlers.SaveGender)
+	rfs.AddLocalFunc("save_location", ussdHandlers.SaveLocation)
+	rfs.AddLocalFunc("save_yob", ussdHandlers.SaveYob)
+	rfs.AddLocalFunc("save_offerings", ussdHandlers.SaveOfferings)
+	rfs.AddLocalFunc("quit_with_balance", ussdHandlers.QuitWithBalance)
+	rfs.AddLocalFunc("reset_unlocked", ussdHandlers.ResetAccountUnlocked)
+	rfs.AddLocalFunc("reset_unlock_for_update", ussdHandlers.ResetUnlockForUpdate)
+	rfs.AddLocalFunc("get_profile_info", ussdHandlers.GetProfileInfo)
+	rfs.AddLocalFunc("verify_yob", ussdHandlers.VerifyYob)
+	rfs.AddLocalFunc("reset_incorrect_date_format", ussdHandlers.ResetIncorrectYob)
 
 	cont, err := en.Init(ctx)
 	en.SetDebugger(engine.NewSimpleDebug(nil))
diff --git a/internal/server/handlers/accountstatus.go b/internal/handlers/server/accountstatus.go
similarity index 96%
rename from internal/server/handlers/accountstatus.go
rename to internal/handlers/server/accountstatus.go
index 1992acc..d93b25d 100644
--- a/internal/server/handlers/accountstatus.go
+++ b/internal/handlers/server/accountstatus.go
@@ -1,4 +1,4 @@
-package handlers
+package server
 
 import (
 	"encoding/json"
@@ -9,7 +9,6 @@ import (
 	"git.grassecon.net/urdt/ussd/internal/models"
 )
 
-
 func CheckAccountStatus(trackingId string) (string, error) {
 	resp, err := http.Get(config.TrackStatusURL + trackingId)
 	if err != nil {
@@ -31,4 +30,4 @@ func CheckAccountStatus(trackingId string) (string, error) {
 	status := trackResp.Result.Transaction.Status
 
 	return status, nil
-}
\ No newline at end of file
+}
diff --git a/internal/server/handlers/balancecheck.go b/internal/handlers/server/balancecheck.go
similarity index 97%
rename from internal/server/handlers/balancecheck.go
rename to internal/handlers/server/balancecheck.go
index 137050d..059ced0 100644
--- a/internal/server/handlers/balancecheck.go
+++ b/internal/handlers/server/balancecheck.go
@@ -1,4 +1,4 @@
-package handlers
+package server
 
 import (
 	"encoding/json"
diff --git a/internal/server/handlers/createaccount.go b/internal/handlers/server/createaccount.go
similarity index 97%
rename from internal/server/handlers/createaccount.go
rename to internal/handlers/server/createaccount.go
index 5175a3b..bdab01c 100644
--- a/internal/server/handlers/createaccount.go
+++ b/internal/handlers/server/createaccount.go
@@ -1,4 +1,4 @@
-package handlers
+package server
 
 import (
 	"encoding/json"
diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go
new file mode 100644
index 0000000..a53cb54
--- /dev/null
+++ b/internal/handlers/ussd/menuhandler.go
@@ -0,0 +1,780 @@
+package ussd
+
+import (
+	"bytes"
+	"context"
+	"encoding/json"
+	"fmt"
+	"os"
+	"regexp"
+	"time"
+
+	"git.defalsify.org/vise.git/engine"
+	"git.defalsify.org/vise.git/lang"
+	"git.defalsify.org/vise.git/resource"
+	"git.defalsify.org/vise.git/state"
+	"git.grassecon.net/urdt/ussd/internal/models"
+	"git.grassecon.net/urdt/ussd/internal/handlers/server"
+	"git.grassecon.net/urdt/ussd/internal/utils"
+)
+
+type FSData struct {
+	Path string
+	St   *state.State
+}
+
+type Handlers struct {
+	fs *FSData
+}
+
+func NewHandlers(path string, st *state.State) *Handlers {
+	return &Handlers{
+		fs: &FSData{
+			Path: path,
+			St:   st,
+		},
+	}
+}
+
+func (h *Handlers) SetLanguage(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	inputStr := string(input)
+	res := resource.Result{}
+	switch inputStr {
+	case "0":
+		res.FlagSet = []uint32{state.FLAG_LANG}
+		res.Content = "eng"
+	case "1":
+		res.FlagSet = []uint32{state.FLAG_LANG}
+		res.Content = "swa"
+	default:
+	}
+
+	res.FlagSet = append(res.FlagSet, models.USERFLAG_LANGUAGE_SET)
+
+	return res, nil
+}
+
+func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+	f, err := os.OpenFile(fp, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
+	if err != nil {
+		return res, err
+	}
+	f.Close()
+	accountResp, err := server.CreateAccount()
+	if err != nil {
+		fmt.Println("Failed to create account:", err)
+		return res, err
+	}
+
+	accountData := map[string]string{
+		"TrackingId":  accountResp.Result.TrackingId,
+		"PublicKey":   accountResp.Result.PublicKey,
+		"CustodialId": accountResp.Result.CustodialId.String(),
+		"Status":      "PENDING",
+	}
+
+	jsonData, err := json.Marshal(accountData)
+	if err != nil {
+		return res, err
+	}
+
+	err = os.WriteFile(fp, jsonData, 0644)
+	if err != nil {
+		return res, err
+	}
+	res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_CREATED)
+	return res, err
+}
+
+func (h *Handlers) SavePin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	accountPIN := string(input)
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+
+	accountData["AccountPIN"] = accountPIN
+
+	updatedJsonData, err := json.Marshal(accountData)
+	if err != nil {
+		return res, err
+	}
+
+	err = os.WriteFile(fp, updatedJsonData, 0644)
+	if err != nil {
+		return res, err
+	}
+
+	return res, nil
+}
+
+func (h *Handlers) VerifyPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+
+	if bytes.Equal(input, []byte(accountData["AccountPIN"])) {
+		res.FlagSet = []uint32{models.USERFLAG_VALIDPIN}
+		res.FlagReset = []uint32{models.USERFLAG_PINMISMATCH}
+	} else {
+		res.FlagSet = []uint32{models.USERFLAG_PINMISMATCH}
+	}
+
+	return res, nil
+}
+
+func codeFromCtx(ctx context.Context) string {
+	var code string
+	engine.Logg.DebugCtxf(ctx, "in msg", "ctx", ctx, "val", code)
+	if ctx.Value("Language") != nil {
+		lang := ctx.Value("Language").(lang.Language)
+		code = lang.Code
+	}
+	return code
+}
+
+func (h *Handlers) SaveFirstname(cxt context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+	if len(input) > 0 {
+		name := string(input)
+		accountData["FirstName"] = name
+		updatedJsonData, err := json.Marshal(accountData)
+		if err != nil {
+			return res, err
+		}
+
+		err = os.WriteFile(fp, updatedJsonData, 0644)
+		if err != nil {
+			return res, err
+		}
+	}
+
+	return res, nil
+}
+
+func (h *Handlers) SaveFamilyname(cxt context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+	if len(input) > 0 {
+		//Save name
+		secondname := string(input)
+		accountData["FamilyName"] = secondname
+		updatedJsonData, err := json.Marshal(accountData)
+		if err != nil {
+			return res, err
+		}
+
+		err = os.WriteFile(fp, updatedJsonData, 0644)
+		if err != nil {
+			return res, err
+		}
+	}
+
+	return res, nil
+}
+
+func (h *Handlers) SaveYob(cxt context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+	if len(input) > 0 {
+		yob := string(input)
+		accountData["YOB"] = yob
+		updatedJsonData, err := json.Marshal(accountData)
+		if err != nil {
+			return res, err
+		}
+
+		err = os.WriteFile(fp, updatedJsonData, 0644)
+		if err != nil {
+			return res, err
+		}
+	}
+
+	return res, nil
+}
+
+func (h *Handlers) SaveLocation(cxt context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+	if len(input) > 0 {
+		location := string(input)
+		accountData["Location"] = location
+		updatedJsonData, err := json.Marshal(accountData)
+		if err != nil {
+			return res, err
+		}
+
+		err = os.WriteFile(fp, updatedJsonData, 0644)
+		if err != nil {
+			return res, err
+		}
+
+	}
+
+	return res, nil
+}
+
+func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+	if len(input) > 0 {
+		gender := string(input)
+
+		switch gender {
+		case "1":
+			gender = "Male"
+		case "2":
+			gender = "Female"
+		case "3":
+			gender = "Other"
+		}
+		accountData["Gender"] = gender
+		updatedJsonData, err := json.Marshal(accountData)
+		if err != nil {
+			return res, err
+		}
+
+		err = os.WriteFile(fp, updatedJsonData, 0644)
+		if err != nil {
+			return res, err
+		}
+	}
+	return res, nil
+}
+
+func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+	if len(input) > 0 {
+		offerings := string(input)
+		accountData["Offerings"] = offerings
+		updatedJsonData, err := json.Marshal(accountData)
+		if err != nil {
+			return res, err
+		}
+		err = os.WriteFile(fp, updatedJsonData, 0644)
+		if err != nil {
+			return res, err
+		}
+	}
+	return res, nil
+}
+
+func (h *Handlers) ResetUnlockForUpdate(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	res.FlagReset = append(res.FlagReset, models.USERFLAG_UNLOCKFORUPDATE)
+	return res, nil
+}
+
+func (h *Handlers) ResetAccountUnlocked(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
+	return res, nil
+}
+
+func (h *Handlers) CheckIdentifier(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+
+	res.Content = accountData["PublicKey"]
+
+	return res, nil
+}
+
+func (h *Handlers) Unlock(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	pin := string(input)
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+
+	if len(input) > 1 {
+		if pin != accountData["AccountPIN"] {
+			res.FlagSet = append(res.FlagSet, models.USERFLAG_INCORRECTPIN)
+			res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
+			return res, nil
+		}
+		if h.fs.St.MatchFlag(models.USERFLAG_ACCOUNT_UNLOCKED, false) {
+			res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTPIN)
+			res.FlagSet = append(res.FlagSet, models.USERFLAG_UNLOCKFORUPDATE)
+			res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_UNLOCKED)
+		} else {
+			res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
+		}
+	}
+	return res, nil
+}
+
+func (h *Handlers) ResetIncorrectPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTPIN)
+	return res, nil
+}
+
+func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+
+	//status, err := checkAccountStatus(accountData["TrackingId"])
+	status, err := server.CheckAccountStatus(accountData["TrackingId"])
+
+	if err != nil {
+		fmt.Println("Error checking account status:", err)
+		return res, nil
+	}
+
+	accountData["Status"] = status
+
+	if status == "SUCCESS" {
+		res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_SUCCESS)
+		res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_PENDING)
+	} else {
+		res.FlagReset = append(res.FlagSet, models.USERFLAG_ACCOUNT_SUCCESS)
+		res.FlagSet = append(res.FlagReset, models.USERFLAG_ACCOUNT_PENDING)
+	}
+
+	updatedJsonData, err := json.Marshal(accountData)
+	if err != nil {
+		return res, err
+	}
+
+	err = os.WriteFile(fp, updatedJsonData, 0644)
+	if err != nil {
+		return res, err
+	}
+
+	return res, nil
+}
+
+func (h *Handlers) Quit(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	switch codeFromCtx(ctx) {
+	case "swa":
+		res.Content = "Asante kwa kutumia huduma ya Sarafu. Kwaheri!"
+	default:
+		res.Content = "Thank you for using Sarafu. Goodbye!"
+	}
+	res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
+	return res, nil
+}
+
+func (h *Handlers) VerifyYob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	date := string(input)
+
+	dateRegex := regexp.MustCompile(`^\d{2}/\d{2}/\d{4}$`)
+	isCorrectFormat := dateRegex.MatchString(date)
+	if !isCorrectFormat {
+		res.FlagSet = append(res.FlagSet, models.USERFLAG_INCORRECTDATEFORMAT)
+	} else {
+		res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTDATEFORMAT)
+	}
+
+	return res, nil
+}
+
+func (h *Handlers) ResetIncorrectYob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTDATEFORMAT)
+	return res, nil
+}
+
+func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+
+	fp := h.fs.Path + "_data"
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+	balance, err := server.CheckBalance(accountData["PublicKey"])
+	if err != nil {
+		return res, nil
+	}
+	res.Content = balance
+
+	return res, nil
+}
+
+func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	recipient := string(input)
+
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+
+	if recipient != "0" {
+		// mimic invalid number check
+		if recipient == "000" {
+			res.FlagSet = append(res.FlagSet, models.USERFLAG_INVALID_RECIPIENT)
+			res.Content = recipient
+
+			return res, nil
+		}
+
+		accountData["Recipient"] = recipient
+
+		updatedJsonData, err := json.Marshal(accountData)
+		if err != nil {
+			return res, err
+		}
+
+		err = os.WriteFile(fp, updatedJsonData, 0644)
+		if err != nil {
+			return res, err
+		}
+	}
+
+	return res, nil
+}
+
+func (h *Handlers) TransactionReset(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+
+	// reset the recipient
+	accountData["Recipient"] = ""
+
+	updatedJsonData, err := json.Marshal(accountData)
+	if err != nil {
+		return res, err
+	}
+
+	err = os.WriteFile(fp, updatedJsonData, 0644)
+	if err != nil {
+		return res, err
+	}
+
+	res.FlagReset = append(res.FlagReset, models.USERFLAG_INVALID_RECIPIENT, models.USERFLAG_INVALID_RECIPIENT_WITH_INVITE)
+
+	return res, nil
+}
+
+func (h *Handlers) ResetTransactionAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+
+	// reset the amount
+	accountData["Amount"] = ""
+
+	updatedJsonData, err := json.Marshal(accountData)
+	if err != nil {
+		return res, err
+	}
+
+	err = os.WriteFile(fp, updatedJsonData, 0644)
+	if err != nil {
+		return res, err
+	}
+
+	res.FlagReset = append(res.FlagReset, models.USERFLAG_INVALID_AMOUNT)
+
+	return res, nil
+}
+
+func (h *Handlers) MaxAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+
+	// mimic a max amount
+	res.Content = "10.00"
+
+	return res, nil
+}
+
+func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	amount := string(input)
+
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+
+	if amount != "0" {
+		// mimic invalid amount
+		if amount == "00" {
+			res.FlagSet = append(res.FlagSet, models.USERFLAG_INVALID_AMOUNT)
+			res.Content = amount
+
+			return res, nil
+		}
+
+		res.Content = amount
+
+		accountData["Amount"] = amount
+
+		updatedJsonData, err := json.Marshal(accountData)
+		if err != nil {
+			return res, err
+		}
+
+		err = os.WriteFile(fp, updatedJsonData, 0644)
+		if err != nil {
+			return res, err
+		}
+
+		return res, nil
+	}
+
+	return res, nil
+}
+
+func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+
+	res.Content = accountData["Recipient"]
+
+	return res, nil
+}
+
+func (h *Handlers) GetProfileInfo(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+	name := accountData["FirstName"] + " " + accountData["FamilyName"]
+	gender := accountData["Gender"]
+	yob := accountData["YOB"]
+	location := accountData["Location"]
+	offerings := accountData["Offerings"]
+
+	layout := "02/01/2006"
+
+	birthdate, err := time.Parse(layout, yob)
+	if err != nil {
+		return res, err
+	}
+
+	currentDate := time.Now()
+	formattedDate := currentDate.Format(layout)
+	today, err := time.Parse(layout, formattedDate)
+	if err != nil {
+		return res, nil
+	}
+	age := utils.CalculateAge(birthdate, today)
+
+	formattedData := fmt.Sprintf("Name: %s\nGender: %s\nAge: %d\nLocation: %s\nYou provide: %s\n", name, gender, age, location, offerings)
+	res.Content = formattedData
+
+	return res, nil
+}
+
+func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+
+	res.Content = accountData["PublicKey"]
+
+	return res, nil
+}
+
+func (h *Handlers) QuitWithBalance(ctx context.Context, sym string, input []byte) (resource.Result, error) {
+	res := resource.Result{}
+	fp := h.fs.Path + "_data"
+
+	jsonData, err := os.ReadFile(fp)
+	if err != nil {
+		return res, err
+	}
+
+	var accountData map[string]string
+	err = json.Unmarshal(jsonData, &accountData)
+	if err != nil {
+		return res, err
+	}
+	balance, err := server.CheckBalance(accountData["PublicKey"])
+	if err != nil {
+		return res, nil
+	}
+	res.Content = fmt.Sprintf("Your account balance is: %s", balance)
+	res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
+	return res, nil
+}