feat: added wallet service
This commit is contained in:
219
server/services/wallet/service.go
Normal file
219
server/services/wallet/service.go
Normal file
@@ -0,0 +1,219 @@
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"ccoin/utils/crypto"
|
||||
"database/sql"
|
||||
"ccoin/models/wallet"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type WalletService struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
// Creates a new instance of WalletService
|
||||
func NewWalletService(db *sql.DB) *WalletService {
|
||||
return &WalletService{db: db}
|
||||
}
|
||||
|
||||
// Creates a new wallet with optional label
|
||||
func (ws *WalletService) CreateWallet(req wallet.CreateWalletRequest) (wallet.WalletResponse, error) {
|
||||
address := crypto.GenerateWalletAddress()
|
||||
timestamp := time.Now()
|
||||
var passwordHash string
|
||||
if req.Password != "" {
|
||||
passwordHash = crypto.HashPassword(req.Password)
|
||||
} else {
|
||||
return wallet.WalletResponse{}, fmt.Errorf("password field is required")
|
||||
}
|
||||
|
||||
_, err := ws.db.Exec(`
|
||||
INSERT INTO wallets (address, balance, label, password_hash, created_at)
|
||||
VALUES ($1, $2, $3, $4, $5)`,
|
||||
address, 0.0, req.Label, passwordHash, timestamp.Unix(),
|
||||
)
|
||||
if err != nil {
|
||||
return wallet.WalletResponse{}, err
|
||||
}
|
||||
|
||||
return wallet.WalletResponse{
|
||||
Address: address,
|
||||
Balance: 0.0,
|
||||
Label: req.Label,
|
||||
PasswordHash: passwordHash,
|
||||
CreatedAt: timestamp.Unix(),
|
||||
LastActivity: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Gets wallet by address
|
||||
func (ws *WalletService) GetWallet(address string) (*wallet.WalletResponse, error) {
|
||||
var w wallet.Wallet
|
||||
row := ws.db.QueryRow(`
|
||||
SELECT address, balance, label, password_hash, created_at, last_activity
|
||||
FROM wallets WHERE address = $1`, address)
|
||||
|
||||
err := row.Scan(&w.Address, &w.Balance, &w.Label, &w.PasswordHash, &w.CreatedAt, &w.LastActivity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &wallet.WalletResponse{
|
||||
Address: w.Address,
|
||||
Balance: w.Balance,
|
||||
Label: w.Label,
|
||||
PasswordHash: w.PasswordHash,
|
||||
CreatedAt: w.CreatedAt.Unix(),
|
||||
LastActivity: ptrTime(w.LastActivity),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Gets wallet balance
|
||||
func (ws *WalletService) GetWalletBalance(address string) (wallet.BalanceResponse, error) {
|
||||
var balance float64
|
||||
err := ws.db.QueryRow(`SELECT balance FROM wallets WHERE address = $1`, address).Scan(&balance)
|
||||
if err != nil {
|
||||
return wallet.BalanceResponse{}, errors.New("wallet not found")
|
||||
}
|
||||
return wallet.BalanceResponse{
|
||||
Address: address,
|
||||
Balance: balance,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Updates wallet balance
|
||||
func (ws *WalletService) UpdateBalance(address string, amount float64) (bool, error) {
|
||||
_, err := ws.db.Exec(`UPDATE wallets SET balance = balance + $1, last_activity = $2 WHERE address = $3`, amount, time.Now().Unix(), address)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Sets wallet balance to specific amount
|
||||
func (ws *WalletService) SetBalance(address string, amount float64) (bool, error) {
|
||||
_, err := ws.db.Exec(`UPDATE wallets SET balance = $1, last_activity = $2 WHERE address = $3`, amount, time.Now().Unix(), address)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Updates wallet label
|
||||
func (ws *WalletService) UpdateLabel(address string, req wallet.UpdateWalletRequest) (bool, error) {
|
||||
result, err := ws.db.Exec(`UPDATE wallets SET label = $1 WHERE address = $2`, address, req.Label)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
rowsAffected, _ := result.RowsAffected()
|
||||
return rowsAffected > 0, nil
|
||||
}
|
||||
|
||||
// Checks if wallet exists
|
||||
func (ws *WalletService) WalletExists(address string) (bool, error) {
|
||||
var count int64
|
||||
err := ws.db.QueryRow(`SELECT COUNT(*) FROM wallets WHERE address = $1`, address).Scan(&count)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
// Gets all wallets with pagination
|
||||
func (ws *WalletService) GetAllWallets(limit, offset int) ([]wallet.WalletResponse, error) {
|
||||
query := fmt.Sprintf(`
|
||||
SELECT address, balance, label, password_hash, created_at, last_activity
|
||||
FROM wallets ORDER BY created_at DESC LIMIT %d OFFSET %d`, limit, offset)
|
||||
|
||||
rows, err := ws.db.Query(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var wallets []wallet.WalletResponse
|
||||
for rows.Next() {
|
||||
var w wallet.Wallet
|
||||
if err := rows.Scan(&w.Address, &w.Balance, &w.Label, &w.PasswordHash,
|
||||
&w.CreatedAt, &w.LastActivity); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wallets = append(wallets, wallet.WalletResponse{
|
||||
Address: w.Address,
|
||||
Balance: w.Balance,
|
||||
Label: w.Label,
|
||||
PasswordHash: w.PasswordHash,
|
||||
CreatedAt: w.CreatedAt.Unix(),
|
||||
LastActivity: ptrTime(w.LastActivity),
|
||||
})
|
||||
}
|
||||
return wallets, nil
|
||||
}
|
||||
|
||||
// Gets total number of wallets
|
||||
func (ws *WalletService) GetTotalWalletCount() (int64, error) {
|
||||
var count int64
|
||||
err := ws.db.QueryRow(`SELECT COUNT(*) FROM wallets`).Scan(&count)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// Gets wallet with balance greater than specified amount
|
||||
func (ws *WalletService) GetWalletsWithBalance(minBalance float64) ([]wallet.WalletResponse, error) {
|
||||
rows, err := ws.db.Query(`SELECT address, balance, label, password_hash, created_at, last_activity FROM wallets WHERE balance > $1 ORDER BY balance DESC`, minBalance)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var wallets []wallet.WalletResponse
|
||||
for rows.Next() {
|
||||
var w wallet.Wallet
|
||||
if err := rows.Scan(&w.Address, &w.Balance, &w.Label, &w.PasswordHash, &w.CreatedAt, &w.LastActivity); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wallets = append(wallets, wallet.WalletResponse{
|
||||
Address: w.Address,
|
||||
Balance: w.Balance,
|
||||
Label: w.Label,
|
||||
PasswordHash: w.PasswordHash,
|
||||
CreatedAt: w.CreatedAt.Unix(),
|
||||
LastActivity: ptrTime(w.LastActivity),
|
||||
})
|
||||
}
|
||||
return wallets, nil
|
||||
}
|
||||
|
||||
// Updates last activity timestamp
|
||||
func (ws *WalletService) UpdateLastActivity(address string) (bool, error) {
|
||||
_, err := ws.db.Exec(`UPDATE wallets SET last_activity = $1 WHERE address = $2`, time.Now().Unix(), address)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Gets total supply across all wallets
|
||||
func (ws *WalletService) GetTotalSupply() (float64, error) {
|
||||
var totalSupply float64
|
||||
err := ws.db.QueryRow(`SELECT SUM(balance) FROM wallets`).Scan(&totalSupply)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return totalSupply, nil
|
||||
}
|
||||
|
||||
// Helper function to convert *time.Time to *int64 for JSON response
|
||||
func ptrTime(t *time.Time) *int64 {
|
||||
if t == nil {
|
||||
return nil
|
||||
}
|
||||
unixTime := t.Unix()
|
||||
return &unixTime
|
||||
}
|
||||
Reference in New Issue
Block a user