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()) } }