From 5b312f9569f0a98dc204a3bd4cb733ead89fb465 Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 12 Jan 2025 07:59:03 +0000 Subject: [PATCH] Move out common, util, debug, storage to sarafu-vise --- common/db.go | 134 --------------------- common/hex.go | 31 ----- common/pin.go | 37 ------ common/pin_test.go | 173 -------------------------- common/recipient.go | 73 ----------- common/storage.go | 69 ----------- common/tokens.go | 81 ------------- common/tokens_test.go | 129 -------------------- common/transfer_statements.go | 119 ------------------ common/user_store.go | 34 ------ common/vouchers.go | 174 --------------------------- common/vouchers_test.go | 200 ------------------------------- debug/cap.go | 5 - debug/db.go | 84 ------------- debug/db_debug.go | 44 ------- debug/db_test.go | 78 ------------ storage/db/sub_prefix_db.go | 43 ------- storage/db/sub_prefix_db_test.go | 54 --------- utils/age.go | 56 --------- utils/isocode.go | 11 -- utils/name.go | 17 --- 21 files changed, 1646 deletions(-) delete mode 100644 common/db.go delete mode 100644 common/hex.go delete mode 100644 common/pin.go delete mode 100644 common/pin_test.go delete mode 100644 common/recipient.go delete mode 100644 common/storage.go delete mode 100644 common/tokens.go delete mode 100644 common/tokens_test.go delete mode 100644 common/transfer_statements.go delete mode 100644 common/user_store.go delete mode 100644 common/vouchers.go delete mode 100644 common/vouchers_test.go delete mode 100644 debug/cap.go delete mode 100644 debug/db.go delete mode 100644 debug/db_debug.go delete mode 100644 debug/db_test.go delete mode 100644 storage/db/sub_prefix_db.go delete mode 100644 storage/db/sub_prefix_db_test.go delete mode 100644 utils/age.go delete mode 100644 utils/isocode.go delete mode 100644 utils/name.go diff --git a/common/db.go b/common/db.go deleted file mode 100644 index 2271716..0000000 --- a/common/db.go +++ /dev/null @@ -1,134 +0,0 @@ -package common - -import ( - "encoding/binary" - "errors" - - "git.defalsify.org/vise.git/logging" -) - -// DataType is a subprefix value used in association with vise/db.DATATYPE_USERDATA. -// -// All keys are used only within the context of a single account. Unless otherwise specified, the user context is the session id. -// -// * The first byte is vise/db.DATATYPE_USERDATA -// * The last 2 bytes are the DataTyp value, big-endian. -// * The intermediate bytes are the id of the user context. -// -// All values are strings -type DataTyp uint16 - -const ( - // API Tracking id to follow status of account creation - DATA_TRACKING_ID = iota - // EVM address returned from API on account creation - DATA_PUBLIC_KEY - // Currently active PIN used to authenticate ussd state change requests - DATA_ACCOUNT_PIN - // The first name of the user - DATA_FIRST_NAME - // The last name of the user - DATA_FAMILY_NAME - // The year-of-birth of the user - DATA_YOB - // The location of the user - DATA_LOCATION - // The gender of the user - DATA_GENDER - // The offerings description of the user - DATA_OFFERINGS - // The ethereum address of the recipient of an ongoing send request - DATA_RECIPIENT - // The voucher value amount of an ongoing send request - DATA_AMOUNT - // A general swap field for temporary values - DATA_TEMPORARY_VALUE - // Currently active voucher symbol of user - DATA_ACTIVE_SYM - // Voucher balance of user's currently active voucher - DATA_ACTIVE_BAL - // String boolean indicating whether use of PIN is blocked - DATA_BLOCKED_NUMBER - // Reverse mapping of a user's evm address to a session id. - DATA_PUBLIC_KEY_REVERSE - // Decimal count of the currently active voucher - DATA_ACTIVE_DECIMAL - // EVM address of the currently active voucher - DATA_ACTIVE_ADDRESS - //Holds count of the number of incorrect PIN attempts - DATA_INCORRECT_PIN_ATTEMPTS - //ISO 639 code for the selected language. - DATA_SELECTED_LANGUAGE_CODE -) - -const ( - // List of valid voucher symbols in the user context. - DATA_VOUCHER_SYMBOLS DataTyp = 256 + iota - // List of voucher balances for vouchers valid in the user context. - DATA_VOUCHER_BALANCES - // List of voucher decimal counts for vouchers valid in the user context. - DATA_VOUCHER_DECIMALS - // List of voucher EVM addresses for vouchers valid in the user context. - DATA_VOUCHER_ADDRESSES - // List of senders for valid transactions in the user context. -) - -const ( - DATA_TX_SENDERS = 512 + iota - // List of recipients for valid transactions in the user context. - DATA_TX_RECIPIENTS - // List of voucher values for valid transactions in the user context. - DATA_TX_VALUES - // List of voucher EVM addresses for valid transactions in the user context. - DATA_TX_ADDRESSES - // List of valid transaction hashes in the user context. - DATA_TX_HASHES - // List of transaction dates for valid transactions in the user context. - DATA_TX_DATES - // List of voucher symbols for valid transactions in the user context. - DATA_TX_SYMBOLS - // List of voucher decimal counts for valid transactions in the user context. - DATA_TX_DECIMALS -) - -var ( - logg = logging.NewVanilla().WithDomain("urdt-common") -) - -func typToBytes(typ DataTyp) []byte { - var b [2]byte - binary.BigEndian.PutUint16(b[:], uint16(typ)) - return b[:] -} - -func PackKey(typ DataTyp, data []byte) []byte { - v := typToBytes(typ) - return append(v, data...) -} - -func StringToDataTyp(str string) (DataTyp, error) { - switch str { - case "DATA_FIRST_NAME": - return DATA_FIRST_NAME, nil - case "DATA_FAMILY_NAME": - return DATA_FAMILY_NAME, nil - case "DATA_YOB": - return DATA_YOB, nil - case "DATA_LOCATION": - return DATA_LOCATION, nil - case "DATA_GENDER": - return DATA_GENDER, nil - case "DATA_OFFERINGS": - return DATA_OFFERINGS, nil - - default: - return 0, errors.New("invalid DataTyp string") - } -} - -// ToBytes converts DataTyp or int to a byte slice -func ToBytes[T ~uint16 | int](value T) []byte { - bytes := make([]byte, 2) - binary.BigEndian.PutUint16(bytes, uint16(value)) - return bytes -} diff --git a/common/hex.go b/common/hex.go deleted file mode 100644 index 971ecf1..0000000 --- a/common/hex.go +++ /dev/null @@ -1,31 +0,0 @@ -package common - -import ( - "encoding/hex" - "strings" -) - -func NormalizeHex(s string) (string, error) { - if len(s) >= 2 { - if s[:2] == "0x" { - s = s[2:] - } - } - r, err := hex.DecodeString(s) - if err != nil { - return "", err - } - return hex.EncodeToString(r), nil -} - -func IsSameHex(left string, right string) bool { - bl, err := NormalizeHex(left) - if err != nil { - return false - } - br, err := NormalizeHex(left) - if err != nil { - return false - } - return strings.Compare(bl, br) == 0 -} diff --git a/common/pin.go b/common/pin.go deleted file mode 100644 index 13f21b3..0000000 --- a/common/pin.go +++ /dev/null @@ -1,37 +0,0 @@ -package common - -import ( - "regexp" - - "golang.org/x/crypto/bcrypt" -) - -const ( - // Define the regex pattern as a constant - pinPattern = `^\d{4}$` - - //Allowed incorrect PIN attempts - AllowedPINAttempts = uint8(3) - -) - -// checks whether the given input is a 4 digit number -func IsValidPIN(pin string) bool { - match, _ := regexp.MatchString(pinPattern, pin) - return match -} - -// HashPIN uses bcrypt with 8 salt rounds to hash the PIN -func HashPIN(pin string) (string, error) { - hash, err := bcrypt.GenerateFromPassword([]byte(pin), 8) - if err != nil { - return "", err - } - return string(hash), nil -} - -// VerifyPIN compareS the hashed PIN with the plaintext PIN -func VerifyPIN(hashedPIN, pin string) bool { - err := bcrypt.CompareHashAndPassword([]byte(hashedPIN), []byte(pin)) - return err == nil -} diff --git a/common/pin_test.go b/common/pin_test.go deleted file mode 100644 index 154ab06..0000000 --- a/common/pin_test.go +++ /dev/null @@ -1,173 +0,0 @@ -package common - -import ( - "testing" - - "golang.org/x/crypto/bcrypt" -) - -func TestIsValidPIN(t *testing.T) { - tests := []struct { - name string - pin string - expected bool - }{ - { - name: "Valid PIN with 4 digits", - pin: "1234", - expected: true, - }, - { - name: "Valid PIN with leading zeros", - pin: "0001", - expected: true, - }, - { - name: "Invalid PIN with less than 4 digits", - pin: "123", - expected: false, - }, - { - name: "Invalid PIN with more than 4 digits", - pin: "12345", - expected: false, - }, - { - name: "Invalid PIN with letters", - pin: "abcd", - expected: false, - }, - { - name: "Invalid PIN with special characters", - pin: "12@#", - expected: false, - }, - { - name: "Empty PIN", - pin: "", - expected: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - actual := IsValidPIN(tt.pin) - if actual != tt.expected { - t.Errorf("IsValidPIN(%q) = %v; expected %v", tt.pin, actual, tt.expected) - } - }) - } -} - -func TestHashPIN(t *testing.T) { - tests := []struct { - name string - pin string - }{ - { - name: "Valid PIN with 4 digits", - pin: "1234", - }, - { - name: "Valid PIN with leading zeros", - pin: "0001", - }, - { - name: "Empty PIN", - pin: "", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - hashedPIN, err := HashPIN(tt.pin) - if err != nil { - t.Errorf("HashPIN(%q) returned an error: %v", tt.pin, err) - return - } - - if hashedPIN == "" { - t.Errorf("HashPIN(%q) returned an empty hash", tt.pin) - } - - // Ensure the hash can be verified with bcrypt - err = bcrypt.CompareHashAndPassword([]byte(hashedPIN), []byte(tt.pin)) - if tt.pin != "" && err != nil { - t.Errorf("HashPIN(%q) produced a hash that does not match: %v", tt.pin, err) - } - }) - } -} - -func TestVerifyMigratedHashPin(t *testing.T) { - tests := []struct { - pin string - hash string - }{ - { - pin: "1234", - hash: "$2b$08$dTvIGxCCysJtdvrSnaLStuylPoOS/ZLYYkxvTeR5QmTFY3TSvPQC6", - }, - } - - for _, tt := range tests { - t.Run(tt.pin, func(t *testing.T) { - ok := VerifyPIN(tt.hash, tt.pin) - if !ok { - t.Errorf("VerifyPIN could not verify migrated PIN: %v", tt.pin) - } - }) - } -} - -func TestVerifyPIN(t *testing.T) { - tests := []struct { - name string - pin string - hashedPIN string - shouldPass bool - }{ - { - name: "Valid PIN verification", - pin: "1234", - hashedPIN: hashPINHelper("1234"), - shouldPass: true, - }, - { - name: "Invalid PIN verification with incorrect PIN", - pin: "5678", - hashedPIN: hashPINHelper("1234"), - shouldPass: false, - }, - { - name: "Invalid PIN verification with empty PIN", - pin: "", - hashedPIN: hashPINHelper("1234"), - shouldPass: false, - }, - { - name: "Invalid PIN verification with invalid hash", - pin: "1234", - hashedPIN: "invalidhash", - shouldPass: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := VerifyPIN(tt.hashedPIN, tt.pin) - if result != tt.shouldPass { - t.Errorf("VerifyPIN(%q, %q) = %v; expected %v", tt.hashedPIN, tt.pin, result, tt.shouldPass) - } - }) - } -} - -// Helper function to hash a PIN for testing purposes -func hashPINHelper(pin string) string { - hashedPIN, err := HashPIN(pin) - if err != nil { - panic("Failed to hash PIN for test setup: " + err.Error()) - } - return hashedPIN -} diff --git a/common/recipient.go b/common/recipient.go deleted file mode 100644 index f463a32..0000000 --- a/common/recipient.go +++ /dev/null @@ -1,73 +0,0 @@ -package common - -import ( - "errors" - "fmt" - "regexp" - "strings" -) - -// Define the regex patterns as constants -const ( - phoneRegex = `^(?:\+254|254|0)?((?:7[0-9]{8})|(?:1[01][0-9]{7}))$` - addressRegex = `^0x[a-fA-F0-9]{40}$` - aliasRegex = `^[a-zA-Z0-9]+$` -) - -// IsValidPhoneNumber checks if the given number is a valid phone number -func IsValidPhoneNumber(phonenumber string) bool { - match, _ := regexp.MatchString(phoneRegex, phonenumber) - return match -} - -// IsValidAddress checks if the given address is a valid Ethereum address -func IsValidAddress(address string) bool { - match, _ := regexp.MatchString(addressRegex, address) - return match -} - -// IsValidAlias checks if the alias is a valid alias format -func IsValidAlias(alias string) bool { - match, _ := regexp.MatchString(aliasRegex, alias) - return match -} - -// CheckRecipient validates the recipient format based on the criteria -func CheckRecipient(recipient string) (string, error) { - if IsValidPhoneNumber(recipient) { - return "phone number", nil - } - - if IsValidAddress(recipient) { - return "address", nil - } - - if IsValidAlias(recipient) { - return "alias", nil - } - - return "", fmt.Errorf("invalid recipient: must be a phone number, address or alias") -} - -// FormatPhoneNumber formats a Kenyan phone number to "+254xxxxxxxx". -func FormatPhoneNumber(phone string) (string, error) { - if !IsValidPhoneNumber(phone) { - return "", errors.New("invalid phone number") - } - - // Remove any leading "+" and spaces - phone = strings.TrimPrefix(phone, "+") - phone = strings.ReplaceAll(phone, " ", "") - - // Replace leading "0" with "254" if present - if strings.HasPrefix(phone, "0") { - phone = "254" + phone[1:] - } - - // Add "+" if not already present - if !strings.HasPrefix(phone, "254") { - return "", errors.New("unexpected format") - } - - return "+" + phone, nil -} diff --git a/common/storage.go b/common/storage.go deleted file mode 100644 index 4887d0f..0000000 --- a/common/storage.go +++ /dev/null @@ -1,69 +0,0 @@ -package common - -import ( - "context" - "errors" - - "git.defalsify.org/vise.git/db" - "git.defalsify.org/vise.git/resource" - "git.defalsify.org/vise.git/persist" - "git.defalsify.org/vise.git/lang" - "git.grassecon.net/grassrootseconomics/visedriver/storage" - dbstorage "git.grassecon.net/grassrootseconomics/visedriver/storage/db" -) - -var ( - ToConnData = storage.ToConnData -) - -func StoreToDb(store *UserDataStore) db.Db { - return store.Db -} - -func StoreToPrefixDb(store *UserDataStore, pfx []byte) dbstorage.PrefixDb { - return dbstorage.NewSubPrefixDb(store.Db, pfx) -} - -type StorageServices interface { - GetPersister(ctx context.Context) (*persist.Persister, error) - GetUserdataDb(ctx context.Context) (db.Db, error) - GetResource(ctx context.Context) (resource.Resource, error) -} - -type StorageService struct { - svc *storage.MenuStorageService -} - -func NewStorageService(conn storage.ConnData) (*StorageService, error) { - svc := &StorageService{ - svc: storage.NewMenuStorageService(conn, ""), - } - return svc, nil -} - -func (ss *StorageService) WithGettext(path string, lns []lang.Language) *StorageService { - ss.svc = ss.svc.WithGettext(path, lns) - return ss -} - -// TODO: simplify enable poresource, conndata instead -func(ss *StorageService) SetResourceDir(resourceDir string) error { - ss.svc = ss.svc.WithResourceDir(resourceDir) - return nil -} - -func(ss *StorageService) GetPersister(ctx context.Context) (*persist.Persister, error) { - return ss.svc.GetPersister(ctx) -} - -func(ss *StorageService) GetUserdataDb(ctx context.Context) (db.Db, error) { - return ss.svc.GetUserdataDb(ctx) -} - -func(ss *StorageService) GetResource(ctx context.Context) (resource.Resource, error) { - return nil, errors.New("not implemented") -} - -func(ss *StorageService) GetStateStore(ctx context.Context) (db.Db, error) { - return ss.svc.GetStateStore(ctx) -} diff --git a/common/tokens.go b/common/tokens.go deleted file mode 100644 index 466f370..0000000 --- a/common/tokens.go +++ /dev/null @@ -1,81 +0,0 @@ -package common - -import ( - "context" - "errors" - "math/big" - "reflect" - "strconv" -) - -type TransactionData struct { - TemporaryValue string - ActiveSym string - Amount string - PublicKey string - Recipient string - ActiveDecimal string - ActiveAddress string -} - -func ParseAndScaleAmount(storedAmount, activeDecimal string) (string, error) { - // Parse token decimal - tokenDecimal, err := strconv.Atoi(activeDecimal) - if err != nil { - - return "", err - } - - // Parse amount - amount, _, err := big.ParseFloat(storedAmount, 10, 0, big.ToZero) - if err != nil { - return "", err - } - - // Scale the amount - multiplier := new(big.Float).SetInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(tokenDecimal)), nil)) - finalAmount := new(big.Float).Mul(amount, multiplier) - - // Convert finalAmount to a string - finalAmountStr := new(big.Int) - finalAmount.Int(finalAmountStr) - - return finalAmountStr.String(), nil -} - -func ReadTransactionData(ctx context.Context, store DataStore, sessionId string) (TransactionData, error) { - data := TransactionData{} - fieldToKey := map[string]DataTyp{ - "TemporaryValue": DATA_TEMPORARY_VALUE, - "ActiveSym": DATA_ACTIVE_SYM, - "Amount": DATA_AMOUNT, - "PublicKey": DATA_PUBLIC_KEY, - "Recipient": DATA_RECIPIENT, - "ActiveDecimal": DATA_ACTIVE_DECIMAL, - "ActiveAddress": DATA_ACTIVE_ADDRESS, - } - - v := reflect.ValueOf(&data).Elem() - for fieldName, key := range fieldToKey { - field := v.FieldByName(fieldName) - if !field.IsValid() || !field.CanSet() { - return data, errors.New("invalid struct field: " + fieldName) - } - - value, err := readStringEntry(ctx, store, sessionId, key) - if err != nil { - return data, err - } - field.SetString(value) - } - - return data, nil -} - -func readStringEntry(ctx context.Context, store DataStore, sessionId string, key DataTyp) (string, error) { - entry, err := store.ReadEntry(ctx, sessionId, key) - if err != nil { - return "", err - } - return string(entry), nil -} diff --git a/common/tokens_test.go b/common/tokens_test.go deleted file mode 100644 index 06bd552..0000000 --- a/common/tokens_test.go +++ /dev/null @@ -1,129 +0,0 @@ -package common - -import ( - "testing" - - "github.com/alecthomas/assert/v2" -) - -func TestParseAndScaleAmount(t *testing.T) { - tests := []struct { - name string - amount string - decimals string - want string - expectError bool - }{ - { - name: "whole number", - amount: "123", - decimals: "2", - want: "12300", - expectError: false, - }, - { - name: "decimal number", - amount: "123.45", - decimals: "2", - want: "12345", - expectError: false, - }, - { - name: "zero decimals", - amount: "123.45", - decimals: "0", - want: "123", - expectError: false, - }, - { - name: "large number", - amount: "1000000.01", - decimals: "6", - want: "1000000010000", - expectError: false, - }, - { - name: "invalid amount", - amount: "abc", - decimals: "2", - want: "", - expectError: true, - }, - { - name: "invalid decimals", - amount: "123.45", - decimals: "abc", - want: "", - expectError: true, - }, - { - name: "zero amount", - amount: "0", - decimals: "2", - want: "0", - expectError: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := ParseAndScaleAmount(tt.amount, tt.decimals) - - // Check error cases - if tt.expectError { - if err == nil { - t.Errorf("ParseAndScaleAmount(%q, %q) expected error, got nil", tt.amount, tt.decimals) - } - return - } - - if err != nil { - t.Errorf("ParseAndScaleAmount(%q, %q) unexpected error: %v", tt.amount, tt.decimals, err) - return - } - - if got != tt.want { - t.Errorf("ParseAndScaleAmount(%q, %q) = %v, want %v", tt.amount, tt.decimals, got, tt.want) - } - }) - } -} - -func TestReadTransactionData(t *testing.T) { - sessionId := "session123" - publicKey := "0X13242618721" - ctx, store := InitializeTestDb(t) - - // Test transaction data - transactionData := map[DataTyp]string{ - DATA_TEMPORARY_VALUE: "0712345678", - DATA_ACTIVE_SYM: "SRF", - DATA_AMOUNT: "1000000", - DATA_PUBLIC_KEY: publicKey, - DATA_RECIPIENT: "0x41c188d63Qa", - DATA_ACTIVE_DECIMAL: "6", - DATA_ACTIVE_ADDRESS: "0xd4c288865Ce", - } - - // Store the data - for key, value := range transactionData { - if err := store.WriteEntry(ctx, sessionId, key, []byte(value)); err != nil { - t.Fatal(err) - } - } - - expectedResult := TransactionData{ - TemporaryValue: "0712345678", - ActiveSym: "SRF", - Amount: "1000000", - PublicKey: publicKey, - Recipient: "0x41c188d63Qa", - ActiveDecimal: "6", - ActiveAddress: "0xd4c288865Ce", - } - - data, err := ReadTransactionData(ctx, store, sessionId) - - assert.NoError(t, err) - assert.Equal(t, expectedResult, data) -} diff --git a/common/transfer_statements.go b/common/transfer_statements.go deleted file mode 100644 index 1f2ff42..0000000 --- a/common/transfer_statements.go +++ /dev/null @@ -1,119 +0,0 @@ -package common - -import ( - "context" - "fmt" - "strings" - "time" - - dbstorage "git.grassecon.net/grassrootseconomics/visedriver/storage/db" - 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 dbstorage.PrefixDb, publicKey string, index int) (string, error) { - keys := []DataTyp{DATA_TX_SENDERS, DATA_TX_RECIPIENTS, DATA_TX_VALUES, DATA_TX_ADDRESSES, DATA_TX_HASHES, DATA_TX_DATES, DATA_TX_SYMBOLS} - data := make(map[DataTyp]string) - - for _, key := range keys { - value, err := db.Get(ctx, ToBytes(key)) - if err != nil { - return "", fmt.Errorf("failed to get %s: %v", ToBytes(key), err) - } - data[key] = string(value) - } - - // Split the data - senders := strings.Split(string(data[DATA_TX_SENDERS]), "\n") - recipients := strings.Split(string(data[DATA_TX_RECIPIENTS]), "\n") - values := strings.Split(string(data[DATA_TX_VALUES]), "\n") - addresses := strings.Split(string(data[DATA_TX_ADDRESSES]), "\n") - hashes := strings.Split(string(data[DATA_TX_HASHES]), "\n") - dates := strings.Split(string(data[DATA_TX_DATES]), "\n") - syms := strings.Split(string(data[DATA_TX_SYMBOLS]), "\n") - - // Check if index is within range - if index < 1 || index > len(senders) { - return "", fmt.Errorf("transaction not found: index %d out of range", index) - } - - // 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 { - 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") -} diff --git a/common/user_store.go b/common/user_store.go deleted file mode 100644 index 6c770d8..0000000 --- a/common/user_store.go +++ /dev/null @@ -1,34 +0,0 @@ -package common - -import ( - "context" - - "git.defalsify.org/vise.git/db" -) - -type DataStore interface { - db.Db - ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) - WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error -} - -type UserDataStore struct { - db.Db -} - -// ReadEntry retrieves an entry to the userdata store. -func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) { - store.SetPrefix(db.DATATYPE_USERDATA) - store.SetSession(sessionId) - k := ToBytes(typ) - return store.Get(ctx, k) -} - -// WriteEntry adds an entry to the userdata store. -// BUG: this uses sessionId twice -func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error { - store.SetPrefix(db.DATATYPE_USERDATA) - store.SetSession(sessionId) - k := ToBytes(typ) - return store.Put(ctx, k, value) -} diff --git a/common/vouchers.go b/common/vouchers.go deleted file mode 100644 index cab32d0..0000000 --- a/common/vouchers.go +++ /dev/null @@ -1,174 +0,0 @@ -package common - -import ( - "context" - "fmt" - "math/big" - "strings" - - dbstorage "git.grassecon.net/grassrootseconomics/visedriver/storage/db" - dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" -) - -// VoucherMetadata helps organize data fields -type VoucherMetadata struct { - Symbols string - Balances string - Decimals string - Addresses string -} - -// ProcessVouchers converts holdings into formatted strings -func ProcessVouchers(holdings []dataserviceapi.TokenHoldings) VoucherMetadata { - var data VoucherMetadata - var symbols, balances, decimals, addresses []string - - for i, h := range holdings { - symbols = append(symbols, fmt.Sprintf("%d:%s", i+1, h.TokenSymbol)) - - // Scale down the balance - scaledBalance := ScaleDownBalance(h.Balance, h.TokenDecimals) - - balances = append(balances, fmt.Sprintf("%d:%s", i+1, scaledBalance)) - decimals = append(decimals, fmt.Sprintf("%d:%s", i+1, h.TokenDecimals)) - addresses = append(addresses, fmt.Sprintf("%d:%s", i+1, h.ContractAddress)) - } - - data.Symbols = strings.Join(symbols, "\n") - data.Balances = strings.Join(balances, "\n") - data.Decimals = strings.Join(decimals, "\n") - data.Addresses = strings.Join(addresses, "\n") - - return data -} - -func ScaleDownBalance(balance, decimals string) string { - // Convert balance and decimals to big.Float - bal := new(big.Float) - bal.SetString(balance) - - dec, ok := new(big.Int).SetString(decimals, 10) - if !ok { - dec = big.NewInt(0) // Default to 0 decimals in case of conversion failure - } - - divisor := new(big.Float).SetInt(new(big.Int).Exp(big.NewInt(10), dec, nil)) - scaledBalance := new(big.Float).Quo(bal, divisor) - - // Return the scaled balance without trailing decimals if it's an integer - if scaledBalance.IsInt() { - return scaledBalance.Text('f', 0) - } - return scaledBalance.Text('f', -1) -} - -// GetVoucherData retrieves and matches voucher data -func GetVoucherData(ctx context.Context, db dbstorage.PrefixDb, input string) (*dataserviceapi.TokenHoldings, error) { - keys := []DataTyp{DATA_VOUCHER_SYMBOLS, DATA_VOUCHER_BALANCES, DATA_VOUCHER_DECIMALS, DATA_VOUCHER_ADDRESSES} - data := make(map[DataTyp]string) - - for _, key := range keys { - value, err := db.Get(ctx, ToBytes(key)) - if err != nil { - return nil, fmt.Errorf("failed to get %s: %v", ToBytes(key), err) - } - data[key] = string(value) - } - - symbol, balance, decimal, address := MatchVoucher(input, - data[DATA_VOUCHER_SYMBOLS], - data[DATA_VOUCHER_BALANCES], - data[DATA_VOUCHER_DECIMALS], - data[DATA_VOUCHER_ADDRESSES], - ) - - if symbol == "" { - return nil, nil - } - - return &dataserviceapi.TokenHoldings{ - TokenSymbol: string(symbol), - Balance: string(balance), - TokenDecimals: string(decimal), - ContractAddress: string(address), - }, nil -} - -// MatchVoucher finds the matching voucher symbol, balance, decimals and contract address based on the input. -func MatchVoucher(input, symbols, balances, decimals, addresses string) (symbol, balance, decimal, address string) { - symList := strings.Split(symbols, "\n") - balList := strings.Split(balances, "\n") - decList := strings.Split(decimals, "\n") - addrList := strings.Split(addresses, "\n") - - logg.Tracef("found", "symlist", symList, "syms", symbols, "input", input) - for i, sym := range symList { - parts := strings.SplitN(sym, ":", 2) - - if input == parts[0] || strings.EqualFold(input, parts[1]) { - symbol = parts[1] - if i < len(balList) { - balance = strings.SplitN(balList[i], ":", 2)[1] - } - if i < len(decList) { - decimal = strings.SplitN(decList[i], ":", 2)[1] - } - if i < len(addrList) { - address = strings.SplitN(addrList[i], ":", 2)[1] - } - break - } - } - return -} - -// StoreTemporaryVoucher saves voucher metadata as temporary entries in the DataStore. -func StoreTemporaryVoucher(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { - tempData := fmt.Sprintf("%s,%s,%s,%s", data.TokenSymbol, data.Balance, data.TokenDecimals, data.ContractAddress) - - if err := store.WriteEntry(ctx, sessionId, DATA_TEMPORARY_VALUE, []byte(tempData)); err != nil { - return err - } - - return nil -} - -// GetTemporaryVoucherData retrieves temporary voucher metadata from the DataStore. -func GetTemporaryVoucherData(ctx context.Context, store DataStore, sessionId string) (*dataserviceapi.TokenHoldings, error) { - temp_data, err := store.ReadEntry(ctx, sessionId, DATA_TEMPORARY_VALUE) - if err != nil { - return nil, err - } - - values := strings.SplitN(string(temp_data), ",", 4) - - data := &dataserviceapi.TokenHoldings{} - - data.TokenSymbol = values[0] - data.Balance = values[1] - data.TokenDecimals = values[2] - data.ContractAddress = values[3] - - return data, nil -} - -// UpdateVoucherData updates the active voucher data in the DataStore. -func UpdateVoucherData(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { - logg.TraceCtxf(ctx, "dtal", "data", data) - // Active voucher data entries - activeEntries := map[DataTyp][]byte{ - DATA_ACTIVE_SYM: []byte(data.TokenSymbol), - DATA_ACTIVE_BAL: []byte(data.Balance), - DATA_ACTIVE_DECIMAL: []byte(data.TokenDecimals), - DATA_ACTIVE_ADDRESS: []byte(data.ContractAddress), - } - - // Write active data - for key, value := range activeEntries { - if err := store.WriteEntry(ctx, sessionId, key, value); err != nil { - return err - } - } - - return nil -} diff --git a/common/vouchers_test.go b/common/vouchers_test.go deleted file mode 100644 index 89510ac..0000000 --- a/common/vouchers_test.go +++ /dev/null @@ -1,200 +0,0 @@ -package common - -import ( - "context" - "fmt" - "testing" - - "github.com/alecthomas/assert/v2" - "github.com/stretchr/testify/require" - - visedb "git.defalsify.org/vise.git/db" - memdb "git.defalsify.org/vise.git/db/mem" - dbstorage "git.grassecon.net/grassrootseconomics/visedriver/storage/db" - dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" -) - -// InitializeTestDb sets up and returns an in-memory database and store. -func InitializeTestDb(t *testing.T) (context.Context, *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 - store := &UserDataStore{Db: db} - - t.Cleanup(func() { - db.Close() // Ensure the DB is closed after each test - }) - - return ctx, store -} - -func TestMatchVoucher(t *testing.T) { - symbols := "1:SRF\n2:MILO" - balances := "1:100\n2:200" - decimals := "1:6\n2:4" - addresses := "1:0xd4c288865Ce\n2:0x41c188d63Qa" - - // Test for valid voucher - symbol, balance, decimal, address := MatchVoucher("2", symbols, balances, decimals, addresses) - - // Assertions for valid voucher - assert.Equal(t, "MILO", symbol) - assert.Equal(t, "200", balance) - assert.Equal(t, "4", decimal) - assert.Equal(t, "0x41c188d63Qa", address) - - // Test for non-existent voucher - symbol, balance, decimal, address = MatchVoucher("3", symbols, balances, decimals, addresses) - - // Assertions for non-match - assert.Equal(t, "", symbol) - assert.Equal(t, "", balance) - assert.Equal(t, "", decimal) - assert.Equal(t, "", address) -} - -func TestProcessVouchers(t *testing.T) { - holdings := []dataserviceapi.TokenHoldings{ - {ContractAddress: "0xd4c288865Ce", TokenSymbol: "SRF", TokenDecimals: "6", Balance: "100000000"}, - {ContractAddress: "0x41c188d63Qa", TokenSymbol: "MILO", TokenDecimals: "4", Balance: "200000000"}, - } - - expectedResult := VoucherMetadata{ - Symbols: "1:SRF\n2:MILO", - Balances: "1:100\n2:20000", - Decimals: "1:6\n2:4", - Addresses: "1:0xd4c288865Ce\n2:0x41c188d63Qa", - } - - result := ProcessVouchers(holdings) - - assert.Equal(t, expectedResult, result) -} - -func TestGetVoucherData(t *testing.T) { - ctx := context.Background() - - db := memdb.NewMemDb() - err := db.Connect(ctx, "") - if err != nil { - t.Fatal(err) - } - - prefix := ToBytes(visedb.DATATYPE_USERDATA) - spdb := dbstorage.NewSubPrefixDb(db, prefix) - - // Test voucher data - mockData := map[DataTyp][]byte{ - DATA_VOUCHER_SYMBOLS: []byte("1:SRF\n2:MILO"), - DATA_VOUCHER_BALANCES: []byte("1:100\n2:200"), - DATA_VOUCHER_DECIMALS: []byte("1:6\n2:4"), - DATA_VOUCHER_ADDRESSES: []byte("1:0xd4c288865Ce\n2:0x41c188d63Qa"), - } - - // Put the data - for key, value := range mockData { - err = spdb.Put(ctx, []byte(ToBytes(key)), []byte(value)) - if err != nil { - t.Fatal(err) - } - } - - result, err := GetVoucherData(ctx, spdb, "1") - - assert.NoError(t, err) - assert.Equal(t, "SRF", result.TokenSymbol) - assert.Equal(t, "100", result.Balance) - assert.Equal(t, "6", result.TokenDecimals) - assert.Equal(t, "0xd4c288865Ce", result.ContractAddress) -} - -func TestStoreTemporaryVoucher(t *testing.T) { - ctx, store := InitializeTestDb(t) - sessionId := "session123" - - // Test data - voucherData := &dataserviceapi.TokenHoldings{ - TokenSymbol: "SRF", - Balance: "200", - TokenDecimals: "6", - ContractAddress: "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9", - } - - // Execute the function being tested - err := StoreTemporaryVoucher(ctx, store, sessionId, voucherData) - require.NoError(t, err) - - // Verify stored data - expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "200", "6", "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9") - - storedValue, err := store.ReadEntry(ctx, sessionId, DATA_TEMPORARY_VALUE) - require.NoError(t, err) - require.Equal(t, expectedData, string(storedValue), "Mismatch for key %v", DATA_TEMPORARY_VALUE) -} - -func TestGetTemporaryVoucherData(t *testing.T) { - ctx, store := InitializeTestDb(t) - sessionId := "session123" - - // Test voucher data - tempData := &dataserviceapi.TokenHoldings{ - TokenSymbol: "SRF", - Balance: "200", - TokenDecimals: "6", - ContractAddress: "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9", - } - - // Store the data - err := StoreTemporaryVoucher(ctx, store, sessionId, tempData) - require.NoError(t, err) - - // Execute the function being tested - data, err := GetTemporaryVoucherData(ctx, store, sessionId) - require.NoError(t, err) - require.Equal(t, tempData, data) -} - -func TestUpdateVoucherData(t *testing.T) { - ctx, store := InitializeTestDb(t) - sessionId := "session123" - - // New voucher data - newData := &dataserviceapi.TokenHoldings{ - TokenSymbol: "SRF", - Balance: "200", - TokenDecimals: "6", - ContractAddress: "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9", - } - - // Old temporary data - tempData := &dataserviceapi.TokenHoldings{ - TokenSymbol: "OLD", - Balance: "100", - TokenDecimals: "8", - ContractAddress: "0xold", - } - require.NoError(t, StoreTemporaryVoucher(ctx, store, sessionId, tempData)) - - // Execute update - err := UpdateVoucherData(ctx, store, sessionId, newData) - require.NoError(t, err) - - // Verify active data was stored correctly - activeEntries := map[DataTyp][]byte{ - DATA_ACTIVE_SYM: []byte(newData.TokenSymbol), - DATA_ACTIVE_BAL: []byte(newData.Balance), - DATA_ACTIVE_DECIMAL: []byte(newData.TokenDecimals), - DATA_ACTIVE_ADDRESS: []byte(newData.ContractAddress), - } - - for key, expectedValue := range activeEntries { - storedValue, err := store.ReadEntry(ctx, sessionId, key) - require.NoError(t, err) - require.Equal(t, expectedValue, storedValue, "Active data mismatch for key %v", key) - } -} diff --git a/debug/cap.go b/debug/cap.go deleted file mode 100644 index 458bb48..0000000 --- a/debug/cap.go +++ /dev/null @@ -1,5 +0,0 @@ -package debug - -var ( - DebugCap uint32 -) diff --git a/debug/db.go b/debug/db.go deleted file mode 100644 index 85efd1a..0000000 --- a/debug/db.go +++ /dev/null @@ -1,84 +0,0 @@ -package debug - -import ( - "fmt" - "encoding/binary" - - "git.grassecon.net/grassrootseconomics/visedriver/common" - "git.defalsify.org/vise.git/db" -) - -var ( - dbTypStr map[common.DataTyp]string = make(map[common.DataTyp]string) -) - -type KeyInfo struct { - SessionId string - Typ uint8 - SubTyp common.DataTyp - Label string - Description string -} - -func (k KeyInfo) String() string { - v := uint16(k.SubTyp) - s := subTypToString(k.SubTyp) - if s == "" { - v = uint16(k.Typ) - s = typToString(k.Typ) - } - return fmt.Sprintf("Session Id: %s\nTyp: %s (%d)\n", k.SessionId, s, v) -} - -func ToKeyInfo(k []byte, sessionId string) (KeyInfo, error) { - o := KeyInfo{} - b := []byte(sessionId) - - if len(k) <= len(b) { - return o, fmt.Errorf("storage key missing") - } - - o.SessionId = sessionId - - o.Typ = uint8(k[0]) - k = k[1:] - o.SessionId = string(k[:len(b)]) - k = k[len(b):] - - if o.Typ == db.DATATYPE_USERDATA { - if len(k) == 0 { - return o, fmt.Errorf("missing subtype key") - } - v := binary.BigEndian.Uint16(k[:2]) - o.SubTyp = common.DataTyp(v) - o.Label = subTypToString(o.SubTyp) - k = k[2:] - } else { - o.Label = typToString(o.Typ) - } - - if len(k) != 0 { - return o, fmt.Errorf("excess key information") - } - - return o, nil -} - -func FromKey(k []byte) (KeyInfo, error) { - o := KeyInfo{} - - if len(k) < 4 { - return o, fmt.Errorf("insufficient key length") - } - - sessionIdBytes := k[1:len(k)-2] - return ToKeyInfo(k, string(sessionIdBytes)) -} - -func subTypToString(v common.DataTyp) string { - return dbTypStr[v + db.DATATYPE_USERDATA + 1] -} - -func typToString(v uint8) string { - return dbTypStr[common.DataTyp(uint16(v))] -} diff --git a/debug/db_debug.go b/debug/db_debug.go deleted file mode 100644 index 0ce276e..0000000 --- a/debug/db_debug.go +++ /dev/null @@ -1,44 +0,0 @@ -// +build debugdb - -package debug - -import ( - "git.defalsify.org/vise.git/db" - - "git.grassecon.net/grassrootseconomics/visedriver/common" -) - -func init() { - DebugCap |= 1 - dbTypStr[db.DATATYPE_STATE] = "internal state" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_TRACKING_ID] = "tracking id" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_PUBLIC_KEY] = "public key" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_ACCOUNT_PIN] = "account pin" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_FIRST_NAME] = "first name" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_FAMILY_NAME] = "family name" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_YOB] = "year of birth" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_LOCATION] = "location" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_GENDER] = "gender" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_OFFERINGS] = "offerings" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_RECIPIENT] = "recipient" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_AMOUNT] = "amount" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_TEMPORARY_VALUE] = "temporary value" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_ACTIVE_SYM] = "active sym" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_ACTIVE_BAL] = "active bal" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_BLOCKED_NUMBER] = "blocked number" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_PUBLIC_KEY_REVERSE] = "public_key_reverse" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_ACTIVE_DECIMAL] = "active decimal" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_ACTIVE_ADDRESS] = "active address" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_VOUCHER_SYMBOLS] = "voucher symbols" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_VOUCHER_BALANCES] = "voucher balances" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_VOUCHER_DECIMALS] = "voucher decimals" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_VOUCHER_ADDRESSES] = "voucher addresses" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_TX_SENDERS] = "tx senders" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_TX_RECIPIENTS] = "tx recipients" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_TX_VALUES] = "tx values" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_TX_ADDRESSES] = "tx addresses" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_TX_HASHES] = "tx hashes" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_TX_DATES] = "tx dates" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_TX_SYMBOLS] = "tx symbols" - dbTypStr[db.DATATYPE_USERDATA + 1 + common.DATA_TX_DECIMALS] = "tx decimals" -} diff --git a/debug/db_test.go b/debug/db_test.go deleted file mode 100644 index d55d47c..0000000 --- a/debug/db_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package debug - -import ( - "testing" - - "git.grassecon.net/grassrootseconomics/visedriver/common" - "git.defalsify.org/vise.git/db" -) - -func TestDebugDbSubKeyInfo(t *testing.T) { - s := "foo" - b := []byte{0x20} - b = append(b, []byte(s)...) - b = append(b, []byte{0x00, 0x02}...) - r, err := ToKeyInfo(b, s) - if err != nil { - t.Fatal(err) - } - if r.SessionId != s { - t.Fatalf("expected %s, got %s", s, r.SessionId) - } - if r.Typ != 32 { - t.Fatalf("expected 64, got %d", r.Typ) - } - if r.SubTyp != 2 { - t.Fatalf("expected 2, got %d", r.SubTyp) - } - if DebugCap & 1 > 0 { - if r.Label != "tracking id" { - t.Fatalf("expected 'tracking id', got '%s'", r.Label) - } - } -} - -func TestDebugDbKeyInfo(t *testing.T) { - s := "bar" - b := []byte{0x10} - b = append(b, []byte(s)...) - r, err := ToKeyInfo(b, s) - if err != nil { - t.Fatal(err) - } - if r.SessionId != s { - t.Fatalf("expected %s, got %s", s, r.SessionId) - } - if r.Typ != 16 { - t.Fatalf("expected 16, got %d", r.Typ) - } - if DebugCap & 1 > 0 { - if r.Label != "internal state" { - t.Fatalf("expected 'internal_state', got '%s'", r.Label) - } - } -} - -func TestDebugDbKeyInfoRestore(t *testing.T) { - s := "bar" - b := []byte{db.DATATYPE_USERDATA} - b = append(b, []byte(s)...) - k := common.ToBytes(common.DATA_ACTIVE_SYM) - b = append(b, k...) - - r, err := ToKeyInfo(b, s) - if err != nil { - t.Fatal(err) - } - if r.SessionId != s { - t.Fatalf("expected %s, got %s", s, r.SessionId) - } - if r.Typ != 32 { - t.Fatalf("expected 32, got %d", r.Typ) - } - if DebugCap & 1 > 0 { - if r.Label != "active sym" { - t.Fatalf("expected 'active sym', got '%s'", r.Label) - } - } -} diff --git a/storage/db/sub_prefix_db.go b/storage/db/sub_prefix_db.go deleted file mode 100644 index 457af78..0000000 --- a/storage/db/sub_prefix_db.go +++ /dev/null @@ -1,43 +0,0 @@ -package storage - -import ( - "context" - - "git.defalsify.org/vise.git/db" -) - -// PrefixDb interface abstracts the database operations. -type PrefixDb interface { - Get(ctx context.Context, key []byte) ([]byte, error) - Put(ctx context.Context, key []byte, val []byte) error -} - -var _ PrefixDb = (*SubPrefixDb)(nil) - -type SubPrefixDb struct { - store db.Db - pfx []byte -} - -func NewSubPrefixDb(store db.Db, pfx []byte) *SubPrefixDb { - return &SubPrefixDb{ - store: store, - pfx: pfx, - } -} - -func (s *SubPrefixDb) toKey(k []byte) []byte { - return append(s.pfx, k...) -} - -func (s *SubPrefixDb) Get(ctx context.Context, key []byte) ([]byte, error) { - s.store.SetPrefix(db.DATATYPE_USERDATA) - key = s.toKey(key) - return s.store.Get(ctx, key) -} - -func (s *SubPrefixDb) Put(ctx context.Context, key []byte, val []byte) error { - s.store.SetPrefix(db.DATATYPE_USERDATA) - key = s.toKey(key) - return s.store.Put(ctx, key, val) -} diff --git a/storage/db/sub_prefix_db_test.go b/storage/db/sub_prefix_db_test.go deleted file mode 100644 index 9e2183c..0000000 --- a/storage/db/sub_prefix_db_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package storage - -import ( - "bytes" - "context" - "testing" - - memdb "git.defalsify.org/vise.git/db/mem" -) - -func TestSubPrefix(t *testing.T) { - ctx := context.Background() - db := memdb.NewMemDb() - err := db.Connect(ctx, "") - if err != nil { - t.Fatal(err) - } - sdba := NewSubPrefixDb(db, []byte("tinkywinky")) - err = sdba.Put(ctx, []byte("foo"), []byte("dipsy")) - if err != nil { - t.Fatal(err) - } - - r, err := sdba.Get(ctx, []byte("foo")) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(r, []byte("dipsy")) { - t.Fatalf("expected 'dipsy', got %s", r) - } - - sdbb := NewSubPrefixDb(db, []byte("lala")) - r, err = sdbb.Get(ctx, []byte("foo")) - if err == nil { - t.Fatal("expected not found") - } - - err = sdbb.Put(ctx, []byte("foo"), []byte("pu")) - if err != nil { - t.Fatal(err) - } - r, err = sdbb.Get(ctx, []byte("foo")) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(r, []byte("pu")) { - t.Fatalf("expected 'pu', got %s", r) - } - - r, err = sdba.Get(ctx, []byte("foo")) - if !bytes.Equal(r, []byte("dipsy")) { - t.Fatalf("expected 'dipsy', got %s", r) - } -} diff --git a/utils/age.go b/utils/age.go deleted file mode 100644 index 59056a8..0000000 --- a/utils/age.go +++ /dev/null @@ -1,56 +0,0 @@ -package utils - -import ( - "strconv" - "time" -) - -// CalculateAge calculates the age based on a given birthdate and the current date in the format dd/mm/yy -// It adjusts for cases where the current date is before the birthday in the current year. -func CalculateAge(birthdate, today time.Time) int { - today = today.In(birthdate.Location()) - ty, tm, td := today.Date() - today = time.Date(ty, tm, td, 0, 0, 0, 0, time.UTC) - by, bm, bd := birthdate.Date() - birthdate = time.Date(by, bm, bd, 0, 0, 0, 0, time.UTC) - if today.Before(birthdate) { - return 0 - } - age := ty - by - anniversary := birthdate.AddDate(age, 0, 0) - if anniversary.After(today) { - age-- - } - return age -} - -// CalculateAgeWithYOB calculates the age based on the given year of birth (YOB). -// It subtracts the YOB from the current year to determine the age. -// -// Parameters: -// -// yob: The year of birth as an integer. -// -// Returns: -// -// The calculated age as an integer. -func CalculateAgeWithYOB(yob int) int { - currentYear := time.Now().Year() - return currentYear - yob -} - - -//IsValidYob checks if the provided yob can be considered valid -func IsValidYOb(yob string) bool { - currentYear := time.Now().Year() - yearOfBirth, err := strconv.ParseInt(yob, 10, 64) - if err != nil { - return false - } - if yearOfBirth >= 1900 && int(yearOfBirth) <= currentYear { - return true - } else { - return false - } - -} diff --git a/utils/isocode.go b/utils/isocode.go deleted file mode 100644 index 692b7bb..0000000 --- a/utils/isocode.go +++ /dev/null @@ -1,11 +0,0 @@ -package utils - -var isoCodes = map[string]bool{ - "eng": true, // English - "swa": true, // Swahili - "default": true, // Default language: English -} - -func IsValidISO639(code string) bool { - return isoCodes[code] -} diff --git a/utils/name.go b/utils/name.go deleted file mode 100644 index ea403d5..0000000 --- a/utils/name.go +++ /dev/null @@ -1,17 +0,0 @@ -package utils - -func ConstructName(firstName, familyName, defaultValue string) string { - name := defaultValue - if familyName != defaultValue { - if firstName != defaultValue { - name = firstName + " " + familyName - } else { - name = familyName - } - } else { - if firstName != defaultValue { - name = firstName - } - } - return name -}