npm package: @tamasha/grpc-contracts
Description: Simple gRPC contracts and utilities for Tamasha microservices
Author: Tamasha Team
Latest version: 1.0.42

# @tamasha/grpc-contracts

Simple and easy-to-use gRPC contracts and utilities for Tamasha microservices.

## 🚀 Quick Start

```bash
npm install @tamasha/grpc-contracts
```

## 📦 What's Included

- **Proto files**: Ready-to-use protocol buffer definitions
- **Simple Client**: Easy gRPC client creation
- **Simple Server**: Easy gRPC server setup
- **Error Handling**: Built-in error management
- **TypeScript Support**: Full TypeScript definitions

## 🔧 Usage

### Creating Auto-Generated Typed gRPC Clients

```typescript
import { 
  GrpcClient, 
  UserServiceClient,
  AuthServiceClient,
  CreateUserRequest,
  User,
  LoginRequest,
  LoginResponse
} from '@tamasha/grpc-contracts';

// Create typed clients (automatically generated from proto files)
const userClient: UserServiceClient = GrpcClient.createUserServiceClient({
  host: 'localhost',
  port: 50051
});

const authClient: AuthServiceClient = GrpcClient.createAuthServiceClient({
  host: 'localhost',
  port: 50052
});

// Use with full type safety and IntelliSense
const createUserRequest: CreateUserRequest = {
  email: 'user@example.com',
  username: 'johndoe',
  first_name: 'John',
  last_name: 'Doe',
  password: 'password123'
};

userClient.createUser(createUserRequest, (error, user: User) => {
  if (error) {
    console.error('Error:', error);
  } else {
    console.log('User created:', user.email);
  }
});
```

### Creating a gRPC Server

```typescript
import { GrpcServer, GrpcError, status } from '@tamasha/grpc-contracts';

// Create server
const server = GrpcServer.create({ port: 50051 });

// Define service implementation
const userService = {
  createUser: (call, callback) => {
    try {
      const { email, username, first_name, last_name } = call.request;
      
      // Your business logic here
      const user = {
        id: 'generated-id',
        email,
        username,
        first_name,
        last_name,
        is_active: true,
        created_at: Date.now(),
        updated_at: Date.now()
      };

      callback(null, user);
    } catch (error) {
      callback(GrpcError.fromError(error));
    }
  }
};

// Add service and start (no proto path needed!)
await server.addService('UserService', userService);
await server.start({ port: 50051 });
```

## 📁 Available Services

### User Service
- `CreateUser` - Create a new user
- `GetUser` - Get user by ID
- `UpdateUser` - Update user information
- `ListUsers` - List users with pagination
- `DeleteUser` - Delete a user

### Auth Service
- `Login` - User authentication
- `ValidateToken` - Validate JWT token
- `RefreshToken` - Refresh access token
- `Logout` - User logout

### Payment Service
- `GetPaymentGatewayAggregator` - Fetch gateway configuration and redirect URL for a workspace
- `PaymentOrder` - Create an order and retrieve payment identifiers
- `GetPaymentOrderDetails` - Retrieve full details for a previously created payment order

```typescript
import {
  GrpcClient,
  PaymentServiceClient,
  GetPaymentOrderDetailRequest,
} from "@tamasha/grpc-contracts";

const client: PaymentServiceClient = GrpcClient.createPaymentServiceClient({
  host: "payment-service",
  port: 50054,
});

const request: GetPaymentOrderDetailRequest = { order_id: "order-123" };

client.getPaymentOrderDetail(request, (error, response) => {
  if (error) {
    console.error("Failed to fetch payment order details", error);
    return;
  }

  console.log("Payment status:", response.status);
});
```

> Check `examples/get-payment-order-detail-example.ts` for a runnable script.

### GPT EventService
- `SendEvent` - Send events to GPT service for processing

## 🏗️ Usage Across Microservices

### In Service A (User Service)
```typescript
import { GrpcServer } from '@tamasha/grpc-contracts';

const server = GrpcServer.create({ port: 50051 });
await server.addService('UserService', userImplementation);
await server.start({ port: 50051 });
```

### In Service B (Auth Service)
```typescript
import { GrpcClient, UserServiceClient } from '@tamasha/grpc-contracts';

// Typed client with full IntelliSense
const userClient: UserServiceClient = await GrpcClient.createUserServiceClient({
  host: 'user-service',
  port: 50051
});

// Type-safe method calls
userClient.getUser({ id: '123' }, (error, user) => {
  console.log('User:', user.email); // Full type safety
});
```

### In Service C (Notification Service)
```typescript
import { GrpcClient, AuthServiceClient } from '@tamasha/grpc-contracts';

const authClient: AuthServiceClient = await GrpcClient.createAuthServiceClient({
  host: 'auth-service',
  port: 50052
});

// Validate token before sending notification
authClient.validateToken({ token: 'jwt-token' }, (error, result) => {
  if (result.valid) {
    // Send notification with type safety
  }
});
```

### GPT EventService Usage

```typescript
import { 
  GrpcClient, 
  EventServiceClient,
  SendEventRequest,
  SendEventResponse
} from '@tamasha/grpc-contracts';

// Create EventService client
const eventClient: EventServiceClient = GrpcClient.createEventServiceClient({
  host: 'localhost',
  port: 50053
});

// Send event with full type safety
const eventRequest: SendEventRequest = {
  req_guid: 'req-123-456-789',
  event_type: 'user_action',
  event_base64_encoded: Buffer.from(JSON.stringify({
    action: 'click',
    element: 'button',
    timestamp: Date.now(),
    user_id: 'user-123'
  })).toString('base64')
};

const response = await new Promise<SendEventResponse>((resolve, reject) => {
  eventClient.sendEvent(eventRequest, (error, response) => {
    if (error) reject(error);
    else resolve(response);
  });
});

console.log('Event processed:', response.status, response.message);
```

### Payment Service Usage

```typescript
import {
  GrpcClient,
  GetPaymentGatewayAggregatorRequest,
  GetPaymentGatewayAggregatorResponse,
  PaymentOrderRequest,
  PaymentOrderResponse,
} from '@tamasha/grpc-contracts';

// Create a typed client for PaymentService
const paymentClient = GrpcClient.createPaymentServiceClient({
  host: 'localhost',
  port: 50054,
});

const request: GetPaymentGatewayAggregatorRequest = {
  workspace_id: 42,
  app_version: 120,
  system_config: {
    enable_upi: true,
    enable_card: false,
  },
  country: 'IN',
  loggedin_user_id: 98765,
};

const response = await new Promise<GetPaymentGatewayAggregatorResponse>((resolve, reject) => {
  paymentClient.getPaymentGatewayAggregator(request, (error, result) => {
    if (error) reject(error);
    else resolve(result);
  });
});

console.log('Aggregator:', response.payment_gateway_aggregator);
console.log('Aggregator URL:', response.payment_gateway_aggregator_url);

const paymentOrderRequest: PaymentOrderRequest = {
  client_id: 'client-123',
  amount: 1500,
  gateway: 'razorpay',
  reference_transaction_id: 'txn-ref-001',
  meta_data: {
    product: 'monthly_subscription',
  },
};

const paymentOrderResponse = await new Promise<PaymentOrderResponse>((resolve, reject) => {
  paymentClient.paymentOrder(paymentOrderRequest, (error, result) => {
    if (error) reject(error);
    else resolve(result);
  });
});

console.log('Payment order status:', paymentOrderResponse.status);
console.log('Payment order id:', paymentOrderResponse.order_id);
console.log('Payment id:', paymentOrderResponse.payment_id);
```

### Wallet Service Example

```typescript
import { 
  GrpcClient, 
  WalletServiceClient,
  AddBalanceRequest,
  DeductBalanceRequest,
  AmountType 
} from '@tamasha/grpc-contracts';

const walletClient: WalletServiceClient = GrpcClient.createWalletServiceClient({
  host: 'localhost',
  port: 50053
});

// Add balance to player's wallet
const addBalanceRequest: AddBalanceRequest = {
  ext_transaction_id: "add_txn_" + Date.now(),
  player_id: 12345,
  amount_type: AmountType.DepositCash,
  amount: 100.50,
  reason: "Deposit from payment gateway"
};

walletClient.addBalance(addBalanceRequest, (error, response) => {
  if (error) {
    console.error('Error:', error);
  } else if (response.success) {
    console.log('✅ Balance added successfully!');
    console.log('Transaction ID:', response.data?.wallet_transaction_id);
  }
});

// Deduct balance from player's wallet
const deductBalanceRequest: DeductBalanceRequest = {
  ext_transaction_id: "deduct_txn_" + Date.now(),
  player_id: 12345,
  amount_type: AmountType.DepositCash,
  amount: 25.00,
  reason: "Game entry fee"
};

walletClient.deductBalance(deductBalanceRequest, (error, response) => {
  if (error) {
    console.error('Error:', error);
  } else if (response.success) {
    console.log('✅ Balance deducted successfully!');
    console.log('Transaction ID:', response.data?.wallet_transaction_id);
  }
});
```

> Need to reconcile transactions from payment providers? Check `examples/settled-txn-by-reference-txn-id-example.ts` for settling a transaction by reference id.

## 🛠️ Proto Files

The package includes these proto files (automatically resolved):

- `proto/common.proto` - Common message types
- `proto/user.proto` - User service definitions
- `proto/auth.proto` - Authentication service definitions
- `proto/wallet.proto` - Wallet service definitions (CheckBalance, AddBalance, DeductBalance, RefundBalance, SettledTxnByReferenceTxnId)
- `proto/gpt.proto` - GPT EventService definitions

## 🔍 Error Handling

```typescript
import { GrpcError, status } from '@tamasha/grpc-contracts';

// Create custom errors
throw new GrpcError(status.NOT_FOUND, 'User not found');

// Handle errors
try {
  // Your gRPC call
} catch (error) {
  const grpcError = GrpcError.fromError(error);
  console.error('gRPC Error:', grpcError.code, grpcError.message);
}
```

## 📝 Examples

Check the `examples/` directory for complete working examples:

- `client-example.ts` - How to create and use gRPC clients
- `server-example.ts` - How to create and run gRPC servers
- `add-balance-example.ts` - Complete AddBalance functionality examples with client and server implementations
- `payment-gateway-aggregator-example.ts` - Fetch payment gateway aggregator configuration
- `payment-order-example.ts` - Create a payment order and inspect identifiers

## 🏗️ Development

```bash
# Install dependencies
npm install

# Build the package
npm run build

# Clean build artifacts
npm run clean
```

## 📄 License

MIT

## 🤝 Contributing

1. Fork the repository
2. Create your feature branch
3. Commit your changes
4. Push to the branch
5. Create a Pull Request

---

**Made with ❤️ by the Tamasha Team**