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.GET("/", h.RootHandler)
|
||||||
|
|
||||||
e.POST("/api/accounts", h.CreateAccountHandler)
|
e.POST("/api/accounts", h.CreateAccountHandler)
|
||||||
|
e.POST("/api/payments/by-account", h.CreatePaymentByAccountNumberHandler)
|
||||||
|
|
||||||
api := e.Group("/api")
|
api := e.Group("/api")
|
||||||
api.Use(h.AuthMiddleware)
|
api.Use(h.AuthMiddleware)
|
||||||
|
|
||||||
api.GET("/account", h.GetAccountHandler)
|
api.GET("/account", h.GetAccountHandler)
|
||||||
api.POST("/payments", h.CreatePaymentHandler)
|
api.POST("/payments", h.CreatePaymentHandler)
|
||||||
|
api.POST("/topup", h.CreateTopUpHandler)
|
||||||
api.GET("/payments", h.GetPaymentsHandler)
|
api.GET("/payments", h.GetPaymentsHandler)
|
||||||
api.GET("/payments/:id", h.GetPaymentHandler)
|
api.GET("/payments/:id", h.GetPaymentHandler)
|
||||||
api.POST("/payments/:id/confirm", h.ConfirmPaymentHandler)
|
api.POST("/payments/:id/confirm", h.ConfirmPaymentHandler)
|
||||||
|
|||||||
@ -47,14 +47,17 @@ func newAccountCreateCmd() *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config.AccountNumber = account.AccountNumber
|
config.AccountNumber = account.AccountNumber
|
||||||
|
config.AccessToken = account.AccessToken
|
||||||
if err := config.Save(); err != nil {
|
if err := config.Save(); err != nil {
|
||||||
return fmt.Errorf("failed to save config: %w", err)
|
return fmt.Errorf("failed to save config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Account created successfully!\n")
|
fmt.Printf("Account created successfully!\n")
|
||||||
fmt.Printf("Account Number: %s\n", account.AccountNumber)
|
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("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
|
return nil
|
||||||
},
|
},
|
||||||
@ -142,17 +145,18 @@ func newAccountInfoCmd() *cobra.Command {
|
|||||||
|
|
||||||
func newAccountTopUpCmd() *cobra.Command {
|
func newAccountTopUpCmd() *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "top-up <amount>",
|
Use: "top-up <amount> [account-number]",
|
||||||
Short: "Add funds to your account via Bitcoin",
|
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 {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
amount, err := strconv.ParseFloat(args[0], 64)
|
amount, err := strconv.ParseFloat(args[0], 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid amount: %w", err)
|
return fmt.Errorf("invalid amount: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if amount < 5.0 {
|
if amount < 1.0 {
|
||||||
return fmt.Errorf("minimum top-up amount is $5.00 USD")
|
return fmt.Errorf("minimum top-up amount is $1.00 USD")
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := LoadConfig()
|
config, err := LoadConfig()
|
||||||
@ -160,20 +164,29 @@ func newAccountTopUpCmd() *cobra.Command {
|
|||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !config.IsAuthenticated() {
|
var accountNumber string
|
||||||
return fmt.Errorf("not logged in. Use 'tcman account login' or 'tcman account create'")
|
|
||||||
|
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()
|
ctx := context.Background()
|
||||||
|
|
||||||
payment, err := client.CreatePayment(ctx, amount)
|
payment, err := client.CreatePaymentByAccountNumber(ctx, accountNumber, amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create payment: %w", err)
|
return fmt.Errorf("failed to create payment: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Bitcoin Payment Created:\n")
|
fmt.Printf("Bitcoin Payment Created:\n")
|
||||||
fmt.Printf(" Payment ID: %d\n", payment.ID)
|
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(" Amount: $%.2f USD (%.8f BTC)\n", payment.USDAmount, payment.BTCAmount)
|
||||||
fmt.Printf(" Address: %s\n", payment.BTCAddress)
|
fmt.Printf(" Address: %s\n", payment.BTCAddress)
|
||||||
fmt.Printf(" Status: %s\n", strings.ToUpper(payment.Status))
|
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(" 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("\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
|
return nil
|
||||||
},
|
},
|
||||||
|
|||||||
@ -19,6 +19,7 @@ type Client struct {
|
|||||||
type Account struct {
|
type Account struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
AccountNumber string `json:"accountNumber"`
|
AccountNumber string `json:"accountNumber"`
|
||||||
|
AccessToken string `json:"accessToken,omitempty"`
|
||||||
BalanceUSD float64 `json:"balanceUsd"`
|
BalanceUSD float64 `json:"balanceUsd"`
|
||||||
IsActive bool `json:"isActive"`
|
IsActive bool `json:"isActive"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
@ -134,6 +135,16 @@ func (c *Client) CreatePayment(ctx context.Context, usdAmount float64) (*Payment
|
|||||||
return &payment, err
|
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) {
|
func (c *Client) GetPayment(ctx context.Context, paymentID int64) (*Payment, error) {
|
||||||
var payment Payment
|
var payment Payment
|
||||||
path := fmt.Sprintf("/api/payments/%d", paymentID)
|
path := fmt.Sprintf("/api/payments/%d", paymentID)
|
||||||
|
|||||||
@ -62,6 +62,28 @@ func (h *Handlers) CreateAccountHandler(c echo.Context) error {
|
|||||||
return c.JSON(201, account)
|
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 {
|
func (h *Handlers) GetAccountHandler(c echo.Context) error {
|
||||||
account := c.Get("account").(*db.Account)
|
account := c.Get("account").(*db.Account)
|
||||||
return c.JSON(200, account)
|
return c.JSON(200, account)
|
||||||
@ -85,6 +107,24 @@ func (h *Handlers) CreatePaymentHandler(c echo.Context) error {
|
|||||||
return c.JSON(201, payment)
|
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 {
|
func (h *Handlers) GetPaymentHandler(c echo.Context) error {
|
||||||
paymentID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
paymentID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user