cab-backend/internal/grpcserver/wallet.go
2026-03-30 21:00:35 +03:00

119 lines
3.4 KiB
Go

package grpcserver
import (
"context"
"errors"
"strconv"
walletpb "game-admin/gen"
"game-admin/internal/wallet"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type WalletServer struct {
walletpb.UnimplementedWalletServiceServer
service *wallet.Service
}
func NewWalletServer(service *wallet.Service) *WalletServer {
return &WalletServer{service: service}
}
func (s *WalletServer) Reserve(ctx context.Context, req *walletpb.ReserveRequest) (*walletpb.ReserveResponse, error) {
transaction, responseStatus, balances, err := s.service.Reserve(
ctx,
req.GetRequestId(),
req.GetUserId(),
req.GetGameId(),
req.GetRoundId(),
req.GetAmount(),
req.GetCurrency(),
)
if err != nil {
return nil, mapWalletError(err)
}
return &walletpb.ReserveResponse{
TransactionId: transaction.ID,
Status: responseStatus,
AvailableBalance: balances.Available,
ReservedBalance: balances.Reserved,
}, nil
}
func (s *WalletServer) Confirm(ctx context.Context, req *walletpb.ConfirmRequest) (*walletpb.ConfirmResponse, error) {
transaction, responseStatus, balances, err := s.service.Confirm(
ctx,
req.GetTransactionId(),
req.GetRoundId(),
req.GetWinAmount(),
)
if err != nil {
return nil, mapWalletError(err)
}
return &walletpb.ConfirmResponse{
TransactionId: transaction.ID,
Status: responseStatus,
AvailableBalance: balances.Available,
ReservedBalance: balances.Reserved,
}, nil
}
func (s *WalletServer) Cancel(ctx context.Context, req *walletpb.CancelRequest) (*walletpb.CancelResponse, error) {
transaction, responseStatus, balances, err := s.service.Cancel(ctx, req.GetTransactionId())
if err != nil {
return nil, mapWalletError(err)
}
return &walletpb.CancelResponse{
TransactionId: transaction.ID,
Status: responseStatus,
AvailableBalance: balances.Available,
ReservedBalance: balances.Reserved,
}, nil
}
func (s *WalletServer) GetTransaction(ctx context.Context, req *walletpb.GetTransactionRequest) (*walletpb.GetTransactionResponse, error) {
transaction, err := s.service.GetTransaction(ctx, req.GetTransactionId())
if err != nil {
return nil, mapWalletError(err)
}
return &walletpb.GetTransactionResponse{
TransactionId: transaction.ID,
UserId: strconv.FormatInt(transaction.UserID, 10),
RoundId: transaction.RoundID,
Amount: transaction.Amount,
WinAmount: transaction.WinAmount,
Status: transaction.Status,
}, nil
}
func mapWalletError(err error) error {
switch {
case errors.Is(err, wallet.ErrInvalidAmount),
errors.Is(err, wallet.ErrMissingRequiredFields),
errors.Is(err, wallet.ErrInvalidUserID),
errors.Is(err, wallet.ErrInvalidGameID),
errors.Is(err, wallet.ErrMissingTransactionID),
errors.Is(err, wallet.ErrMissingRoundID),
errors.Is(err, wallet.ErrInvalidWinAmount),
errors.Is(err, wallet.ErrRoundMismatch):
return status.Error(codes.InvalidArgument, err.Error())
case errors.Is(err, wallet.ErrAccountNotFound),
errors.Is(err, wallet.ErrTransactionNotFound):
return status.Error(codes.NotFound, err.Error())
case errors.Is(err, wallet.ErrInsufficientFunds),
errors.Is(err, wallet.ErrAlreadyCanceled),
errors.Is(err, wallet.ErrAlreadyConfirmed),
errors.Is(err, wallet.ErrInvalidTransactionState):
return status.Error(codes.FailedPrecondition, err.Error())
default:
return status.Error(codes.Internal, err.Error())
}
}