Compare commits
No commits in common. "1d82bc2261e6a1540e74aaf293fcf34d3bf68d0a" and "6fa0d8e2ffc9cc5518915f8b1ebfc6eb1fb53356" have entirely different histories.
1d82bc2261
...
6fa0d8e2ff
@ -1,115 +0,0 @@
|
|||||||
package common
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.grassecon.net/urdt/ussd/internal/storage"
|
|
||||||
dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TransferMetadata helps organize data fields
|
|
||||||
type TransferMetadata struct {
|
|
||||||
Senders string
|
|
||||||
Recipients string
|
|
||||||
TransferValues string
|
|
||||||
Addresses string
|
|
||||||
TxHashes string
|
|
||||||
Dates string
|
|
||||||
Symbols string
|
|
||||||
Decimals string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessTransfers converts transfers into formatted strings
|
|
||||||
func ProcessTransfers(transfers []dataserviceapi.Last10TxResponse) TransferMetadata {
|
|
||||||
var data TransferMetadata
|
|
||||||
var senders, recipients, transferValues, addresses, txHashes, dates, symbols, decimals []string
|
|
||||||
|
|
||||||
for _, t := range transfers {
|
|
||||||
senders = append(senders, t.Sender)
|
|
||||||
recipients = append(recipients, t.Recipient)
|
|
||||||
|
|
||||||
// Scale down the amount
|
|
||||||
scaledBalance := ScaleDownBalance(t.TransferValue, t.TokenDecimals)
|
|
||||||
transferValues = append(transferValues, scaledBalance)
|
|
||||||
|
|
||||||
addresses = append(addresses, t.ContractAddress)
|
|
||||||
txHashes = append(txHashes, t.TxHash)
|
|
||||||
dates = append(dates, fmt.Sprintf("%s", t.DateBlock))
|
|
||||||
symbols = append(symbols, t.TokenSymbol)
|
|
||||||
decimals = append(decimals, t.TokenDecimals)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.Senders = strings.Join(senders, "\n")
|
|
||||||
data.Recipients = strings.Join(recipients, "\n")
|
|
||||||
data.TransferValues = strings.Join(transferValues, "\n")
|
|
||||||
data.Addresses = strings.Join(addresses, "\n")
|
|
||||||
data.TxHashes = strings.Join(txHashes, "\n")
|
|
||||||
data.Dates = strings.Join(dates, "\n")
|
|
||||||
data.Symbols = strings.Join(symbols, "\n")
|
|
||||||
data.Decimals = strings.Join(decimals, "\n")
|
|
||||||
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTransferData retrieves and matches transfer data
|
|
||||||
// returns a formatted string of the full transaction/statement
|
|
||||||
func GetTransferData(ctx context.Context, db storage.PrefixDb, publicKey string, index int) (string, error) {
|
|
||||||
keys := []string{"txfrom", "txto", "txval", "txaddr", "txhash", "txdate", "txsym"}
|
|
||||||
data := make(map[string]string)
|
|
||||||
|
|
||||||
for _, key := range keys {
|
|
||||||
value, err := db.Get(ctx, []byte(key))
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to get %s: %v", key, err)
|
|
||||||
}
|
|
||||||
data[key] = string(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split the data
|
|
||||||
senders := strings.Split(string(data["txfrom"]), "\n")
|
|
||||||
recipients := strings.Split(string(data["txto"]), "\n")
|
|
||||||
values := strings.Split(string(data["txval"]), "\n")
|
|
||||||
addresses := strings.Split(string(data["txaddr"]), "\n")
|
|
||||||
hashes := strings.Split(string(data["txhash"]), "\n")
|
|
||||||
dates := strings.Split(string(data["txdate"]), "\n")
|
|
||||||
syms := strings.Split(string(data["txsym"]), "\n")
|
|
||||||
|
|
||||||
// Adjust for 0-based indexing
|
|
||||||
i := index - 1
|
|
||||||
transactionType := "received"
|
|
||||||
party := fmt.Sprintf("from: %s", strings.TrimSpace(senders[i]))
|
|
||||||
if strings.TrimSpace(senders[i]) == publicKey {
|
|
||||||
transactionType = "sent"
|
|
||||||
party = fmt.Sprintf("to: %s", strings.TrimSpace(recipients[i]))
|
|
||||||
}
|
|
||||||
|
|
||||||
formattedDate := formatDate(strings.TrimSpace(dates[i]))
|
|
||||||
|
|
||||||
// Build the full transaction detail
|
|
||||||
detail := fmt.Sprintf(
|
|
||||||
"%s %s %s\n%s\ncontract address: %s\ntxhash: %s\ndate: %s",
|
|
||||||
transactionType,
|
|
||||||
strings.TrimSpace(values[i]),
|
|
||||||
strings.TrimSpace(syms[i]),
|
|
||||||
party,
|
|
||||||
strings.TrimSpace(addresses[i]),
|
|
||||||
strings.TrimSpace(hashes[i]),
|
|
||||||
formattedDate,
|
|
||||||
)
|
|
||||||
|
|
||||||
return detail, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to format date in desired output
|
|
||||||
func formatDate(dateStr string) string {
|
|
||||||
fmt.Println(dateStr)
|
|
||||||
parsedDate, err := time.Parse("2006-01-02 15:04:05 -0700 MST", dateStr)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error parsing date:", err)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return parsedDate.Format("2006-01-02 03:04:05 PM")
|
|
||||||
}
|
|
@ -118,9 +118,7 @@ func (ls *LocalHandlerService) GetHandler(accountService remote.AccountServiceIn
|
|||||||
ls.DbRs.AddLocalFunc("reset_others_pin", ussdHandlers.ResetOthersPin)
|
ls.DbRs.AddLocalFunc("reset_others_pin", ussdHandlers.ResetOthersPin)
|
||||||
ls.DbRs.AddLocalFunc("save_others_temporary_pin", ussdHandlers.SaveOthersTemporaryPin)
|
ls.DbRs.AddLocalFunc("save_others_temporary_pin", ussdHandlers.SaveOthersTemporaryPin)
|
||||||
ls.DbRs.AddLocalFunc("get_current_profile_info", ussdHandlers.GetCurrentProfileInfo)
|
ls.DbRs.AddLocalFunc("get_current_profile_info", ussdHandlers.GetCurrentProfileInfo)
|
||||||
ls.DbRs.AddLocalFunc("check_transactions", ussdHandlers.CheckTransactions)
|
ls.DbRs.AddLocalFunc("get_transactions", ussdHandlers.GetTransactions)
|
||||||
ls.DbRs.AddLocalFunc("get_transactions", ussdHandlers.GetTransactionsList)
|
|
||||||
ls.DbRs.AddLocalFunc("view_statement", ussdHandlers.ViewTransactionStatement)
|
|
||||||
|
|
||||||
return ussdHandlers, nil
|
return ussdHandlers, nil
|
||||||
}
|
}
|
||||||
|
@ -1634,171 +1634,11 @@ func (h *Handlers) GetVoucherDetails(ctx context.Context, sym string, input []by
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckTransactions retrieves the transactions from the API using the "PublicKey" and stores to prefixDb
|
// GetTransactions retrieves the transactions from the API using the "PublicKey"
|
||||||
func (h *Handlers) CheckTransactions(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) GetTransactions(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
var res resource.Result
|
var res resource.Result
|
||||||
sessionId, ok := ctx.Value("SessionId").(string)
|
|
||||||
if !ok {
|
|
||||||
return res, fmt.Errorf("missing session")
|
|
||||||
}
|
|
||||||
|
|
||||||
flag_no_transfers, _ := h.flagManager.GetFlag("flag_no_transfers")
|
res.Content = "Transaction list"
|
||||||
flag_api_error, _ := h.flagManager.GetFlag("flag_api_error")
|
|
||||||
|
|
||||||
store := h.userdataStore
|
|
||||||
publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY)
|
|
||||||
if err != nil {
|
|
||||||
logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", common.DATA_PUBLIC_KEY, "error", err)
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch transactions from the API using the public key
|
|
||||||
transactionsResp, err := h.accountService.FetchTransactions(ctx, string(publicKey))
|
|
||||||
if err != nil {
|
|
||||||
res.FlagSet = append(res.FlagSet, flag_api_error)
|
|
||||||
logg.ErrorCtxf(ctx, "failed on FetchTransactions", "error", err)
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return if there are no transactions
|
|
||||||
if len(transactionsResp) == 0 {
|
|
||||||
res.FlagSet = append(res.FlagSet, flag_no_transfers)
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data := common.ProcessTransfers(transactionsResp)
|
|
||||||
|
|
||||||
// Store all transaction data
|
|
||||||
dataMap := map[string]string{
|
|
||||||
"txfrom": data.Senders,
|
|
||||||
"txto": data.Recipients,
|
|
||||||
"txval": data.TransferValues,
|
|
||||||
"txaddr": data.Addresses,
|
|
||||||
"txhash": data.TxHashes,
|
|
||||||
"txdate": data.Dates,
|
|
||||||
"txsym": data.Symbols,
|
|
||||||
"txdeci": data.Decimals,
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, value := range dataMap {
|
|
||||||
if err := h.prefixDb.Put(ctx, []byte(key), []byte(value)); err != nil {
|
|
||||||
logg.ErrorCtxf(ctx, "failed to write to prefixDb", "error", err)
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res.FlagReset = append(res.FlagReset, flag_no_transfers)
|
|
||||||
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTransactionsList fetches the list of transactions and formats them
|
|
||||||
func (h *Handlers) GetTransactionsList(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
|
||||||
var res resource.Result
|
|
||||||
sessionId, ok := ctx.Value("SessionId").(string)
|
|
||||||
if !ok {
|
|
||||||
return res, fmt.Errorf("missing session")
|
|
||||||
}
|
|
||||||
store := h.userdataStore
|
|
||||||
publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY)
|
|
||||||
if err != nil {
|
|
||||||
logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", common.DATA_PUBLIC_KEY, "error", err)
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read transactions from the store and format them
|
|
||||||
TransactionSenders, err := h.prefixDb.Get(ctx, []byte("txfrom"))
|
|
||||||
if err != nil {
|
|
||||||
logg.ErrorCtxf(ctx, "Failed to read the TransactionSenders from prefixDb", "error", err)
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
TransactionSyms, err := h.prefixDb.Get(ctx, []byte("txsym"))
|
|
||||||
if err != nil {
|
|
||||||
logg.ErrorCtxf(ctx, "Failed to read the TransactionSyms from prefixDb", "error", err)
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
TransactionValues, err := h.prefixDb.Get(ctx, []byte("txval"))
|
|
||||||
if err != nil {
|
|
||||||
logg.ErrorCtxf(ctx, "Failed to read the TransactionValues from prefixDb", "error", err)
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
TransactionDates, err := h.prefixDb.Get(ctx, []byte("txdate"))
|
|
||||||
if err != nil {
|
|
||||||
logg.ErrorCtxf(ctx, "Failed to read the TransactionDates from prefixDb", "error", err)
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the data
|
|
||||||
senders := strings.Split(string(TransactionSenders), "\n")
|
|
||||||
syms := strings.Split(string(TransactionSyms), "\n")
|
|
||||||
values := strings.Split(string(TransactionValues), "\n")
|
|
||||||
dates := strings.Split(string(TransactionDates), "\n")
|
|
||||||
|
|
||||||
var formattedTransactions []string
|
|
||||||
for i := 0; i < len(senders); i++ {
|
|
||||||
sender := strings.TrimSpace(senders[i])
|
|
||||||
sym := strings.TrimSpace(syms[i])
|
|
||||||
value := strings.TrimSpace(values[i])
|
|
||||||
date := strings.Split(strings.TrimSpace(dates[i]), " ")[0]
|
|
||||||
|
|
||||||
status := "received"
|
|
||||||
if sender == string(publicKey) {
|
|
||||||
status = "sent"
|
|
||||||
}
|
|
||||||
|
|
||||||
formattedTransactions = append(formattedTransactions, fmt.Sprintf("%d:%s %s %s %s", i+1, status, value, sym, date))
|
|
||||||
}
|
|
||||||
|
|
||||||
res.Content = strings.Join(formattedTransactions, "\n")
|
|
||||||
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ViewTransactionStatement retrieves the token holding and balance from the subprefixDB
|
|
||||||
// and displays it to the user for them to select it
|
|
||||||
func (h *Handlers) ViewTransactionStatement(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
|
||||||
var res resource.Result
|
|
||||||
sessionId, ok := ctx.Value("SessionId").(string)
|
|
||||||
if !ok {
|
|
||||||
return res, fmt.Errorf("missing session")
|
|
||||||
}
|
|
||||||
store := h.userdataStore
|
|
||||||
publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY)
|
|
||||||
if err != nil {
|
|
||||||
logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", common.DATA_PUBLIC_KEY, "error", err)
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
flag_incorrect_statement, _ := h.flagManager.GetFlag("flag_incorrect_statement")
|
|
||||||
|
|
||||||
inputStr := string(input)
|
|
||||||
if inputStr == "0" || inputStr == "99" || inputStr == "11" || inputStr == "22" {
|
|
||||||
res.FlagReset = append(res.FlagReset, flag_incorrect_statement)
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert input string to integer
|
|
||||||
index, err := strconv.Atoi(strings.TrimSpace(inputStr))
|
|
||||||
if err != nil {
|
|
||||||
return res, fmt.Errorf("invalid input: must be a number between 1 and 10")
|
|
||||||
}
|
|
||||||
|
|
||||||
if index < 1 || index > 10 {
|
|
||||||
return res, fmt.Errorf("invalid input: index must be between 1 and 10")
|
|
||||||
}
|
|
||||||
|
|
||||||
statement, err := common.GetTransferData(ctx, h.prefixDb, string(publicKey), index)
|
|
||||||
if err != nil {
|
|
||||||
return res, fmt.Errorf("failed to retrieve transfer data: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if statement == "" {
|
|
||||||
res.FlagSet = append(res.FlagSet, flag_incorrect_statement)
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
res.FlagReset = append(res.FlagReset, flag_incorrect_statement)
|
|
||||||
res.Content = statement
|
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
LOAD check_transactions 0
|
|
||||||
RELOAD check_transactions
|
|
||||||
CATCH no_transfers flag_no_transfers 1
|
|
||||||
LOAD authorize_account 6
|
LOAD authorize_account 6
|
||||||
MOUT back 0
|
MOUT back 0
|
||||||
MOUT quit 9
|
MOUT quit 9
|
||||||
|
@ -1 +0,0 @@
|
|||||||
No transfers history
|
|
@ -1,5 +0,0 @@
|
|||||||
MOUT back 0
|
|
||||||
MOUT quit 9
|
|
||||||
HALT
|
|
||||||
INCMP ^ 0
|
|
||||||
INCMP quit 9
|
|
@ -1 +0,0 @@
|
|||||||
Hakuna historia kwa akaunti yako
|
|
@ -19,5 +19,3 @@ flag,flag_api_call_error,25,this is set when communication to an external servic
|
|||||||
flag,flag_no_active_voucher,26,this is set when a user does not have an active voucher
|
flag,flag_no_active_voucher,26,this is set when a user does not have an active voucher
|
||||||
flag,flag_admin_privilege,27,this is set when a user has admin privileges.
|
flag,flag_admin_privilege,27,this is set when a user has admin privileges.
|
||||||
flag,flag_unregistered_number,28,this is set when an unregistered phonenumber tries to perform an action
|
flag,flag_unregistered_number,28,this is set when an unregistered phonenumber tries to perform an action
|
||||||
flag,flag_no_transfers,29,this is set when a user does not have any transactions
|
|
||||||
flag,flag_incorrect_statement,30,this is set when the selected statement is invalid
|
|
||||||
|
|
@ -5,11 +5,7 @@ MOUT quit 99
|
|||||||
MNEXT next 11
|
MNEXT next 11
|
||||||
MPREV prev 22
|
MPREV prev 22
|
||||||
HALT
|
HALT
|
||||||
LOAD view_statement 0
|
|
||||||
RELOAD view_statement
|
|
||||||
CATCH . flag_incorrect_statement 1
|
|
||||||
INCMP _ 0
|
INCMP _ 0
|
||||||
INCMP quit 99
|
INCMP quit 99
|
||||||
INCMP > 11
|
INCMP > 11
|
||||||
INCMP < 22
|
INCMP < 22
|
||||||
INCMP view_statement *
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
{{.view_statement}}
|
|
@ -1,10 +0,0 @@
|
|||||||
MAP view_statement
|
|
||||||
MOUT back 0
|
|
||||||
MOUT quit 9
|
|
||||||
MNEXT next 11
|
|
||||||
MPREV prev 22
|
|
||||||
HALT
|
|
||||||
INCMP _ 0
|
|
||||||
INCMP quit 9
|
|
||||||
INCMP > 11
|
|
||||||
INCMP < 22
|
|
Loading…
Reference in New Issue
Block a user