diff --git a/.env.example b/.env.example index e6ff1ce..8d11abe 100644 --- a/.env.example +++ b/.env.example @@ -39,7 +39,7 @@ DEFAULT_MPESA_ASSET=cUSD MPESA_BEARER_TOKEN=eyJeSIsInRcCI6IkpXVCJ.yJwdWJsaWNLZXkiOiIwrrrrrr MPESA_ONRAMP_BASE=https://pretium.v1.grassecon.net -# Known stable voucher addresses (USDm, USD₮) -STABLE_VOUCHER_ADDRESSES=0x765DE816845861e75A25fCA122bb6898B8B1282a,0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e +# Known stable voucher addresses (USDm, USD₮, USDC) +STABLE_VOUCHER_ADDRESSES=0x765DE816845861e75A25fCA122bb6898B8B1282a,0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e,0xcebA9300f2b948710d2653dD7B07f33A8B32118C DEFAULT_STABLE_VOUCHER_ADDRESS=0x765DE816845861e75A25fCA122bb6898B8B1282a DEFAULT_STABLE_VOUCHER_DECIMALS=18 diff --git a/handlers/application/mpesa.go b/handlers/application/mpesa.go index cdb5415..7841cf4 100644 --- a/handlers/application/mpesa.go +++ b/handlers/application/mpesa.go @@ -100,11 +100,13 @@ func (h *MenuHandlers) GetMpesaMaxLimit(ctx context.Context, sym string, input [ } // Fetch min withdrawal amount from config/env - minksh := fmt.Sprintf("%f", config.MinMpesaWithdrawAmount()) - minKshFormatted, _ := store.TruncateDecimalString(minksh, 0) + minWithdraw := config.MinMpesaWithdrawAmount() // float64 (20) + minKshFormatted, _ := store.TruncateDecimalString(fmt.Sprintf("%f", minWithdraw), 0) - // If SAT is the same as RAT, return early with KSH format - if string(metadata.TokenAddress) == string(recipientActiveAddress) { + // If SAT is the same as RAT (default USDm), + // or if the voucher is a stable coin + // return early with KSH format + if string(metadata.TokenAddress) == string(recipientActiveAddress) || isStableVoucher(metadata.TokenAddress) { txType = "normal" // Save the transaction type if err := userStore.WriteEntry(ctx, sessionId, storedb.DATA_SEND_TRANSACTION_TYPE, []byte(txType)); err != nil { @@ -113,9 +115,16 @@ func (h *MenuHandlers) GetMpesaMaxLimit(ctx context.Context, sym string, input [ } activeFloat, _ := strconv.ParseFloat(string(metadata.Balance), 64) - ksh := fmt.Sprintf("%f", activeFloat*rates.Buy) + kshValue := activeFloat * rates.Buy - maxKshFormatted, _ := store.TruncateDecimalString(ksh, 0) + maxKshFormatted, _ := store.TruncateDecimalString(fmt.Sprintf("%f", kshValue), 0) + + // Ensure that the max is greater than the min + if kshValue < minWithdraw { + res.FlagSet = append(res.FlagSet, flag_low_swap_amount) + res.Content = l.Get("%s Ksh", maxKshFormatted) + return res, nil + } res.Content = l.Get( "Enter the amount of Mpesa to withdraw: (Min: Ksh %s, Max %s Ksh)\n", diff --git a/handlers/application/pool_deposit.go b/handlers/application/pool_deposit.go index e71fcac..e6c1854 100644 --- a/handlers/application/pool_deposit.go +++ b/handlers/application/pool_deposit.go @@ -206,8 +206,8 @@ func (h *MenuHandlers) InitiatePoolDeposit(ctx context.Context, sym string, inpu return res, err } - // Call pool deposit API - r, err := h.accountService.PoolDeposit(ctx, finalAmountStr, string(publicKey), string(activePoolAddress), poolDepositVoucher.TokenAddress) + // Call token transfer API and send the token to the pool address + r, err := h.accountService.TokenTransfer(ctx, finalAmountStr, string(publicKey), string(activePoolAddress), poolDepositVoucher.TokenAddress) if err != nil { flag_api_call_error, _ := h.flagManager.GetFlag("flag_api_call_error") res.FlagSet = append(res.FlagSet, flag_api_call_error) diff --git a/handlers/application/send.go b/handlers/application/send.go index 86a4e4a..2213296 100644 --- a/handlers/application/send.go +++ b/handlers/application/send.go @@ -380,6 +380,19 @@ func (h *MenuHandlers) MaxAmount(ctx context.Context, sym string, input []byte) return res, err } + // Case for M-Pesa + // if the recipient is Mpesa (address), check if the sender's voucher is a stable coin + recipientAddress, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_RECIPIENT) + if err != nil { + logg.ErrorCtxf(ctx, "Failed to read recipient's address", "error", err) + return res, err + } + if string(recipientAddress) == config.DefaultMpesaAddress() && isStableVoucher(string(activeAddress)) { + res.FlagReset = append(res.FlagReset, flag_swap_transaction) + res.Content = l.Get("Maximum amount: %s %s\nEnter amount:", formattedBalance, string(activeSym)) + return res, nil + } + if string(swapToVoucher.TokenAddress) == string(activeAddress) { // recipient has active token same as selected token → normal transaction transactionType = []byte("normal")