Compare commits

..

No commits in common. "5773305785e9a761a8751965a961bae410961620" and "93df6a6a08d5f6c21ee67c1848a4336a0f318465" have entirely different histories.

8 changed files with 30 additions and 132 deletions

View File

@ -11,7 +11,6 @@ const (
trackStatusPath = "/api/track" trackStatusPath = "/api/track"
balancePathPrefix = "/api/account" balancePathPrefix = "/api/account"
trackPath = "/api/v2/account/status" trackPath = "/api/v2/account/status"
tokenTransferPrefix = "/api/v2/token/transfer"
voucherHoldingsPathPrefix = "/api/v1/holdings" voucherHoldingsPathPrefix = "/api/v1/holdings"
voucherTransfersPathPrefix = "/api/v1/transfers/last10" voucherTransfersPathPrefix = "/api/v1/transfers/last10"
voucherDataPathPrefix = "/api/v1/token" voucherDataPathPrefix = "/api/v1/token"
@ -29,7 +28,6 @@ var (
TrackStatusURL string TrackStatusURL string
BalanceURL string BalanceURL string
TrackURL string TrackURL string
TokenTransferURL string
VoucherHoldingsURL string VoucherHoldingsURL string
VoucherTransfersURL string VoucherTransfersURL string
VoucherDataURL string VoucherDataURL string
@ -64,7 +62,6 @@ func LoadConfig() error {
TrackStatusURL, _ = url.JoinPath(custodialURLBase, trackStatusPath) TrackStatusURL, _ = url.JoinPath(custodialURLBase, trackStatusPath)
BalanceURL, _ = url.JoinPath(custodialURLBase, balancePathPrefix) BalanceURL, _ = url.JoinPath(custodialURLBase, balancePathPrefix)
TrackURL, _ = url.JoinPath(custodialURLBase, trackPath) TrackURL, _ = url.JoinPath(custodialURLBase, trackPath)
TokenTransferURL, _ = url.JoinPath(custodialURLBase, tokenTransferPrefix)
VoucherHoldingsURL, _ = url.JoinPath(dataURLBase, voucherHoldingsPathPrefix) VoucherHoldingsURL, _ = url.JoinPath(dataURLBase, voucherHoldingsPathPrefix)
VoucherTransfersURL, _ = url.JoinPath(dataURLBase, voucherTransfersPathPrefix) VoucherTransfersURL, _ = url.JoinPath(dataURLBase, voucherTransfersPathPrefix)
VoucherDataURL, _ = url.JoinPath(dataURLBase, voucherDataPathPrefix) VoucherDataURL, _ = url.JoinPath(dataURLBase, voucherDataPathPrefix)

View File

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"math/big"
"path" "path"
"regexp" "regexp"
"strconv" "strconv"
@ -703,7 +702,7 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b
r, err := h.accountService.TrackAccountStatus(ctx, string(publicKey)) r, err := h.accountService.TrackAccountStatus(ctx, string(publicKey))
if err != nil { if err != nil {
res.FlagSet = append(res.FlagSet, flag_api_error) res.FlagSet = append(res.FlagSet, flag_api_error)
logg.ErrorCtxf(ctx, "failed on TrackAccountStatus", "error", err) logg.ErrorCtxf(ctx, "failed on TrackAccountStatus", err)
return res, err return res, err
} }
@ -930,7 +929,6 @@ func (h *Handlers) ValidateBlockedNumber(ctx context.Context, sym string, input
// ValidateRecipient validates that the given input is a valid phone number. // ValidateRecipient validates that the given input is a valid phone number.
func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
var err error
store := h.userdataStore store := h.userdataStore
sessionId, ok := ctx.Value("SessionId").(string) sessionId, ok := ctx.Value("SessionId").(string)
@ -951,18 +949,18 @@ func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []by
return res, nil return res, nil
} }
// save the recipient as the temporaryRecipient
err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(recipient))
if err != nil {
logg.ErrorCtxf(ctx, "failed to write temporaryRecipient entry with", "key", common.DATA_TEMPORARY_VALUE, "value", recipient, "error", err)
return res, err
}
publicKey, err := store.ReadEntry(ctx, recipient, common.DATA_PUBLIC_KEY) publicKey, err := store.ReadEntry(ctx, recipient, common.DATA_PUBLIC_KEY)
if err != nil { if err != nil {
if db.IsNotFound(err) { if db.IsNotFound(err) {
logg.InfoCtxf(ctx, "Unregistered number") logg.InfoCtxf(ctx, "Unregistered number")
// save the recipient as the temporaryInvitedNumber
err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(recipient))
if err != nil {
logg.ErrorCtxf(ctx, "failed to write temporaryInvitedNumber entry with", "key", common.DATA_TEMPORARY_VALUE, "value", recipient, "error", err)
return res, err
}
res.FlagSet = append(res.FlagSet, flag_invalid_recipient_with_invite) res.FlagSet = append(res.FlagSet, flag_invalid_recipient_with_invite)
res.Content = recipient res.Content = recipient
@ -1135,7 +1133,7 @@ func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte)
return res, nil return res, nil
} }
// GetRecipient returns the transaction recipient phone number from the gdbm. // GetRecipient returns the transaction recipient from the gdbm.
func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
@ -1144,7 +1142,7 @@ func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) (
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
store := h.userdataStore store := h.userdataStore
recipient, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) recipient, _ := store.ReadEntry(ctx, sessionId, common.DATA_RECIPIENT)
res.Content = string(recipient) res.Content = string(recipient)
@ -1215,56 +1213,27 @@ func (h *Handlers) InitiateTransaction(ctx context.Context, sym string, input []
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error")
account_authorized_flag, _ := h.flagManager.GetFlag("flag_account_authorized")
code := codeFromCtx(ctx) code := codeFromCtx(ctx)
l := gotext.NewLocale(translationDir, code) l := gotext.NewLocale(translationDir, code)
l.AddDomain("default") l.AddDomain("default")
// TODO
// Use the amount, recipient and sender to call the API and initialize the transaction
store := h.userdataStore store := h.userdataStore
recipientNumber, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE)
amount, _ := store.ReadEntry(ctx, sessionId, common.DATA_AMOUNT)
recipient, _ := store.ReadEntry(ctx, sessionId, common.DATA_RECIPIENT)
activeSym, _ := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_SYM) activeSym, _ := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_SYM)
storedAmount, _ := store.ReadEntry(ctx, sessionId, common.DATA_AMOUNT) res.Content = l.Get("Your request has been sent. %s will receive %s %s from %s.", string(recipient), string(amount), string(activeSym), string(sessionId))
fromAddress, _ := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY)
toAddress, _ := store.ReadEntry(ctx, sessionId, common.DATA_RECIPIENT)
activeDecimal, _ := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_DECIMAL)
tokenAddress, _ := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_ADDRESS)
// Parse tokendecimal account_authorized_flag, err := h.flagManager.GetFlag("flag_account_authorized")
tokenDecimal, err := strconv.Atoi(string(activeDecimal))
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "Failed to set the flag_account_authorized", "error", err)
return res, err return res, err
} }
// Parse amount and scale it
amount, _, err := big.ParseFloat(string(storedAmount), 10, 0, big.ToZero)
if err != nil {
return res, err
}
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)
// Call TokenTransfer
r, err := h.accountService.TokenTransfer(ctx, finalAmountStr.String(), string(fromAddress), string(toAddress), string(tokenAddress))
if err != nil {
res.Content = l.Get("Your request failed. Please try again later.")
res.FlagSet = append(res.FlagSet, flag_api_error)
logg.ErrorCtxf(ctx, "failed on TokenTransfer", "error", err)
return res, err
}
trackingId := r.TrackingId
logg.InfoCtxf(ctx, "TokenTransfer", "trackingId", trackingId)
res.Content = l.Get("Your request has been sent. %s will receive %s %s from %s.", string(recipientNumber), string(storedAmount), string(activeSym), string(sessionId))
res.FlagReset = append(res.FlagReset, account_authorized_flag) res.FlagReset = append(res.FlagReset, account_authorized_flag)
return res, nil return res, nil
} }
@ -1480,8 +1449,6 @@ func (h *Handlers) SetDefaultVoucher(ctx context.Context, sym string, input []by
firstVoucher := vouchersResp[0] firstVoucher := vouchersResp[0]
defaultSym := firstVoucher.TokenSymbol defaultSym := firstVoucher.TokenSymbol
defaultBal := firstVoucher.Balance defaultBal := firstVoucher.Balance
defaultDec := firstVoucher.TokenDecimals
defaultAddr := firstVoucher.ContractAddress
// set the active symbol // set the active symbol
err = store.WriteEntry(ctx, sessionId, common.DATA_ACTIVE_SYM, []byte(defaultSym)) err = store.WriteEntry(ctx, sessionId, common.DATA_ACTIVE_SYM, []byte(defaultSym))
@ -1495,18 +1462,6 @@ func (h *Handlers) SetDefaultVoucher(ctx context.Context, sym string, input []by
logg.ErrorCtxf(ctx, "failed to write defaultBal entry with", "key", common.DATA_ACTIVE_BAL, "value", defaultBal, "error", err) logg.ErrorCtxf(ctx, "failed to write defaultBal entry with", "key", common.DATA_ACTIVE_BAL, "value", defaultBal, "error", err)
return res, err return res, err
} }
// set the active decimals
err = store.WriteEntry(ctx, sessionId, common.DATA_ACTIVE_DECIMAL, []byte(defaultDec))
if err != nil {
logg.ErrorCtxf(ctx, "failed to write defaultDec entry with", "key", common.DATA_ACTIVE_DECIMAL, "value", defaultDec, "error", err)
return res, err
}
// set the active contract address
err = store.WriteEntry(ctx, sessionId, common.DATA_ACTIVE_ADDRESS, []byte(defaultAddr))
if err != nil {
logg.ErrorCtxf(ctx, "failed to write defaultAddr entry with", "key", common.DATA_ACTIVE_ADDRESS, "value", defaultAddr, "error", err)
return res, err
}
return res, nil return res, nil
} }

View File

@ -28,6 +28,7 @@ func (m *MockAccountService) TrackAccountStatus(ctx context.Context, trackingId
return args.Get(0).(*models.TrackStatusResult), args.Error(1) return args.Get(0).(*models.TrackStatusResult), args.Error(1)
} }
func (m *MockAccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { func (m *MockAccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) {
args := m.Called(publicKey) args := m.Called(publicKey)
return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1)
@ -38,12 +39,7 @@ func (m *MockAccountService) FetchTransactions(ctx context.Context, publicKey st
return args.Get(0).([]dataserviceapi.Last10TxResponse), args.Error(1) return args.Get(0).([]dataserviceapi.Last10TxResponse), args.Error(1)
} }
func (m *MockAccountService) VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) { func(m MockAccountService) VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) {
args := m.Called(address) args := m.Called(address)
return args.Get(0).(*models.VoucherDataResult), args.Error(1) return args.Get(0).(*models.VoucherDataResult), args.Error(1)
} }
func (m *MockAccountService) TokenTransfer(ctx context.Context, amount, from, to, tokenAddress string) (*models.TokenTransferResponse, error) {
args := m.Called()
return args.Get(0).(*models.TokenTransferResponse), args.Error(1)
}

View File

@ -50,9 +50,3 @@ func (tas *TestAccountService) FetchTransactions(ctx context.Context, publicKey
func(m TestAccountService) VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) { func(m TestAccountService) VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) {
return &models.VoucherDataResult{}, nil return &models.VoucherDataResult{}, nil
} }
func (tas *TestAccountService) TokenTransfer(ctx context.Context, amount, from, to, tokenAddress string) (*models.TokenTransferResponse, error) {
return &models.TokenTransferResponse{
TrackingId: "e034d147-747d-42ea-928d-b5a7cb3426af",
}, nil
}

View File

@ -1,5 +0,0 @@
package models
type TokenTransferResponse struct {
TrackingId string `json:"trackingId"`
}

View File

@ -23,7 +23,6 @@ type AccountServiceInterface interface {
FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error)
FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error)
VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error)
TokenTransfer(ctx context.Context, amount, from, to, tokenAddress string) (*models.TokenTransferResponse, error)
} }
type AccountService struct { type AccountService struct {
@ -168,41 +167,6 @@ func (as *AccountService) VoucherData(ctx context.Context, address string) (*mod
return &voucherDataResult, err return &voucherDataResult, err
} }
// TokenTransfer creates a new token transfer in the custodial system.
// Returns:
// - *models.TokenTransferResponse: A pointer to an TokenTransferResponse struct containing the trackingId.
// If there is an error during the request or processing, this will be nil.
// - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data.
// If no error occurs, this will be nil.
func (as *AccountService) TokenTransfer(ctx context.Context, amount, from, to, tokenAddress string) (*models.TokenTransferResponse, error) {
var r models.TokenTransferResponse
// Create request payload
payload := map[string]string{
"amount": amount,
"from": from,
"to": to,
"tokenAddress": tokenAddress,
}
payloadBytes, err := json.Marshal(payload)
if err != nil {
return nil, err
}
// Create a new request
req, err := http.NewRequest("POST", config.TokenTransferURL, bytes.NewBuffer(payloadBytes))
if err != nil {
return nil, err
}
_, err = doCustodialRequest(ctx, req, &r)
if err != nil {
return nil, err
}
return &r, nil
}
func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) {
var okResponse api.OKResponse var okResponse api.OKResponse
var errResponse api.ErrResponse var errResponse api.ErrResponse

View File

@ -9,7 +9,7 @@ RELOAD validate_amount
CATCH api_failure flag_api_call_error 1 CATCH api_failure flag_api_call_error 1
CATCH invalid_amount flag_invalid_amount 1 CATCH invalid_amount flag_invalid_amount 1
INCMP _ 0 INCMP _ 0
LOAD get_recipient 0 LOAD get_recipient 12
LOAD get_sender 64 LOAD get_sender 64
LOAD get_amount 32 LOAD get_amount 32
INCMP transaction_pin * INCMP transaction_pin *

View File

@ -18,6 +18,3 @@ msgstr "Ombi lako la kumwalika %s kwa matandao wa Sarafu halikufaulu. Tafadhali
msgid "Your invitation to %s to join Sarafu Network has been sent." msgid "Your invitation to %s to join Sarafu Network has been sent."
msgstr "Ombi lako la kumwalika %s kwa matandao wa Sarafu limetumwa." msgstr "Ombi lako la kumwalika %s kwa matandao wa Sarafu limetumwa."
msgid "Your request failed. Please try again later."
msgstr "Ombi lako halikufaulu. Tafadhali jaribu tena baadaye."