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

# Hướng dẫn bắt đầu nhanh với Solana WebSocket

> Bắt đầu sử dụng Solana WebSocket chỉ trong vài phút với hướng dẫn từng bước về giám sát tài khoản, theo dõi giao dịch và xây dựng ứng dụng thời gian thực.

## Hướng dẫn bắt đầu nhanh

<Steps>
  <Step title="Get Your API Key">
    Lấy khóa API Helius từ [bảng điều khiển](https://dashboard.helius.dev). Bạn sẽ cần khóa này để xác thực. Các tác nhân có thể lấy khóa bằng [Helius CLI](/docs/vi/agents/cli).
  </Step>

  <Step title="Choose Your Network">
    Chọn [điểm cuối](https://www.helius.dev/docs/api-reference/endpoints) phù hợp:

    * **Mainnet**: `wss://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY`
    * **Mainnet (Gatekeeper Beta)**: `wss://beta.helius-rpc.com/?api-key=YOUR_API_KEY`
    * **Devnet**: `wss://devnet.helius-rpc.com/?api-key=YOUR_API_KEY`
  </Step>

  <Step title="Create Your First Connection">
    ```javascript theme={"system"}
    const ws = new WebSocket('wss://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY');

    ws.onopen = () => {
      console.log('Connected to Solana!');
    };

    ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      console.log('Received:', data);
    };
    ```
  </Step>

  <Step title="Subscribe to Updates">
    ```javascript theme={"system"}
    // Subscribe to account changes
    const subscribeMessage = {
      "jsonrpc": "2.0",
      "id": 1,
      "method": "accountSubscribe",
      "params": [
        "ACCOUNT_ADDRESS_HERE",
        { "commitment": "confirmed" }
      ]
    };

    ws.send(JSON.stringify(subscribeMessage));
    ```
  </Step>
</Steps>

## Các phương thức đăng ký

### Giám sát tài khoản

Giám sát các tài khoản cụ thể để phát hiện thay đổi số dư, cập nhật dữ liệu hoặc chuyển quyền sở hữu.

<CodeGroup>
  ```javascript Basic Account Subscription theme={"system"}
  const ws = new WebSocket('wss://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY');

  const subscribeToAccount = (accountAddress) => {
    const request = {
      "jsonrpc": "2.0",
      "id": 1,
      "method": "accountSubscribe",
      "params": [
        accountAddress,
        {
          "encoding": "jsonParsed",
          "commitment": "confirmed"
        }
      ]
    };
    
    ws.send(JSON.stringify(request));
  };

  ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    
    if (data.method === "accountNotification") {
      console.log("Account updated:", data.params.result.value);
      
      // Handle the account change
      const accountInfo = data.params.result.value;
      console.log(`New balance: ${accountInfo.lamports} lamports`);
    }
  };

  // Subscribe to a wallet address
  subscribeToAccount("9PejEmViKHgUkVFWN57cNEZnFS4Qo6SzsLj5UPAXfDTF");
  ```

  ```javascript Token Account Monitoring theme={"system"}
  const ws = new WebSocket('wss://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY');

  // Monitor a token account for balance changes
  const monitorTokenAccount = (tokenAccountAddress) => {
    const request = {
      "jsonrpc": "2.0",
      "id": 2,
      "method": "accountSubscribe",
      "params": [
        tokenAccountAddress,
        {
          "encoding": "jsonParsed",
          "commitment": "confirmed"
        }
      ]
    };
    
    ws.send(JSON.stringify(request));
  };

  ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    
    if (data.method === "accountNotification") {
      const accountData = data.params.result.value.data;
      
      if (accountData.program === "spl-token") {
        const parsed = accountData.parsed;
        console.log(`Token balance: ${parsed.info.tokenAmount.uiAmount}`);
        console.log(`Owner: ${parsed.info.owner}`);
      }
    }
  };
  ```
</CodeGroup>

### Giám sát hoạt động của chương trình

Theo dõi tất cả tài khoản thuộc sở hữu của một chương trình — lý tưởng để giám sát giao dịch DEX, chuyển NFT hoặc hoạt động DeFi.

<CodeGroup>
  ```javascript DEX Trade Monitoring theme={"system"}
  // Monitor Raydium AMM for all trade activity
  const RAYDIUM_AMM_PROGRAM = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8";

  const subscribeToProgram = (programId) => {
    const request = {
      "jsonrpc": "2.0",
      "id": 3,
      "method": "programSubscribe",
      "params": [
        programId,
        {
          "encoding": "jsonParsed",
          "commitment": "confirmed",
          "filters": [
            {
              "dataSize": 752 // Raydium pool account size
            }
          ]
        }
      ]
    };
    
    ws.send(JSON.stringify(request));
  };

  ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    
    if (data.method === "programNotification") {
      console.log("Raydium pool updated:", data.params.result.value.pubkey);
      // Process the pool data change
      const accountData = data.params.result.value.account;
      // Parse and handle the pool state change
    }
  };

  subscribeToProgram(RAYDIUM_AMM_PROGRAM);
  ```

  ```javascript NFT Marketplace Monitoring   theme={"system"}
  // Monitor Magic Eden program for NFT activity
  const MAGIC_EDEN_PROGRAM = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";

  const subscribeToNFTActivity = () => {
    const request = {
      "jsonrpc": "2.0",
      "id": 4,
      "method": "programSubscribe",
      "params": [
        MAGIC_EDEN_PROGRAM,
        {
          "encoding": "base64",
          "commitment": "confirmed"
        }
      ]
    };
    
    ws.send(JSON.stringify(request));
  };

  ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    
    if (data.method === "programNotification") {
      console.log("NFT marketplace activity detected");
      // Decode and process the marketplace instruction
      const accountInfo = data.params.result.value;
      // Handle NFT listing, purchase, or cancellation
    }
  };
  ```
</CodeGroup>

### Giám sát giao dịch

Theo dõi các giao dịch cụ thể hoặc giám sát những giao dịch đề cập đến một số tài khoản nhất định.

<CodeGroup>
  ```javascript Transaction Status Tracking theme={"system"}
  // Monitor a specific transaction signature
  const trackTransaction = (signature) => {
    const request = {
      "jsonrpc": "2.0",
      "id": 5,
      "method": "signatureSubscribe",
      "params": [
        signature,
        {
          "commitment": "confirmed"
        }
      ]
    };
    
    ws.send(JSON.stringify(request));
  };

  ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    
    if (data.method === "signatureNotification") {
      const result = data.params.result;
      
      if (result.value.err) {
        console.log("Transaction failed:", result.value.err);
      } else {
        console.log("Transaction confirmed successfully!");
      }
      
      // Subscription automatically ends after notification
    }
  };

  // Track a payment or swap transaction
  trackTransaction("YOUR_TRANSACTION_SIGNATURE_HERE");
  ```

  ```javascript Log-Based Monitoring theme={"system"}
  // Monitor all transactions mentioning a specific address
  const monitorAddress = (address) => {
    const request = {
      "jsonrpc": "2.0",
      "id": 6,
      "method": "logsSubscribe",
      "params": [
        {
          "mentions": [address]
        },
        {
          "commitment": "confirmed"
        }
      ]
    };
    
    ws.send(JSON.stringify(request));
  };

  ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    
    if (data.method === "logsNotification") {
      const logs = data.params.result.value.logs;
      const signature = data.params.result.value.signature;
      
      console.log(`Transaction ${signature} mentioned our address`);
      console.log("Logs:", logs);
      
      // Parse logs for specific events or errors
      if (logs.some(log => log.includes("Program failed"))) {
        console.log("Transaction failed!");
      }
    }
  };

  // Monitor a token mint for all activity
  monitorAddress("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
  ```
</CodeGroup>

## Triển khai sẵn sàng cho môi trường production

Dưới đây là một cách triển khai WebSocket ổn định với logic kết nối lại, xử lý lỗi và quản lý trạng thái phù hợp:

```javascript [expandable] theme={"system"}
class WebSocketManager {
  constructor(endpoint) {
    this.endpoint = endpoint;
    this.ws = null;
    this.subscriptions = new Map();
    this.isConnected = false;
  }

  async connect() {
    this.ws = new WebSocket(this.endpoint);
    
    this.ws.onopen = () => {
      console.log('Connected');
      this.isConnected = true;
      this.resubscribeAll();
    };

    this.ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      
      // Handle subscription confirmations
      if (data.result && typeof data.result === 'number') {
        const sub = Array.from(this.subscriptions.values())
          .find(s => s.requestId === data.id);
        if (sub) sub.subscriptionId = data.result;
        return;
      }

      // Handle notifications
      if (data.method?.endsWith('Notification')) {
        const sub = Array.from(this.subscriptions.values())
          .find(s => s.subscriptionId === data.params.subscription);
        if (sub?.callback) sub.callback(data.params.result);
      }
    };

    this.ws.onclose = () => {
      console.log('Disconnected');
      this.isConnected = false;
      // Implement reconnection logic here
    };
  }

  subscribe(method, params, callback) {
    const requestId = Date.now();
    const subscription = { requestId, method, params, callback, subscriptionId: null };
    this.subscriptions.set(requestId, subscription);
    
    if (this.isConnected) {
      this.ws.send(JSON.stringify({
        jsonrpc: '2.0',
        id: requestId,
        method,
        params
      }));
    }
    
    return requestId;
  }

  resubscribeAll() {
    for (const [id, sub] of this.subscriptions) {
      sub.subscriptionId = null;
      this.ws.send(JSON.stringify({
        jsonrpc: '2.0',
        id,
        method: sub.method,
        params: sub.params
      }));
    }
  }
}

// Usage
const wsManager = new WebSocketManager('wss://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY');
await wsManager.connect();

// Subscribe to account changes
wsManager.subscribe(
  'accountSubscribe',
  ['account-address-here', { commitment: 'confirmed' }],
  (data) => console.log('Account updated:', data)
);
```

## Khám phá thêm các phương thức WebSocket

Các ví dụ trên đề cập đến những loại đăng ký được sử dụng phổ biến nhất, nhưng API WebSocket của Solana còn cung cấp nhiều phương thức khác cho các nhu cầu giám sát chuyên biệt.

<Card title="Complete WebSocket API Reference" icon="book" href="/docs/vi/api-reference/rpc/websocket-methods">
  **Khám phá hơn 18 phương thức WebSocket** cùng tài liệu chi tiết, tham số và định dạng phản hồi.
</Card>

## Các trường hợp sử dụng thực tế

### Bảng điều khiển giao dịch DeFi

```javascript [expandable] theme={"system"}
class LiquidityPoolMonitor {
  constructor(wsManager) {
    this.wsManager = wsManager;
    this.pools = new Map();
  }

  monitorPool(poolAddress, tokenAMint, tokenBMint) {
    // Monitor the pool account itself
    const poolSubscription = this.wsManager.subscribe(
      'accountSubscribe',
      [poolAddress, { encoding: 'base64', commitment: 'confirmed' }],
      (data) => this.handlePoolUpdate(poolAddress, data)
    );

    // Monitor token reserves
    const tokenASubscription = this.wsManager.subscribe(
      'accountSubscribe', 
      [tokenAMint, { encoding: 'jsonParsed', commitment: 'confirmed' }],
      (data) => this.handleReserveUpdate(poolAddress, 'tokenA', data)
    );

    const tokenBSubscription = this.wsManager.subscribe(
      'accountSubscribe',
      [tokenBMint, { encoding: 'jsonParsed', commitment: 'confirmed' }],
      (data) => this.handleReserveUpdate(poolAddress, 'tokenB', data)
    );

    this.pools.set(poolAddress, {
      poolSubscription,
      tokenASubscription, 
      tokenBSubscription,
      lastUpdate: Date.now()
    });
  }

  handlePoolUpdate(poolAddress, data) {
    // Decode pool state and calculate price
    const poolState = this.decodePoolState(data.value.data);
    
    console.log(`Pool ${poolAddress} updated:`);
    console.log(`- Price: ${poolState.price}`);
    console.log(`- Liquidity: ${poolState.liquidity}`);
    console.log(`- Volume 24h: ${poolState.volume24h}`);
    
    // Emit price update event
    this.emitPriceUpdate(poolAddress, poolState);
  }

  handleReserveUpdate(poolAddress, tokenType, data) {
    const tokenAmount = data.value.data.parsed.info.tokenAmount;
    console.log(`${tokenType} reserve updated: ${tokenAmount.uiAmount}`);
    
    // Update internal state and recalculate price
    this.updatePoolPrice(poolAddress, tokenType, tokenAmount);
  }

  decodePoolState(data) {
    // Implement pool state decoding based on DEX
    // This is pseudo-code - actual implementation depends on the DEX
    return {
      price: 0,
      liquidity: 0,
      volume24h: 0
    };
  }

  emitPriceUpdate(poolAddress, poolState) {
    // Emit custom events for price updates
    window.dispatchEvent(new CustomEvent('poolPriceUpdate', {
      detail: { poolAddress, ...poolState }
    }));
  }
}

// Usage
const poolMonitor = new LiquidityPoolMonitor(wsManager);
poolMonitor.monitorPool(
  'POOL_ADDRESS',
  'TOKEN_A_MINT', 
  'TOKEN_B_MINT'
);
```

### Công cụ theo dõi danh mục đầu tư

```javascript [expandable] theme={"system"}
class PortfolioTracker {
  constructor(wsManager) {
    this.wsManager = wsManager;
    this.watchedAddresses = new Set();
    this.balances = new Map();
  }

  addWallet(walletAddress) {
    if (this.watchedAddresses.has(walletAddress)) return;

    this.watchedAddresses.add(walletAddress);
    
    // Monitor SOL balance
    const solSubscription = this.wsManager.subscribe(
      'accountSubscribe',
      [walletAddress, { encoding: 'jsonParsed', commitment: 'confirmed' }],
      (data) => this.handleSolBalanceUpdate(walletAddress, data)
    );

    // Monitor all token accounts owned by this wallet
    const tokenSubscription = this.wsManager.subscribe(
      'programSubscribe',
      [
        'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
        {
          encoding: 'jsonParsed',
          commitment: 'confirmed',
          filters: [
            { memcmp: { offset: 32, bytes: walletAddress } }
          ]
        }
      ],
      (data) => this.handleTokenBalanceUpdate(walletAddress, data)
    );

    console.log(`Now tracking portfolio for ${walletAddress}`);
  }

  handleSolBalanceUpdate(walletAddress, data) {
    const lamports = data.value.lamports;
    const solBalance = lamports / 1e9;
    
    this.balances.set(`${walletAddress}:SOL`, solBalance);
    
    console.log(`${walletAddress} SOL balance: ${solBalance}`);
    this.emitBalanceUpdate(walletAddress, 'SOL', solBalance);
  }

  handleTokenBalanceUpdate(walletAddress, data) {
    const tokenData = data.value.account.data.parsed.info;
    const tokenMint = tokenData.mint;
    const balance = parseFloat(tokenData.tokenAmount.uiAmount);
    
    this.balances.set(`${walletAddress}:${tokenMint}`, balance);
    
    console.log(`${walletAddress} token ${tokenMint} balance: ${balance}`);
    this.emitBalanceUpdate(walletAddress, tokenMint, balance);
  }

  emitBalanceUpdate(walletAddress, asset, balance) {
    window.dispatchEvent(new CustomEvent('balanceUpdate', {
      detail: { walletAddress, asset, balance, timestamp: Date.now() }
    }));
  }

  getPortfolioValue(walletAddress) {
    // Calculate total portfolio value in USD
    // This would integrate with price feeds
    let totalValue = 0;
    
    for (const [key, balance] of this.balances) {
      if (key.startsWith(walletAddress)) {
        const asset = key.split(':')[1];
        const price = this.getAssetPrice(asset); // Implement price lookup
        totalValue += balance * price;
      }
    }
    
    return totalValue;
  }
}
```

### Tích hợp sàn giao dịch NFT

```javascript [expandable] theme={"system"}
class NFTActivityMonitor {
  constructor(wsManager) {
    this.wsManager = wsManager;
    this.watchedCollections = new Map();
  }

  monitorCollection(collectionAddress, options = {}) {
    const { includeListings = true, includeSales = true, includeCancellations = true } = options;

    // Monitor the collection's update authority or creator address
    const collectionSubscription = this.wsManager.subscribe(
      'logsSubscribe',
      [
        { mentions: [collectionAddress] },
        { commitment: 'confirmed' }
      ],
      (data) => this.handleCollectionActivity(collectionAddress, data)
    );

    this.watchedCollections.set(collectionAddress, {
      subscription: collectionSubscription,
      options,
      stats: {
        listings: 0,
        sales: 0,
        volume: 0
      }
    });

    console.log(`Monitoring NFT collection: ${collectionAddress}`);
  }

  handleCollectionActivity(collectionAddress, data) {
    const logs = data.value.logs;
    const signature = data.value.signature;

    // Parse marketplace-specific logs
    const activity = this.parseMarketplaceActivity(logs);
    
    if (activity) {
      console.log(`NFT Activity in ${collectionAddress}:`);
      console.log(`- Type: ${activity.type}`);
      console.log(`- Price: ${activity.price} SOL`);
      console.log(`- Signature: ${signature}`);

      // Update collection stats
      this.updateCollectionStats(collectionAddress, activity);
      
      // Emit activity event
      this.emitNFTActivity(collectionAddress, activity, signature);
    }
  }

  parseMarketplaceActivity(logs) {
    // Parse Magic Eden, OpenSea, or other marketplace logs
    for (const log of logs) {
      // Magic Eden listing
      if (log.includes('Instruction: List')) {
        const price = this.extractPriceFromLog(log);
        return { type: 'listing', price };
      }
      
      // Magic Eden sale
      if (log.includes('Instruction: ExecuteSale')) {
        const price = this.extractPriceFromLog(log);
        return { type: 'sale', price };
      }
      
      // Listing cancellation
      if (log.includes('Instruction: CancelBuy') || log.includes('Instruction: CancelSell')) {
        return { type: 'cancellation', price: 0 };
      }
    }
    
    return null;
  }

  extractPriceFromLog(log) {
    // Extract price from marketplace logs - implementation depends on marketplace
    // This is pseudo-code
    const priceMatch = log.match(/price:\s*(\d+)/);
    return priceMatch ? parseInt(priceMatch[1]) / 1e9 : 0;
  }

  updateCollectionStats(collectionAddress, activity) {
    const collection = this.watchedCollections.get(collectionAddress);
    if (!collection) return;

    switch (activity.type) {
      case 'listing':
        collection.stats.listings++;
        break;
      case 'sale':
        collection.stats.sales++;
        collection.stats.volume += activity.price;
        break;
    }
  }

  emitNFTActivity(collectionAddress, activity, signature) {
    window.dispatchEvent(new CustomEvent('nftActivity', {
      detail: {
        collection: collectionAddress,
        activity,
        signature,
        timestamp: Date.now()
      }
    }));
  }
}
```

### Ví dụ tích hợp React

```javascript [expandable] theme={"system"}
import React, { useEffect, useState } from 'react';

function WebSocketComponent() {
  const [accountData, setAccountData] = useState(null);
  const [wsManager, setWsManager] = useState(null);

  useEffect(() => {
    // Initialize WebSocket
    const manager = new WebSocketManager('wss://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY');
    
    manager.connect().then(() => {
      // Subscribe to account changes
      manager.subscribe(
        'accountSubscribe',
        ['account-address-here', { commitment: 'confirmed' }],
        (data) => setAccountData(data)
      );
    });

    setWsManager(manager);

    // Cleanup on unmount
    return () => {
      if (manager) manager.disconnect();
    };
  }, []);

  return (
    <div>
      <h3>Account Monitor</h3>
      {accountData ? (
        <div>
          <p>Balance: {accountData.value.lamports} lamports</p>
          <p>Owner: {accountData.value.owner}</p>
        </div>
      ) : (
        <p>Waiting for account updates...</p>
      )}
    </div>
  );
}
```

## Tối ưu hóa hiệu suất

<Tabs>
  <Tab title="Connection Management">
    ```javascript [expandable] theme={"system"}
    // Use connection pooling for multiple subscriptions
    class WebSocketPool {
      constructor(endpoint, maxConnections = 3) {
        this.endpoint = endpoint;
        this.connections = [];
        this.maxConnections = maxConnections;
        this.currentConnectionIndex = 0;
      }
      
      async getConnection() {
        if (this.connections.length < this.maxConnections) {
          const wsManager = new SolanaWebSocketManager(this.endpoint);
          await wsManager.connect();
          this.connections.push(wsManager);
          return wsManager;
        }
        
        // Round-robin selection
        const connection = this.connections[this.currentConnectionIndex];
        this.currentConnectionIndex = (this.currentConnectionIndex + 1) % this.connections.length;
        return connection;
      }
    }
    ```
  </Tab>

  <Tab title="Memory Management">
    ```javascript [expandable] theme={"system"}
    // Implement subscription cleanup and memory management
    class ManagedWebSocket extends SolanaWebSocketManager {
      constructor(endpoint, options = {}) {
        super(endpoint, options);
        this.maxSubscriptions = options.maxSubscriptions || 100;
        this.subscriptionHistory = [];
      }
      
      subscribe(method, params, callback) {
        // Check subscription limit
        if (this.subscriptions.size >= this.maxSubscriptions) {
          this.cleanupOldSubscriptions();
        }
        
        const requestId = super.subscribe(method, params, callback);
        
        // Track subscription for cleanup
        this.subscriptionHistory.push({
          requestId,
          timestamp: Date.now(),
          method
        });
        
        return requestId;
      }
      
      cleanupOldSubscriptions() {
        // Remove oldest 10% of subscriptions
        const toRemove = Math.floor(this.subscriptions.size * 0.1);
        const sortedHistory = this.subscriptionHistory
          .sort((a, b) => a.timestamp - b.timestamp);
        
        for (let i = 0; i < toRemove && i < sortedHistory.length; i++) {
          const sub = sortedHistory[i];
          this.unsubscribe(sub.requestId);
          
          // Remove from history
          this.subscriptionHistory = this.subscriptionHistory
            .filter(s => s.requestId !== sub.requestId);
        }
      }
    }
    ```
  </Tab>
</Tabs>

## Xử lý lỗi và gỡ lỗi

<Info>
  Xử lý lỗi ổn định là yếu tố thiết yếu đối với các ứng dụng WebSocket trong môi trường production. Hãy triển khai những mẫu này để xử lý sự cố mạng, giới hạn tốc độ và lỗi API một cách phù hợp.
</Info>

```javascript [expandable] theme={"system"}
class ErrorHandlingWebSocket extends SolanaWebSocketManager {
  constructor(endpoint, options = {}) {
    super(endpoint, options);
    this.errorCounts = new Map();
    this.maxErrorsPerMinute = options.maxErrorsPerMinute || 10;
  }

  handleMessage(data) {
    try {
      // Handle rate limiting
      if (data.error && data.error.code === 429) {
        console.warn('Rate limited, backing off...');
        this.handleRateLimit();
        return;
      }

      // Handle subscription errors
      if (data.error && data.error.code === -32602) {
        console.error('Invalid subscription parameters:', data.error.message);
        this.handleInvalidSubscription(data.id);
        return;
      }

      // Handle network errors
      if (data.error && data.error.code === -32603) {
        console.error('Internal server error:', data.error.message);
        this.handleServerError();
        return;
      }

      super.handleMessage(data);
    } catch (error) {
      console.error('Error processing WebSocket message:', error);
      this.incrementErrorCount('message_processing');
    }
  }

  handleRateLimit() {
    // Exponential backoff for rate limiting
    const backoffDelay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
    
    setTimeout(() => {
      if (this.subscriptions.size > 0) {
        console.log('Retrying after rate limit...');
        this.resubscribeAll();
      }
    }, backoffDelay);
  }

  handleInvalidSubscription(requestId) {
    // Remove invalid subscription
    const subscription = Array.from(this.subscriptions.entries())
      .find(([id, sub]) => sub.requestId === requestId);
    
    if (subscription) {
      console.warn(`Removing invalid subscription: ${subscription[1].method}`);
      this.subscriptions.delete(subscription[0]);
    }
  }

  handleServerError() {
    // Log server error and potentially switch endpoints
    this.incrementErrorCount('server_error');
    
    if (this.getErrorCount('server_error') > 5) {
      console.error('Too many server errors, consider switching endpoints');
      this.eventEmitter.dispatchEvent(new CustomEvent('tooManyServerErrors'));
    }
  }

  incrementErrorCount(errorType) {
    const now = Date.now();
    const errors = this.errorCounts.get(errorType) || [];
    
    // Add current error
    errors.push(now);
    
    // Remove errors older than 1 minute
    const oneMinuteAgo = now - 60000;
    const recentErrors = errors.filter(timestamp => timestamp > oneMinuteAgo);
    
    this.errorCounts.set(errorType, recentErrors);
    
    // Check if we're exceeding error threshold
    if (recentErrors.length > this.maxErrorsPerMinute) {
      console.error(`Too many ${errorType} errors in the last minute`);
      this.eventEmitter.dispatchEvent(new CustomEvent('errorThresholdExceeded', {
        detail: { errorType, count: recentErrors.length }
      }));
    }
  }

  getErrorCount(errorType) {
    const errors = this.errorCounts.get(errorType) || [];
    const oneMinuteAgo = Date.now() - 60000;
    return errors.filter(timestamp => timestamp > oneMinuteAgo).length;
  }
}
```

## Các bước tiếp theo

<CardGroup cols={2}>
  <Card title="API Reference" icon="code" href="/docs/vi/api-reference/rpc/websocket-methods">
    Tài liệu đầy đủ cho tất cả phương thức đăng ký WebSocket
  </Card>

  <Card title="WebSocket Overview" icon="signal-stream" href="/docs/vi/rpc/websocket">
    Khám phá các đăng ký Helius WebSocket, bao gồm `transactionSubscribe` và các bộ lọc `accountSubscribe` nâng cao
  </Card>

  <Card title="LaserStream" icon="bolt" href="/docs/vi/laserstream">
    Nâng cấp lên LaserStream để truyền phát dữ liệu siêu nhanh với khả năng phát lại dữ liệu lịch sử
  </Card>

  <Card title="LaserStream Guide" icon="book" href="/docs/vi/laserstream/guides/account-subscription">
    Tìm hiểu cách truyền phát các bản cập nhật tài khoản theo thời gian thực bằng LaserStream
  </Card>
</CardGroup>

Nếu có câu hỏi hoặc cần hỗ trợ thêm, hãy tham gia [cộng đồng Discord](https://discord.com/invite/6GXdee3gBj), nơi đội ngũ của chúng tôi và các thành viên cộng đồng luôn sẵn sàng trợ giúp!
