update minimum top-up and fix some sync issues between client and server
This commit is contained in:
parent
10e0c22108
commit
3cde1ffb63
@ -45,12 +45,14 @@ func main() {
|
||||
e.GET("/", h.RootHandler)
|
||||
|
||||
e.POST("/api/accounts", h.CreateAccountHandler)
|
||||
e.POST("/api/payments/by-account", h.CreatePaymentByAccountNumberHandler)
|
||||
|
||||
api := e.Group("/api")
|
||||
api.Use(h.AuthMiddleware)
|
||||
|
||||
api.GET("/account", h.GetAccountHandler)
|
||||
api.POST("/payments", h.CreatePaymentHandler)
|
||||
api.POST("/topup", h.CreateTopUpHandler)
|
||||
api.GET("/payments", h.GetPaymentsHandler)
|
||||
api.GET("/payments/:id", h.GetPaymentHandler)
|
||||
api.POST("/payments/:id/confirm", h.ConfirmPaymentHandler)
|
||||
|
||||
@ -47,14 +47,17 @@ func newAccountCreateCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
config.AccountNumber = account.AccountNumber
|
||||
config.AccessToken = account.AccessToken
|
||||
if err := config.Save(); err != nil {
|
||||
return fmt.Errorf("failed to save config: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Account created successfully!\n")
|
||||
fmt.Printf("Account Number: %s\n", account.AccountNumber)
|
||||
fmt.Printf("Access Token: %s\n", account.AccessToken)
|
||||
fmt.Printf("Status: %s\n", getAccountStatus(account))
|
||||
fmt.Printf("\nTo activate your account, add funds using: tcman account top-up\n")
|
||||
fmt.Printf("\nIMPORTANT: Save your account number and access token!\n")
|
||||
fmt.Printf("You are now logged in. Add funds using: tcman account top-up 1\n")
|
||||
|
||||
return nil
|
||||
},
|
||||
@ -142,17 +145,18 @@ func newAccountInfoCmd() *cobra.Command {
|
||||
|
||||
func newAccountTopUpCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "top-up <amount>",
|
||||
Use: "top-up <amount> [account-number]",
|
||||
Short: "Add funds to your account via Bitcoin",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Long: "Add funds to your account. If logged in, uses your account. If not logged in, provide account number.",
|
||||
Args: cobra.RangeArgs(1, 2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
amount, err := strconv.ParseFloat(args[0], 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid amount: %w", err)
|
||||
}
|
||||
|
||||
if amount < 5.0 {
|
||||
return fmt.Errorf("minimum top-up amount is $5.00 USD")
|
||||
if amount < 1.0 {
|
||||
return fmt.Errorf("minimum top-up amount is $1.00 USD")
|
||||
}
|
||||
|
||||
config, err := LoadConfig()
|
||||
@ -160,20 +164,29 @@ func newAccountTopUpCmd() *cobra.Command {
|
||||
return fmt.Errorf("failed to load config: %w", err)
|
||||
}
|
||||
|
||||
if !config.IsAuthenticated() {
|
||||
return fmt.Errorf("not logged in. Use 'tcman account login' or 'tcman account create'")
|
||||
var accountNumber string
|
||||
|
||||
if len(args) == 2 {
|
||||
accountNumber = args[1]
|
||||
} else if config.IsAuthenticated() {
|
||||
accountNumber = config.AccountNumber
|
||||
} else if config.AccountNumber != "" {
|
||||
accountNumber = config.AccountNumber
|
||||
} else {
|
||||
return fmt.Errorf("account number required. Usage: tcman account top-up <amount> <account-number>")
|
||||
}
|
||||
|
||||
client := NewClient(config.ServerURL, config.AccessToken)
|
||||
client := NewClient(config.ServerURL, "")
|
||||
ctx := context.Background()
|
||||
|
||||
payment, err := client.CreatePayment(ctx, amount)
|
||||
payment, err := client.CreatePaymentByAccountNumber(ctx, accountNumber, amount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create payment: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Bitcoin Payment Created:\n")
|
||||
fmt.Printf(" Payment ID: %d\n", payment.ID)
|
||||
fmt.Printf(" Account: %s\n", accountNumber)
|
||||
fmt.Printf(" Amount: $%.2f USD (%.8f BTC)\n", payment.USDAmount, payment.BTCAmount)
|
||||
fmt.Printf(" Address: %s\n", payment.BTCAddress)
|
||||
fmt.Printf(" Status: %s\n", strings.ToUpper(payment.Status))
|
||||
@ -181,7 +194,7 @@ func newAccountTopUpCmd() *cobra.Command {
|
||||
fmt.Printf(" Expires: %s\n", payment.ExpiresAt.Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
fmt.Printf("\nSend exactly %.8f BTC to the address above.\n", payment.BTCAmount)
|
||||
fmt.Printf("Check payment status with: tcman account payments\n")
|
||||
fmt.Printf("Your payment will be confirmed manually after Bitcoin is received.\n")
|
||||
|
||||
return nil
|
||||
},
|
||||
|
||||
@ -19,6 +19,7 @@ type Client struct {
|
||||
type Account struct {
|
||||
ID int64 `json:"id"`
|
||||
AccountNumber string `json:"accountNumber"`
|
||||
AccessToken string `json:"accessToken,omitempty"`
|
||||
BalanceUSD float64 `json:"balanceUsd"`
|
||||
IsActive bool `json:"isActive"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
@ -134,6 +135,16 @@ func (c *Client) CreatePayment(ctx context.Context, usdAmount float64) (*Payment
|
||||
return &payment, err
|
||||
}
|
||||
|
||||
func (c *Client) CreatePaymentByAccountNumber(ctx context.Context, accountNumber string, usdAmount float64) (*Payment, error) {
|
||||
req := map[string]interface{}{
|
||||
"account_number": accountNumber,
|
||||
"usd_amount": usdAmount,
|
||||
}
|
||||
var payment Payment
|
||||
err := c.makeRequest(ctx, "POST", "/api/payments/by-account", req, &payment)
|
||||
return &payment, err
|
||||
}
|
||||
|
||||
func (c *Client) GetPayment(ctx context.Context, paymentID int64) (*Payment, error) {
|
||||
var payment Payment
|
||||
path := fmt.Sprintf("/api/payments/%d", paymentID)
|
||||
|
||||
@ -62,6 +62,28 @@ func (h *Handlers) CreateAccountHandler(c echo.Context) error {
|
||||
return c.JSON(201, account)
|
||||
}
|
||||
|
||||
func (h *Handlers) CreatePaymentByAccountNumberHandler(c echo.Context) error {
|
||||
var req struct {
|
||||
AccountNumber string `json:"account_number"`
|
||||
USDAmount float64 `json:"usd_amount"`
|
||||
}
|
||||
if err := c.Bind(&req); err != nil || req.USDAmount < 1.0 || req.AccountNumber == "" {
|
||||
return c.JSON(400, map[string]string{"error": "Account number required and minimum payment amount is $1.00 USD"})
|
||||
}
|
||||
|
||||
account, err := h.accountService.GetAccountByNumber(context.Background(), req.AccountNumber)
|
||||
if err != nil {
|
||||
return c.JSON(404, map[string]string{"error": "Account not found"})
|
||||
}
|
||||
|
||||
payment, err := h.accountService.CreatePayment(context.Background(), account.ID, req.USDAmount)
|
||||
if err != nil {
|
||||
return c.JSON(500, map[string]string{"error": "Failed to create payment"})
|
||||
}
|
||||
|
||||
return c.JSON(201, payment)
|
||||
}
|
||||
|
||||
func (h *Handlers) GetAccountHandler(c echo.Context) error {
|
||||
account := c.Get("account").(*db.Account)
|
||||
return c.JSON(200, account)
|
||||
@ -85,6 +107,24 @@ func (h *Handlers) CreatePaymentHandler(c echo.Context) error {
|
||||
return c.JSON(201, payment)
|
||||
}
|
||||
|
||||
func (h *Handlers) CreateTopUpHandler(c echo.Context) error {
|
||||
account := c.Get("account").(*db.Account)
|
||||
|
||||
var req struct {
|
||||
USDAmount float64 `json:"usd_amount"`
|
||||
}
|
||||
if err := c.Bind(&req); err != nil || req.USDAmount < 1.0 {
|
||||
return c.JSON(400, map[string]string{"error": "Minimum top-up amount is $1.00 USD"})
|
||||
}
|
||||
|
||||
payment, err := h.accountService.CreatePayment(context.Background(), account.ID, req.USDAmount)
|
||||
if err != nil {
|
||||
return c.JSON(500, map[string]string{"error": "Failed to create top-up"})
|
||||
}
|
||||
|
||||
return c.JSON(201, payment)
|
||||
}
|
||||
|
||||
func (h *Handlers) GetPaymentHandler(c echo.Context) error {
|
||||
paymentID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user