diff --git a/handlers/application/pool_deposit.go b/handlers/application/pool_deposit.go new file mode 100644 index 0000000..bcc84c1 --- /dev/null +++ b/handlers/application/pool_deposit.go @@ -0,0 +1,220 @@ +package application + +import ( + "context" + "fmt" + "strconv" + "strings" + + "git.defalsify.org/vise.git/resource" + "git.grassecon.net/grassrootseconomics/sarafu-vise/store" + storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" + "gopkg.in/leonelquinteros/gotext.v1" +) + +// GetPoolDepositVouchers returns a list of stable coins +func (h *MenuHandlers) GetPoolDepositVouchers(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") + } + + code := codeFromCtx(ctx) + l := gotext.NewLocale(translationDir, code) + l.AddDomain("default") + + userStore := h.userdataStore + + // Read stable vouchers from the store + voucherData, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_STABLE_VOUCHER_SYMBOLS) + if err != nil { + logg.ErrorCtxf(ctx, "failed to read stable voucherData entires with", "key", storedb.DATA_STABLE_VOUCHER_SYMBOLS, "error", err) + return res, err + } + + if len(voucherData) == 0 { + return res, nil + } + + voucherBalances, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_STABLE_VOUCHER_BALANCES) + if err != nil { + logg.ErrorCtxf(ctx, "failed to read stable voucherData entires with", "key", storedb.DATA_STABLE_VOUCHER_BALANCES, "error", err) + return res, err + } + + formattedVoucherList := store.FormatVoucherList(ctx, string(voucherData), string(voucherBalances)) + finalOutput := strings.Join(formattedVoucherList, "\n") + + res.Content = l.Get("Select number or symbol from your vouchers:\n%s", finalOutput) + + return res, nil +} + +// PoolDepositMaxAmount returns the balance of the selected voucher +func (h *MenuHandlers) PoolDepositMaxAmount(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") + } + + code := codeFromCtx(ctx) + l := gotext.NewLocale(translationDir, code) + l.AddDomain("default") + + flag_incorrect_voucher, _ := h.flagManager.GetFlag("flag_incorrect_voucher") + + res.FlagReset = append(res.FlagReset, flag_incorrect_voucher) + + inputStr := string(input) + if inputStr == "0" || inputStr == "99" || inputStr == "88" || inputStr == "98" { + return res, nil + } + + userStore := h.userdataStore + metadata, err := store.GetStableVoucherData(ctx, userStore, sessionId, inputStr) + if err != nil { + return res, fmt.Errorf("failed to retrieve swap to voucher data: %v", err) + } + if metadata == nil { + res.FlagSet = append(res.FlagSet, flag_incorrect_voucher) + return res, nil + } + + // Store the pool deposit voucher data + if err := store.StoreTemporaryVoucher(ctx, h.userdataStore, sessionId, metadata); err != nil { + logg.ErrorCtxf(ctx, "failed on StoreTemporaryVoucher", "error", err) + return res, err + } + + // Format the balance amount to 2 decimal places + formattedBalance, _ := store.TruncateDecimalString(string(metadata.Balance), 2) + + res.Content = l.Get("Maximum amount: %s %s\nEnter amount:", formattedBalance, metadata.TokenSymbol) + + return res, nil +} + +// ConfirmPoolDeposit displays the pool deposit preview for a PIN confirmation +func (h *MenuHandlers) ConfirmPoolDeposit(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") + } + + inputStr := string(input) + if inputStr == "0" { + return res, nil + } + + flag_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount") + + res.FlagReset = append(res.FlagReset, flag_invalid_amount) + + code := codeFromCtx(ctx) + l := gotext.NewLocale(translationDir, code) + l.AddDomain("default") + + userStore := h.userdataStore + + poolDepositVoucher, err := store.GetTemporaryVoucherData(ctx, h.userdataStore, sessionId) + if err != nil { + logg.ErrorCtxf(ctx, "failed on GetTemporaryVoucherData", "error", err) + return res, err + } + + maxValue, err := strconv.ParseFloat(poolDepositVoucher.Balance, 64) + if err != nil { + logg.ErrorCtxf(ctx, "Failed to convert the swapMaxAmount to a float", "error", err) + return res, err + } + + inputAmount, err := strconv.ParseFloat(inputStr, 64) + if err != nil || inputAmount > maxValue || inputAmount < 0.1 { + res.FlagSet = append(res.FlagSet, flag_invalid_amount) + res.Content = inputStr + return res, nil + } + + err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_AMOUNT, []byte(inputStr)) + if err != nil { + logg.ErrorCtxf(ctx, "failed to write pool deposit amount entry with", "key", storedb.DATA_AMOUNT, "value", inputStr, "error", err) + return res, err + } + + // Resolve active pool + _, activePoolName, err := h.resolveActivePoolDetails(ctx, sessionId) + if err != nil { + return res, err + } + + res.Content = l.Get( + "You will deposit %s %s into %s\n", + inputStr, poolDepositVoucher.TokenSymbol, activePoolName, + ) + + return res, nil +} + +// InitiatePoolDeposit calls the pool deposit API +func (h *MenuHandlers) InitiatePoolDeposit(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + var err error + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + + flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized") + + code := codeFromCtx(ctx) + l := gotext.NewLocale(translationDir, code) + l.AddDomain("default") + + // Resolve active pool + activePoolAddress, activePoolName, err := h.resolveActivePoolDetails(ctx, sessionId) + if err != nil { + return res, err + } + + poolDepositVoucher, err := store.GetTemporaryVoucherData(ctx, h.userdataStore, sessionId) + if err != nil { + logg.ErrorCtxf(ctx, "failed on GetTemporaryVoucherData", "error", err) + return res, err + } + + poolDepositdata, err := store.ReadTransactionData(ctx, h.userdataStore, sessionId) + if err != nil { + return res, err + } + + finalAmountStr, err := store.ParseAndScaleAmount(poolDepositdata.Amount, poolDepositVoucher.TokenDecimals) + if err != nil { + return res, err + } + + // Call pool deposit API + r, err := h.accountService.PoolDeposit(ctx, finalAmountStr, poolDepositdata.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) + res.Content = l.Get("Your request failed. Please try again later.") + logg.ErrorCtxf(ctx, "failed on pool deposit", "error", err) + return res, nil + } + + trackingId := r.TrackingId + logg.InfoCtxf(ctx, "Pool deposit", "trackingId", trackingId) + + res.Content = l.Get( + "Your request has been sent. You will receive an SMS when %s %s has been deposited into %s.", + poolDepositdata.Amount, + poolDepositVoucher.TokenSymbol, + activePoolName, + ) + + res.FlagReset = append(res.FlagReset, flag_account_authorized) + return res, nil +}