project-tidyup - menuhandler and tests #90
| @ -22,7 +22,6 @@ import ( | ||||
| 	commonlang "git.grassecon.net/grassrootseconomics/common/lang" | ||||
| 	"git.grassecon.net/grassrootseconomics/common/pin" | ||||
| 	"git.grassecon.net/grassrootseconomics/sarafu-api/remote" | ||||
| 	"git.grassecon.net/grassrootseconomics/sarafu-vise/config" | ||||
| 	"git.grassecon.net/grassrootseconomics/sarafu-vise/internal/sms" | ||||
| 	"git.grassecon.net/grassrootseconomics/sarafu-vise/profile" | ||||
| 	"git.grassecon.net/grassrootseconomics/sarafu-vise/store" | ||||
| @ -558,780 +557,6 @@ func (h *MenuHandlers) FetchCommunityBalance(ctx context.Context, sym string, in | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // ValidateRecipient validates that the given input is valid.
 | ||||
| //
 | ||||
| // TODO: split up functino
 | ||||
| func (h *MenuHandlers) ValidateRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) { | ||||
| 	var res resource.Result | ||||
| 	var AliasAddressResult string | ||||
| 	var AliasAddress *models.AliasAddress | ||||
| 	store := h.userdataStore | ||||
| 
 | ||||
| 	sessionId, ok := ctx.Value("SessionId").(string) | ||||
| 	if !ok { | ||||
| 		return res, fmt.Errorf("missing session") | ||||
| 	} | ||||
| 	flag_invalid_recipient, _ := h.flagManager.GetFlag("flag_invalid_recipient") | ||||
| 	flag_invalid_recipient_with_invite, _ := h.flagManager.GetFlag("flag_invalid_recipient_with_invite") | ||||
| 	flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") | ||||
| 
 | ||||
| 	// remove white spaces
 | ||||
| 	recipient := strings.ReplaceAll(string(input), " ", "") | ||||
| 
 | ||||
| 	if recipient != "0" { | ||||
| 		recipientType, err := identity.CheckRecipient(recipient) | ||||
| 		if err != nil { | ||||
| 			// Invalid recipient format (not a phone number, address, or valid alias format)
 | ||||
| 			res.FlagSet = append(res.FlagSet, flag_invalid_recipient) | ||||
| 			res.Content = recipient | ||||
| 
 | ||||
| 			return res, nil | ||||
| 		} | ||||
| 
 | ||||
| 		// save the recipient as the temporaryRecipient
 | ||||
| 		err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(recipient)) | ||||
| 		if err != nil { | ||||
| 			logg.ErrorCtxf(ctx, "failed to write temporaryRecipient entry with", "key", storedb.DATA_TEMPORARY_VALUE, "value", recipient, "error", err) | ||||
| 			return res, err | ||||
| 		} | ||||
| 
 | ||||
| 		switch recipientType { | ||||
| 		case "phone number": | ||||
| 			// format the phone number
 | ||||
| 			formattedNumber, err := phone.FormatPhoneNumber(recipient) | ||||
| 			if err != nil { | ||||
| 				logg.ErrorCtxf(ctx, "Failed to format the phone number: %s", recipient, "error", err) | ||||
| 				return res, err | ||||
| 			} | ||||
| 
 | ||||
| 			// Check if the phone number is registered
 | ||||
| 			publicKey, err := store.ReadEntry(ctx, formattedNumber, storedb.DATA_PUBLIC_KEY) | ||||
| 			if err != nil { | ||||
| 				if db.IsNotFound(err) { | ||||
| 					logg.InfoCtxf(ctx, "Unregistered phone number: %s", recipient) | ||||
| 					res.FlagSet = append(res.FlagSet, flag_invalid_recipient_with_invite) | ||||
| 					res.Content = recipient | ||||
| 					return res, nil | ||||
| 				} | ||||
| 
 | ||||
| 				logg.ErrorCtxf(ctx, "failed to read publicKey entry with", "key", storedb.DATA_PUBLIC_KEY, "error", err) | ||||
| 				return res, err | ||||
| 			} | ||||
| 
 | ||||
| 			// Save the publicKey as the recipient
 | ||||
| 			err = store.WriteEntry(ctx, sessionId, storedb.DATA_RECIPIENT, publicKey) | ||||
| 			if err != nil { | ||||
| 				logg.ErrorCtxf(ctx, "failed to write recipient entry with", "key", storedb.DATA_RECIPIENT, "value", string(publicKey), "error", err) | ||||
| 				return res, err | ||||
| 			} | ||||
| 
 | ||||
| 		case "address": | ||||
| 			// checksum the address
 | ||||
| 			address := ethutils.ChecksumAddress(recipient) | ||||
| 
 | ||||
| 			// Save the valid Ethereum address as the recipient
 | ||||
| 			err = store.WriteEntry(ctx, sessionId, storedb.DATA_RECIPIENT, []byte(address)) | ||||
| 			if err != nil { | ||||
| 				logg.ErrorCtxf(ctx, "failed to write recipient entry with", "key", storedb.DATA_RECIPIENT, "value", recipient, "error", err) | ||||
| 				return res, err | ||||
| 			} | ||||
| 
 | ||||
| 		case "alias": | ||||
| 			if strings.Contains(recipient, ".") { | ||||
| 				AliasAddress, err = h.accountService.CheckAliasAddress(ctx, recipient) | ||||
| 				if err == nil { | ||||
| 					AliasAddressResult = AliasAddress.Address | ||||
| 				} else { | ||||
| 					logg.ErrorCtxf(ctx, "failed to resolve alias", "alias", recipient, "error_alias_check", err) | ||||
| 				} | ||||
| 			} else { | ||||
| 				//Perform a search for each search domain,break on first match
 | ||||
| 				for _, domain := range config.SearchDomains() { | ||||
| 					fqdn := fmt.Sprintf("%s.%s", recipient, domain) | ||||
| 					logg.InfoCtxf(ctx, "Resolving with fqdn alias", "alias", fqdn) | ||||
| 					AliasAddress, err = h.accountService.CheckAliasAddress(ctx, fqdn) | ||||
| 					if err == nil { | ||||
| 						res.FlagReset = append(res.FlagReset, flag_api_error) | ||||
| 						AliasAddressResult = AliasAddress.Address | ||||
| 						continue | ||||
| 					} else { | ||||
| 						res.FlagSet = append(res.FlagSet, flag_api_error) | ||||
| 						logg.ErrorCtxf(ctx, "failed to resolve alias", "alias", recipient, "error_alias_check", err) | ||||
| 						return res, nil | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if AliasAddressResult == "" { | ||||
| 				res.Content = recipient | ||||
| 				res.FlagSet = append(res.FlagSet, flag_invalid_recipient) | ||||
| 				return res, nil | ||||
| 			} else { | ||||
| 				err = store.WriteEntry(ctx, sessionId, storedb.DATA_RECIPIENT, []byte(AliasAddressResult)) | ||||
| 				if err != nil { | ||||
| 					logg.ErrorCtxf(ctx, "failed to write recipient entry with", "key", storedb.DATA_RECIPIENT, "value", AliasAddressResult, "error", err) | ||||
| 					return res, err | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // TransactionReset resets the previous transaction data (Recipient and Amount)
 | ||||
| // as well as the invalid flags.
 | ||||
| func (h *MenuHandlers) TransactionReset(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_invalid_recipient, _ := h.flagManager.GetFlag("flag_invalid_recipient") | ||||
| 	flag_invalid_recipient_with_invite, _ := h.flagManager.GetFlag("flag_invalid_recipient_with_invite") | ||||
| 	store := h.userdataStore | ||||
| 	err = store.WriteEntry(ctx, sessionId, storedb.DATA_AMOUNT, []byte("")) | ||||
| 	if err != nil { | ||||
| 		return res, nil | ||||
| 	} | ||||
| 
 | ||||
| 	err = store.WriteEntry(ctx, sessionId, storedb.DATA_RECIPIENT, []byte("")) | ||||
| 	if err != nil { | ||||
| 		return res, nil | ||||
| 	} | ||||
| 
 | ||||
| 	res.FlagReset = append(res.FlagReset, flag_invalid_recipient, flag_invalid_recipient_with_invite) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // InviteValidRecipient sends an invitation to the valid phone number.
 | ||||
| func (h *MenuHandlers) InviteValidRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) { | ||||
| 	var res resource.Result | ||||
| 	store := h.userdataStore | ||||
| 	smsservice := h.smsService | ||||
| 
 | ||||
| 	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") | ||||
| 
 | ||||
| 	recipient, err := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "Failed to read invalid recipient info", "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	if !phone.IsValidPhoneNumber(string(recipient)) { | ||||
| 		logg.InfoCtxf(ctx, "corrupted recipient", "key", storedb.DATA_TEMPORARY_VALUE, "recipient", recipient) | ||||
| 		return res, nil | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = smsservice.Accountservice.SendUpsellSMS(ctx, sessionId, string(recipient)) | ||||
| 	if err != nil { | ||||
| 		res.Content = l.Get("Your invite request for %s to Sarafu Network failed. Please try again later.", string(recipient)) | ||||
| 		return res, nil | ||||
| 	} | ||||
| 	res.Content = l.Get("Your invitation to %s to join Sarafu Network has been sent.", string(recipient)) | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // ResetTransactionAmount resets the transaction amount and invalid flag.
 | ||||
| func (h *MenuHandlers) ResetTransactionAmount(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_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount") | ||||
| 	store := h.userdataStore | ||||
| 	err = store.WriteEntry(ctx, sessionId, storedb.DATA_AMOUNT, []byte("")) | ||||
| 	if err != nil { | ||||
| 		return res, nil | ||||
| 	} | ||||
| 
 | ||||
| 	res.FlagReset = append(res.FlagReset, flag_invalid_amount) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // MaxAmount gets the current balance from the API and sets it as
 | ||||
| // the result content.
 | ||||
| func (h *MenuHandlers) MaxAmount(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") | ||||
| 	} | ||||
| 	store := h.userdataStore | ||||
| 
 | ||||
| 	activeBal, err := store.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_BAL) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed to read activeBal entry with", "key", storedb.DATA_ACTIVE_BAL, "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	res.Content = string(activeBal) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // ValidateAmount ensures that the given input is a valid amount and that
 | ||||
| // it is not more than the current balance.
 | ||||
| func (h *MenuHandlers) ValidateAmount(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") | ||||
| 	} | ||||
| 	flag_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount") | ||||
| 	userStore := h.userdataStore | ||||
| 
 | ||||
| 	var balanceValue float64 | ||||
| 
 | ||||
| 	// retrieve the active balance
 | ||||
| 	activeBal, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_BAL) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed to read activeBal entry with", "key", storedb.DATA_ACTIVE_BAL, "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 	balanceValue, err = strconv.ParseFloat(string(activeBal), 64) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "Failed to convert the activeBal to a float", "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Extract numeric part from the input amount
 | ||||
| 	amountStr := strings.TrimSpace(string(input)) | ||||
| 	inputAmount, err := strconv.ParseFloat(amountStr, 64) | ||||
| 	if err != nil { | ||||
| 		res.FlagSet = append(res.FlagSet, flag_invalid_amount) | ||||
| 		res.Content = amountStr | ||||
| 		return res, nil | ||||
| 	} | ||||
| 
 | ||||
| 	if inputAmount > balanceValue { | ||||
| 		res.FlagSet = append(res.FlagSet, flag_invalid_amount) | ||||
| 		res.Content = amountStr | ||||
| 		return res, nil | ||||
| 	} | ||||
| 
 | ||||
| 	// Format the amount to 2 decimal places before saving (truncated)
 | ||||
| 	formattedAmount, err := store.TruncateDecimalString(amountStr, 2) | ||||
| 	if err != nil { | ||||
| 		res.FlagSet = append(res.FlagSet, flag_invalid_amount) | ||||
| 		res.Content = amountStr | ||||
| 		return res, nil | ||||
| 	} | ||||
| 
 | ||||
| 	err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_AMOUNT, []byte(formattedAmount)) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed to write amount entry with", "key", storedb.DATA_AMOUNT, "value", formattedAmount, "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	res.Content = formattedAmount | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // GetRecipient returns the transaction recipient phone number from the gdbm.
 | ||||
| func (h *MenuHandlers) GetRecipient(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 | ||||
| 	recipient, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) | ||||
| 	if len(recipient) == 0 { | ||||
| 		logg.ErrorCtxf(ctx, "recipient is empty", "key", storedb.DATA_TEMPORARY_VALUE) | ||||
| 		return res, fmt.Errorf("Data error encountered") | ||||
| 	} | ||||
| 
 | ||||
| 	res.Content = string(recipient) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // RetrieveBlockedNumber gets the current number during the pin reset for other's is in progress.
 | ||||
| func (h *MenuHandlers) RetrieveBlockedNumber(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 | ||||
| 	blockedNumber, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_BLOCKED_NUMBER) | ||||
| 
 | ||||
| 	res.Content = string(blockedNumber) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // GetSender returns the sessionId (phoneNumber).
 | ||||
| func (h *MenuHandlers) GetSender(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") | ||||
| 	} | ||||
| 
 | ||||
| 	res.Content = sessionId | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // GetAmount retrieves the amount from teh Gdbm Db.
 | ||||
| func (h *MenuHandlers) GetAmount(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 | ||||
| 
 | ||||
| 	// retrieve the active symbol
 | ||||
| 	activeSym, err := store.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_SYM) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed to read activeSym entry with", "key", storedb.DATA_ACTIVE_SYM, "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	amount, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_AMOUNT) | ||||
| 
 | ||||
| 	res.Content = fmt.Sprintf("%s %s", string(amount), string(activeSym)) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // InitiateTransaction calls the TokenTransfer and returns a confirmation based on the result.
 | ||||
| func (h *MenuHandlers) InitiateTransaction(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") | ||||
| 
 | ||||
| 	data, err := store.ReadTransactionData(ctx, h.userdataStore, sessionId) | ||||
| 	if err != nil { | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	finalAmountStr, err := store.ParseAndScaleAmount(data.Amount, data.ActiveDecimal) | ||||
| 	if err != nil { | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Call TokenTransfer
 | ||||
| 	r, err := h.accountService.TokenTransfer(ctx, finalAmountStr, data.PublicKey, data.Recipient, data.ActiveAddress) | ||||
| 	if err != nil { | ||||
| 		flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") | ||||
| 		res.FlagSet = append(res.FlagSet, flag_api_error) | ||||
| 		res.Content = l.Get("Your request failed. Please try again later.") | ||||
| 		logg.ErrorCtxf(ctx, "failed on TokenTransfer", "error", err) | ||||
| 		return res, nil | ||||
| 	} | ||||
| 
 | ||||
| 	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.", | ||||
| 		data.TemporaryValue, | ||||
| 		data.Amount, | ||||
| 		data.ActiveSym, | ||||
| 		sessionId, | ||||
| 	) | ||||
| 
 | ||||
| 	res.FlagReset = append(res.FlagReset, flag_account_authorized) | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // ManageVouchers retrieves the token holdings from the API using the "PublicKey" and
 | ||||
| // 1. sets the first as the default voucher if no active voucher is set.
 | ||||
| // 2. Stores list of vouchers
 | ||||
| // 3. updates the balance of the active voucher
 | ||||
| func (h *MenuHandlers) ManageVouchers(ctx context.Context, sym string, input []byte) (resource.Result, error) { | ||||
| 	var res resource.Result | ||||
| 	userStore := h.userdataStore | ||||
| 	logdb := h.logDb | ||||
| 
 | ||||
| 	sessionId, ok := ctx.Value("SessionId").(string) | ||||
| 	if !ok { | ||||
| 		return res, fmt.Errorf("missing session") | ||||
| 	} | ||||
| 
 | ||||
| 	flag_no_active_voucher, _ := h.flagManager.GetFlag("flag_no_active_voucher") | ||||
| 	flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") | ||||
| 
 | ||||
| 	publicKey, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed to read publicKey entry", "key", storedb.DATA_PUBLIC_KEY, "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Fetch vouchers from API
 | ||||
| 	vouchersResp, err := h.accountService.FetchVouchers(ctx, string(publicKey)) | ||||
| 	if err != nil { | ||||
| 		res.FlagSet = append(res.FlagSet, flag_api_error) | ||||
| 		return res, nil | ||||
| 	} | ||||
| 	res.FlagReset = append(res.FlagReset, flag_api_error) | ||||
| 
 | ||||
| 	if len(vouchersResp) == 0 { | ||||
| 		res.FlagSet = append(res.FlagSet, flag_no_active_voucher) | ||||
| 		return res, nil | ||||
| 	} | ||||
| 
 | ||||
| 	res.FlagReset = append(res.FlagReset, flag_no_active_voucher) | ||||
| 
 | ||||
| 	// Check if user has an active voucher with proper error handling
 | ||||
| 	activeSym, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_SYM) | ||||
| 	if err != nil { | ||||
| 		if db.IsNotFound(err) { | ||||
| 			// No active voucher, set the first one as default
 | ||||
| 			firstVoucher := vouchersResp[0] | ||||
| 			defaultSym := firstVoucher.TokenSymbol | ||||
| 			defaultBal := firstVoucher.Balance | ||||
| 			defaultDec := firstVoucher.TokenDecimals | ||||
| 			defaultAddr := firstVoucher.TokenAddress | ||||
| 
 | ||||
| 			// Scale down the balance
 | ||||
| 			scaledBalance := store.ScaleDownBalance(defaultBal, defaultDec) | ||||
| 
 | ||||
| 			firstVoucherMap := map[storedb.DataTyp]string{ | ||||
| 				storedb.DATA_ACTIVE_SYM:     defaultSym, | ||||
| 				storedb.DATA_ACTIVE_BAL:     scaledBalance, | ||||
| 				storedb.DATA_ACTIVE_DECIMAL: defaultDec, | ||||
| 				storedb.DATA_ACTIVE_ADDRESS: defaultAddr, | ||||
| 			} | ||||
| 
 | ||||
| 			for key, value := range firstVoucherMap { | ||||
| 				if err := userStore.WriteEntry(ctx, sessionId, key, []byte(value)); err != nil { | ||||
| 					logg.ErrorCtxf(ctx, "Failed to write active voucher data", "key", key, "error", err) | ||||
| 					return res, err | ||||
| 				} | ||||
| 				err = logdb.WriteLogEntry(ctx, sessionId, key, []byte(value)) | ||||
| 				if err != nil { | ||||
| 					logg.DebugCtxf(ctx, "Failed to write voucher db log entry", "key", key, "value", value) | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			logg.InfoCtxf(ctx, "Default voucher set", "symbol", defaultSym, "balance", defaultBal, "decimals", defaultDec, "address", defaultAddr) | ||||
| 		} else { | ||||
| 			logg.ErrorCtxf(ctx, "failed to read activeSym entry with", "key", storedb.DATA_ACTIVE_SYM, "error", err) | ||||
| 			return res, err | ||||
| 		} | ||||
| 	} else { | ||||
| 		// Update active voucher balance
 | ||||
| 		activeSymStr := string(activeSym) | ||||
| 
 | ||||
| 		// Find the matching voucher data
 | ||||
| 		var activeData *dataserviceapi.TokenHoldings | ||||
| 		for _, voucher := range vouchersResp { | ||||
| 			if voucher.TokenSymbol == activeSymStr { | ||||
| 				activeData = &voucher | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if activeData == nil { | ||||
| 			logg.ErrorCtxf(ctx, "activeSym not found in vouchers, setting the first voucher as the default", "activeSym", activeSymStr) | ||||
| 			firstVoucher := vouchersResp[0] | ||||
| 			activeData = &firstVoucher | ||||
| 		} | ||||
| 
 | ||||
| 		// Scale down the balance
 | ||||
| 		scaledBalance := store.ScaleDownBalance(activeData.Balance, activeData.TokenDecimals) | ||||
| 
 | ||||
| 		// Update the balance field with the scaled value
 | ||||
| 		activeData.Balance = scaledBalance | ||||
| 
 | ||||
| 		// Pass the matching voucher data to UpdateVoucherData
 | ||||
| 		if err := store.UpdateVoucherData(ctx, h.userdataStore, sessionId, activeData); err != nil { | ||||
| 			logg.ErrorCtxf(ctx, "failed on UpdateVoucherData", "error", err) | ||||
| 			return res, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Store all voucher data
 | ||||
| 	data := store.ProcessVouchers(vouchersResp) | ||||
| 	dataMap := map[storedb.DataTyp]string{ | ||||
| 		storedb.DATA_VOUCHER_SYMBOLS:   data.Symbols, | ||||
| 		storedb.DATA_VOUCHER_BALANCES:  data.Balances, | ||||
| 		storedb.DATA_VOUCHER_DECIMALS:  data.Decimals, | ||||
| 		storedb.DATA_VOUCHER_ADDRESSES: data.Addresses, | ||||
| 	} | ||||
| 
 | ||||
| 	// Write data entries
 | ||||
| 	for key, value := range dataMap { | ||||
| 		if err := userStore.WriteEntry(ctx, sessionId, key, []byte(value)); err != nil { | ||||
| 			logg.ErrorCtxf(ctx, "Failed to write data entry for sessionId: %s", sessionId, "key", key, "error", err) | ||||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // GetVoucherList fetches the list of vouchers and formats them.
 | ||||
| func (h *MenuHandlers) GetVoucherList(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") | ||||
| 	} | ||||
| 
 | ||||
| 	userStore := h.userdataStore | ||||
| 
 | ||||
| 	// Read vouchers from the store
 | ||||
| 	voucherData, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_VOUCHER_SYMBOLS) | ||||
| 	logg.InfoCtxf(ctx, "reading voucherData in GetVoucherList", "sessionId", sessionId, "key", storedb.DATA_VOUCHER_SYMBOLS, "voucherData", voucherData) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed to read voucherData entires with", "key", storedb.DATA_VOUCHER_SYMBOLS, "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	voucherBalances, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_VOUCHER_BALANCES) | ||||
| 	logg.InfoCtxf(ctx, "reading voucherBalances in GetVoucherList", "sessionId", sessionId, "key", storedb.DATA_VOUCHER_BALANCES, "voucherBalances", voucherBalances) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed to read voucherData entires with", "key", storedb.DATA_VOUCHER_BALANCES, "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	formattedVoucherList := store.FormatVoucherList(ctx, string(voucherData), string(voucherBalances)) | ||||
| 	finalOutput := strings.Join(formattedVoucherList, "\n") | ||||
| 
 | ||||
| 	logg.InfoCtxf(ctx, "final output for GetVoucherList", "sessionId", sessionId, "finalOutput", finalOutput) | ||||
| 
 | ||||
| 	res.Content = finalOutput | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // ViewVoucher retrieves the token holding and balance from the subprefixDB
 | ||||
| // and displays it to the user for them to select it.
 | ||||
| func (h *MenuHandlers) ViewVoucher(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") | ||||
| 
 | ||||
| 	inputStr := string(input) | ||||
| 
 | ||||
| 	metadata, err := store.GetVoucherData(ctx, h.userdataStore, sessionId, inputStr) | ||||
| 	if err != nil { | ||||
| 		return res, fmt.Errorf("failed to retrieve voucher data: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if metadata == nil { | ||||
| 		res.FlagSet = append(res.FlagSet, flag_incorrect_voucher) | ||||
| 		return res, nil | ||||
| 	} | ||||
| 
 | ||||
| 	if err := store.StoreTemporaryVoucher(ctx, h.userdataStore, sessionId, metadata); err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed on StoreTemporaryVoucher", "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	res.FlagReset = append(res.FlagReset, flag_incorrect_voucher) | ||||
| 	res.Content = l.Get("Symbol: %s\nBalance: %s", metadata.TokenSymbol, metadata.Balance) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // SetVoucher retrieves the temp voucher data and sets it as the active data.
 | ||||
| func (h *MenuHandlers) SetVoucher(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") | ||||
| 	} | ||||
| 
 | ||||
| 	// Get temporary data
 | ||||
| 	tempData, err := store.GetTemporaryVoucherData(ctx, h.userdataStore, sessionId) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed on GetTemporaryVoucherData", "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Set as active and clear temporary data
 | ||||
| 	if err := store.UpdateVoucherData(ctx, h.userdataStore, sessionId, tempData); err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed on UpdateVoucherData", "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	res.Content = tempData.TokenSymbol | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // GetVoucherDetails retrieves the voucher details.
 | ||||
| func (h *MenuHandlers) GetVoucherDetails(ctx context.Context, sym string, input []byte) (resource.Result, error) { | ||||
| 	var res resource.Result | ||||
| 	store := h.userdataStore | ||||
| 	sessionId, ok := ctx.Value("SessionId").(string) | ||||
| 	if !ok { | ||||
| 		return res, fmt.Errorf("missing session") | ||||
| 	} | ||||
| 	flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") | ||||
| 
 | ||||
| 	// get the active address
 | ||||
| 	activeAddress, err := store.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_ADDRESS) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed to read activeAddress entry with", "key", storedb.DATA_ACTIVE_ADDRESS, "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	// use the voucher contract address to get the data from the API
 | ||||
| 	voucherData, err := h.accountService.VoucherData(ctx, string(activeAddress)) | ||||
| 	if err != nil { | ||||
| 		res.FlagSet = append(res.FlagSet, flag_api_error) | ||||
| 		return res, nil | ||||
| 	} | ||||
| 	res.FlagReset = append(res.FlagReset, flag_api_error) | ||||
| 
 | ||||
| 	res.Content = fmt.Sprintf( | ||||
| 		"Name: %s\nSymbol: %s\nCommodity: %s\nLocation: %s", voucherData.TokenName, voucherData.TokenSymbol, voucherData.TokenCommodity, voucherData.TokenLocation, | ||||
| 	) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // GetDefaultPool returns the current user's Pool. If none is set, it returns the default config pool.
 | ||||
| func (h *MenuHandlers) GetDefaultPool(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") | ||||
| 	} | ||||
| 
 | ||||
| 	userStore := h.userdataStore | ||||
| 	activePoolSym, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_POOL_SYM) | ||||
| 	if err != nil { | ||||
| 		if db.IsNotFound(err) { | ||||
| 			// set the default as the response
 | ||||
| 			res.Content = config.DefaultPoolSymbol() | ||||
| 			return res, nil | ||||
| 		} | ||||
| 
 | ||||
| 		logg.ErrorCtxf(ctx, "failed to read the activePoolSym entry with", "key", storedb.DATA_ACTIVE_POOL_SYM, "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	res.Content = string(activePoolSym) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // ViewPool retrieves the pool details from the user store
 | ||||
| // and displays it to the user for them to select it.
 | ||||
| func (h *MenuHandlers) ViewPool(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_pool, _ := h.flagManager.GetFlag("flag_incorrect_pool") | ||||
| 
 | ||||
| 	inputStr := string(input) | ||||
| 
 | ||||
| 	poolData, err := store.GetPoolData(ctx, h.userdataStore, sessionId, inputStr) | ||||
| 	if err != nil { | ||||
| 		return res, fmt.Errorf("failed to retrieve pool data: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if poolData == nil { | ||||
| 		flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") | ||||
| 
 | ||||
| 		// no match found. Call the API using the inputStr as the symbol
 | ||||
| 		poolResp, err := h.accountService.RetrievePoolDetails(ctx, inputStr) | ||||
| 		if err != nil { | ||||
| 			res.FlagSet = append(res.FlagSet, flag_api_error) | ||||
| 			return res, nil | ||||
| 		} | ||||
| 
 | ||||
| 		if len(poolResp.PoolSymbol) == 0 { | ||||
| 			// If the API does not return the data, set the flag
 | ||||
| 			res.FlagSet = append(res.FlagSet, flag_incorrect_pool) | ||||
| 			return res, nil | ||||
| 		} | ||||
| 
 | ||||
| 		poolData = poolResp | ||||
| 	} | ||||
| 
 | ||||
| 	if err := store.StoreTemporaryPool(ctx, h.userdataStore, sessionId, poolData); err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed on StoreTemporaryPool", "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	res.FlagReset = append(res.FlagReset, flag_incorrect_pool) | ||||
| 	res.Content = l.Get("Name: %s\nSymbol: %s", poolData.PoolName, poolData.PoolSymbol) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // SetPool retrieves the temp pool data and sets it as the active data.
 | ||||
| func (h *MenuHandlers) SetPool(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") | ||||
| 	} | ||||
| 
 | ||||
| 	// Get temporary data
 | ||||
| 	tempData, err := store.GetTemporaryPoolData(ctx, h.userdataStore, sessionId) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed on GetTemporaryPoolData", "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Set as active and clear temporary data
 | ||||
| 	if err := store.UpdatePoolData(ctx, h.userdataStore, sessionId, tempData); err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed on UpdatePoolData", "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	res.Content = tempData.PoolSymbol | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // persistInitialLanguageCode receives an initial language code and persists it to the store
 | ||||
| func (h *MenuHandlers) persistInitialLanguageCode(ctx context.Context, sessionId string, code string) error { | ||||
| 	store := h.userdataStore | ||||
|  | ||||
							
								
								
									
										163
									
								
								handlers/application/pools.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								handlers/application/pools.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,163 @@ | ||||
| package application | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"git.defalsify.org/vise.git/db" | ||||
| 	"git.defalsify.org/vise.git/resource" | ||||
| 	"git.grassecon.net/grassrootseconomics/sarafu-vise/config" | ||||
| 	"git.grassecon.net/grassrootseconomics/sarafu-vise/store" | ||||
| 	storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" | ||||
| 	"gopkg.in/leonelquinteros/gotext.v1" | ||||
| ) | ||||
| 
 | ||||
| // GetPools fetches a list of 5 top pools
 | ||||
| func (h *MenuHandlers) GetPools(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") | ||||
| 	} | ||||
| 	userStore := h.userdataStore | ||||
| 
 | ||||
| 	flag_api_error, _ := h.flagManager.GetFlag("flag_api_error") | ||||
| 
 | ||||
| 	// call the api to get a list of top 5 pools sorted by swaps
 | ||||
| 	topPools, err := h.accountService.FetchTopPools(ctx) | ||||
| 	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 pools
 | ||||
| 	if len(topPools) == 0 { | ||||
| 		return res, nil | ||||
| 	} | ||||
| 
 | ||||
| 	data := store.ProcessPools(topPools) | ||||
| 
 | ||||
| 	// Store all Pool data
 | ||||
| 	dataMap := map[storedb.DataTyp]string{ | ||||
| 		storedb.DATA_POOL_NAMES:     data.PoolNames, | ||||
| 		storedb.DATA_POOL_SYMBOLS:   data.PoolSymbols, | ||||
| 		storedb.DATA_POOL_ADDRESSES: data.PoolContractAdrresses, | ||||
| 	} | ||||
| 
 | ||||
| 	// Write data entries
 | ||||
| 	for key, value := range dataMap { | ||||
| 		if err := userStore.WriteEntry(ctx, sessionId, key, []byte(value)); err != nil { | ||||
| 			logg.ErrorCtxf(ctx, "Failed to write data entry for sessionId: %s", sessionId, "key", key, "error", err) | ||||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	res.Content = h.ReplaceSeparatorFunc(data.PoolSymbols) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // GetDefaultPool returns the current user's Pool. If none is set, it returns the default config pool.
 | ||||
| func (h *MenuHandlers) GetDefaultPool(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") | ||||
| 	} | ||||
| 
 | ||||
| 	userStore := h.userdataStore | ||||
| 	activePoolSym, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_POOL_SYM) | ||||
| 	if err != nil { | ||||
| 		if db.IsNotFound(err) { | ||||
| 			// set the default as the response
 | ||||
| 			res.Content = config.DefaultPoolSymbol() | ||||
| 			return res, nil | ||||
| 		} | ||||
| 
 | ||||
| 		logg.ErrorCtxf(ctx, "failed to read the activePoolSym entry with", "key", storedb.DATA_ACTIVE_POOL_SYM, "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	res.Content = string(activePoolSym) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // ViewPool retrieves the pool details from the user store
 | ||||
| // and displays it to the user for them to select it.
 | ||||
| func (h *MenuHandlers) ViewPool(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_pool, _ := h.flagManager.GetFlag("flag_incorrect_pool") | ||||
| 
 | ||||
| 	inputStr := string(input) | ||||
| 
 | ||||
| 	poolData, err := store.GetPoolData(ctx, h.userdataStore, sessionId, inputStr) | ||||
| 	if err != nil { | ||||
| 		return res, fmt.Errorf("failed to retrieve pool data: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if poolData == nil { | ||||
| 		flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") | ||||
| 
 | ||||
| 		// no match found. Call the API using the inputStr as the symbol
 | ||||
| 		poolResp, err := h.accountService.RetrievePoolDetails(ctx, inputStr) | ||||
| 		if err != nil { | ||||
| 			res.FlagSet = append(res.FlagSet, flag_api_error) | ||||
| 			return res, nil | ||||
| 		} | ||||
| 
 | ||||
| 		if len(poolResp.PoolSymbol) == 0 { | ||||
| 			// If the API does not return the data, set the flag
 | ||||
| 			res.FlagSet = append(res.FlagSet, flag_incorrect_pool) | ||||
| 			return res, nil | ||||
| 		} | ||||
| 
 | ||||
| 		poolData = poolResp | ||||
| 	} | ||||
| 
 | ||||
| 	if err := store.StoreTemporaryPool(ctx, h.userdataStore, sessionId, poolData); err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed on StoreTemporaryPool", "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	res.FlagReset = append(res.FlagReset, flag_incorrect_pool) | ||||
| 	res.Content = l.Get("Name: %s\nSymbol: %s", poolData.PoolName, poolData.PoolSymbol) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // SetPool retrieves the temp pool data and sets it as the active data.
 | ||||
| func (h *MenuHandlers) SetPool(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") | ||||
| 	} | ||||
| 
 | ||||
| 	// Get temporary data
 | ||||
| 	tempData, err := store.GetTemporaryPoolData(ctx, h.userdataStore, sessionId) | ||||
| 	if err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed on GetTemporaryPoolData", "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Set as active and clear temporary data
 | ||||
| 	if err := store.UpdatePoolData(ctx, h.userdataStore, sessionId, tempData); err != nil { | ||||
| 		logg.ErrorCtxf(ctx, "failed on UpdatePoolData", "error", err) | ||||
| 		return res, err | ||||
| 	} | ||||
| 
 | ||||
| 	res.Content = tempData.PoolSymbol | ||||
| 	return res, nil | ||||
| } | ||||
| @ -13,52 +13,6 @@ import ( | ||||
| 	"gopkg.in/leonelquinteros/gotext.v1" | ||||
| ) | ||||
| 
 | ||||
| // GetPools fetches a list of 5 top pools
 | ||||
| func (h *MenuHandlers) GetPools(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") | ||||
| 	} | ||||
| 	userStore := h.userdataStore | ||||
| 
 | ||||
| 	flag_api_error, _ := h.flagManager.GetFlag("flag_api_error") | ||||
| 
 | ||||
| 	// call the api to get a list of top 5 pools sorted by swaps
 | ||||
| 	topPools, err := h.accountService.FetchTopPools(ctx) | ||||
| 	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 pools
 | ||||
| 	if len(topPools) == 0 { | ||||
| 		return res, nil | ||||
| 	} | ||||
| 
 | ||||
| 	data := store.ProcessPools(topPools) | ||||
| 
 | ||||
| 	// Store all Pool data
 | ||||
| 	dataMap := map[storedb.DataTyp]string{ | ||||
| 		storedb.DATA_POOL_NAMES:     data.PoolNames, | ||||
| 		storedb.DATA_POOL_SYMBOLS:   data.PoolSymbols, | ||||
| 		storedb.DATA_POOL_ADDRESSES: data.PoolContractAdrresses, | ||||
| 	} | ||||
| 
 | ||||
| 	// Write data entries
 | ||||
| 	for key, value := range dataMap { | ||||
| 		if err := userStore.WriteEntry(ctx, sessionId, key, []byte(value)); err != nil { | ||||
| 			logg.ErrorCtxf(ctx, "Failed to write data entry for sessionId: %s", sessionId, "key", key, "error", err) | ||||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	res.Content = h.ReplaceSeparatorFunc(data.PoolSymbols) | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // LoadSwapFromList returns a list of possible vouchers to swap to
 | ||||
| func (h *MenuHandlers) LoadSwapToList(ctx context.Context, sym string, input []byte) (resource.Result, error) { | ||||
| 	var res resource.Result | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user