> ## Documentation Index
> Fetch the complete documentation index at: https://docs.transaction.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# WebSocket Support

> Real-time payment updates via WebSocket connections

## Overview

Transaction API provides WebSocket support for real-time payment updates. This allows you to receive instant notifications about payment status changes without polling the API.

## Connection

### WebSocket URL

```
wss://api.transaction.gg/ws
```

### Authentication

Include your JWT token in the connection query parameter:

```javascript theme={null}
const ws = new WebSocket('wss://api.transaction.gg/ws?token=your_jwt_token');
```

## Connection Management

### Basic Connection

```javascript theme={null}
class TransactionWebSocket {
  constructor(token) {
    this.token = token;
    this.ws = null;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 5;
  }
  
  connect() {
    this.ws = new WebSocket(`wss://api.transaction.gg/ws?token=${this.token}`);
    
    this.ws.onopen = () => {
      console.log('WebSocket connected');
      this.reconnectAttempts = 0;
    };
    
    this.ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      this.handleMessage(data);
    };
    
    this.ws.onclose = () => {
      console.log('WebSocket disconnected');
      this.handleReconnect();
    };
    
    this.ws.onerror = (error) => {
      console.error('WebSocket error:', error);
    };
  }
  
  handleMessage(data) {
    switch (data.event) {
      case 'payment.status_update':
        this.handlePaymentUpdate(data);
        break;
      case 'payment.completed':
        this.handlePaymentCompleted(data);
        break;
      case 'payment.expired':
        this.handlePaymentExpired(data);
        break;
      default:
        console.log('Unknown event:', data.event);
    }
  }
  
  handleReconnect() {
    if (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++;
      const delay = Math.pow(2, this.reconnectAttempts) * 1000;
      
      setTimeout(() => {
        console.log(`Reconnecting... (attempt ${this.reconnectAttempts})`);
        this.connect();
      }, delay);
    }
  }
}
```

### Advanced Connection with Heartbeat

```javascript theme={null}
class AdvancedTransactionWebSocket extends TransactionWebSocket {
  constructor(token) {
    super(token);
    this.heartbeatInterval = null;
    this.pingInterval = 30000; // 30 seconds
  }
  
  connect() {
    super.connect();
    
    this.ws.onopen = () => {
      console.log('WebSocket connected');
      this.reconnectAttempts = 0;
      this.startHeartbeat();
    };
    
    this.ws.onclose = () => {
      console.log('WebSocket disconnected');
      this.stopHeartbeat();
      this.handleReconnect();
    };
  }
  
  startHeartbeat() {
    this.heartbeatInterval = setInterval(() => {
      if (this.ws.readyState === WebSocket.OPEN) {
        this.ws.send(JSON.stringify({ type: 'ping' }));
      }
    }, this.pingInterval);
  }
  
  stopHeartbeat() {
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval);
      this.heartbeatInterval = null;
    }
  }
}
```

## Supported Events

### Payment Status Update

```json theme={null}
{
  "event": "payment.status_update",
  "payment": {
    "id": "pay_abc123def456",
    "status": "pending",
    "amountCrypto": "0.00012345",
    "crypto": "BTC",
    "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
    "confirmations": 2,
    "requiredConfirmations": 3
  },
  "timestamp": "2024-01-01T00:15:00Z"
}
```

### Payment Completed

```json theme={null}
{
  "event": "payment.completed",
  "payment": {
    "id": "pay_abc123def456",
    "status": "completed",
    "amountCrypto": "0.00012345",
    "crypto": "BTC",
    "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
    "incomingTxHash": "abc123...",
    "completedAt": "2024-01-01T00:30:00Z",
    "customerId": "cus_V6n6SN2KnsIFCuQU",
    "orderId": "order_123"
  },
  "timestamp": "2024-01-01T00:30:00Z"
}
```

### Payment Expired

```json theme={null}
{
  "event": "payment.expired",
  "payment": {
    "id": "pay_abc123def456",
    "status": "expired",
    "expiresAt": "2024-01-01T01:00:00Z"
  },
  "timestamp": "2024-01-01T01:00:00Z"
}
```

## Event Handling

### Payment Status Updates

```javascript theme={null}
handlePaymentUpdate(data) {
  const payment = data.payment;
  
  // Update UI with new status
  this.updatePaymentStatus(payment.id, payment.status);
  
  // Show confirmation progress
  if (payment.confirmations && payment.requiredConfirmations) {
    const progress = (payment.confirmations / payment.requiredConfirmations) * 100;
    this.updateConfirmationProgress(payment.id, progress);
  }
}
```

### Payment Completion

```javascript theme={null}
handlePaymentCompleted(data) {
  const payment = data.payment;
  
  // Update order status
  this.updateOrderStatus(payment.orderId, 'completed');
  
  // Send confirmation email
  this.sendConfirmationEmail(payment.customerId);
  
  // Redirect to success page
  this.redirectToSuccess(payment.orderId);
}
```

### Payment Expiration

```javascript theme={null}
handlePaymentExpired(data) {
  const payment = data.payment;
  
  // Update order status
  this.updateOrderStatus(payment.orderId, 'expired');
  
  // Show expiration message
  this.showExpirationMessage(payment.id);
  
  // Offer retry option
  this.offerPaymentRetry(payment.orderId);
}
```

## React Integration

### Custom Hook

```javascript theme={null}
import { useState, useEffect, useRef } from 'react';

function useTransactionWebSocket(token) {
  const [connectionStatus, setConnectionStatus] = useState('disconnected');
  const [payments, setPayments] = useState({});
  const wsRef = useRef(null);
  
  useEffect(() => {
    if (!token) return;
    
    const ws = new WebSocket(`wss://api.transaction.gg/ws?token=${token}`);
    wsRef.current = ws;
    
    ws.onopen = () => {
      setConnectionStatus('connected');
    };
    
    ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      
      if (data.event === 'payment.status_update') {
        setPayments(prev => ({
          ...prev,
          [data.payment.id]: data.payment
        }));
      }
    };
    
    ws.onclose = () => {
      setConnectionStatus('disconnected');
    };
    
    return () => {
      ws.close();
    };
  }, [token]);
  
  return { connectionStatus, payments };
}
```

### Component Usage

```javascript theme={null}
function PaymentTracker({ paymentId, token }) {
  const { connectionStatus, payments } = useTransactionWebSocket(token);
  const payment = payments[paymentId];
  
  if (connectionStatus === 'disconnected') {
    return <div>Connecting to real-time updates...</div>;
  }
  
  if (!payment) {
    return <div>Loading payment...</div>;
  }
  
  return (
    <div>
      <h3>Payment Status: {payment.status}</h3>
      {payment.confirmations && (
        <div>
          Confirmations: {payment.confirmations}/{payment.requiredConfirmations}
        </div>
      )}
    </div>
  );
}
```

## Error Handling

### Connection Errors

```javascript theme={null}
class WebSocketErrorHandler {
  constructor(ws) {
    this.ws = ws;
    this.setupErrorHandling();
  }
  
  setupErrorHandling() {
    this.ws.onerror = (error) => {
      console.error('WebSocket error:', error);
      this.handleError(error);
    };
    
    this.ws.onclose = (event) => {
      if (!event.wasClean) {
        console.error('WebSocket closed unexpectedly:', event.code, event.reason);
        this.handleUnexpectedClose(event);
      }
    };
  }
  
  handleError(error) {
    // Log error for debugging
    console.error('WebSocket error details:', error);
    
    // Attempt to reconnect
    this.attemptReconnect();
  }
  
  handleUnexpectedClose(event) {
    // Handle different close codes
    switch (event.code) {
      case 1006: // Abnormal closure
        this.attemptReconnect();
        break;
      case 1011: // Server error
        this.handleServerError();
        break;
      default:
        this.handleGenericClose(event);
    }
  }
}
```

## Best Practices

### Connection Management

<Steps>
  <Step title="Implement Reconnection">
    Always implement automatic reconnection for production applications.
  </Step>

  <Step title="Handle Connection States">
    Track connection status and show appropriate UI feedback.
  </Step>

  <Step title="Use Heartbeats">
    Implement ping/pong to detect dead connections.
  </Step>

  <Step title="Graceful Degradation">
    Fall back to polling if WebSocket connection fails.
  </Step>
</Steps>

### Performance Optimization

```javascript theme={null}
// Throttle updates to prevent UI flooding
class ThrottledWebSocket extends TransactionWebSocket {
  constructor(token, throttleMs = 1000) {
    super(token);
    this.throttleMs = throttleMs;
    this.updateQueue = [];
    this.throttleTimer = null;
  }
  
  handleMessage(data) {
    this.updateQueue.push(data);
    
    if (!this.throttleTimer) {
      this.throttleTimer = setTimeout(() => {
        this.processUpdateQueue();
        this.throttleTimer = null;
      }, this.throttleMs);
    }
  }
  
  processUpdateQueue() {
    // Process all queued updates
    this.updateQueue.forEach(data => super.handleMessage(data));
    this.updateQueue = [];
  }
}
```

## WebSocket vs Webhooks

<Columns cols={2}>
  <Card title="WebSocket" icon="bolt">
    **Best for:**

    * Real-time UI updates
    * Client-side applications
    * Interactive dashboards
    * Mobile apps

    **Pros:**

    * Real-time updates
    * Low latency
    * Persistent connection
  </Card>

  <Card title="Webhooks" icon="webhook">
    **Best for:**

    * Server-to-server communication
    * Backend processing
    * Reliable delivery
    * Audit trails

    **Pros:**

    * Reliable delivery
    * Retry mechanism
    * Server-side processing
    * Better for critical operations
  </Card>
</Columns>

## Testing WebSocket Connections

### Local Testing

```javascript theme={null}
// Test WebSocket connection locally
function testWebSocketConnection() {
  const ws = new WebSocket('wss://api.transaction.gg/ws?token=test_token');
  
  ws.onopen = () => {
    console.log('✅ WebSocket connected successfully');
  };
  
  ws.onmessage = (event) => {
    console.log('📨 Received message:', JSON.parse(event.data));
  };
  
  ws.onerror = (error) => {
    console.error('❌ WebSocket error:', error);
  };
  
  ws.onclose = (event) => {
    console.log('🔌 WebSocket closed:', event.code, event.reason);
  };
}
```

### Production Monitoring

```javascript theme={null}
// Monitor WebSocket health in production
class WebSocketMonitor {
  constructor(ws) {
    this.ws = ws;
    this.metrics = {
      messagesReceived: 0,
      connectionUptime: 0,
      lastMessageTime: null
    };
    
    this.startMonitoring();
  }
  
  startMonitoring() {
    setInterval(() => {
      this.checkConnectionHealth();
    }, 30000); // Check every 30 seconds
  }
  
  checkConnectionHealth() {
    const now = Date.now();
    const timeSinceLastMessage = now - this.metrics.lastMessageTime;
    
    if (timeSinceLastMessage > 60000) { // 1 minute
      console.warn('No messages received in the last minute');
    }
  }
}
```

<Note>
  **Production Tip:** Use both WebSocket and webhooks for critical applications. WebSocket for real-time UI updates and webhooks for reliable server-side processing.
</Note>
