Solana Tracker

Shred Stream WebSocket API

Stream Solana transactions in real-time directly from the shredstream, receiving transactions as they're gossiped across the network before they're processed. Included for free in all RPC plans.

Connection

Connect to the WebSocket endpoint with your API key like for the regular RPC Websocket:

const ws = new WebSocket('wss://rpc-mainnet.solanatracker.io/?api_key=YOUR_API_KEY');

Important Limitations

Shredstream transactions have significant limitations compared to Yellowstone gRPC or RPC Websockets:

  • No Transaction Metadata: Shreds arrive before transactions are processed, so there is no meta field. This means:

    • No fee information
    • No pre/post balances
    • No inner instructions
    • No logs
    • No compute units consumed
    • No error information
  • Unresolved Address Lookup Tables: Address lookup tables (ALTs) are not expanded. You'll see the lookup table addresses, not the actual accounts they reference.

  • No Confirmation Status: Transactions may still fail during execution. You're seeing them as they're gossiped, not after they're confirmed.

  • Placeholder Values: Some fields like fee will have placeholder values (typically 5000 lamports).

Subscribe to Transactions

Subscribe using the shredSubscribe method with optional filters:

Basic Subscription

ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 1,
  method: "shredSubscribe",
  params: [
    {}, // Empty filter = all transactions
    {
      encoding: "base64",
      transactionDetails: "full",
      maxSupportedTransactionVersion: 0
    }
  ]
}));

Response

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": 123456 // Subscription ID
}

Filters

Filters use AND logic - all specified filter conditions must match for a transaction to be sent.

Filter Fields

accountInclude (OR logic)

At least one of these accounts must be present in the transaction.

{
  accountInclude: [
    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",  // Token Program
    "11111111111111111111111111111111"              // System Program
  ]
}

accountExclude (Rejection filter)

If any of these accounts are present, the transaction is rejected.

{
  accountExclude: [
    "Vote111111111111111111111111111111111111111" // Exclude vote program
  ]
}

accountRequired (AND logic)

All of these accounts must be present in the transaction.

{
  accountRequired: [
    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
    "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
  ]
}

vote

Filter vote transactions.

{ vote: false } // Exclude vote transactions
{ vote: true }  // Only vote transactions

Options

encoding

How transaction data is encoded. Default: "base64"

Options:

  • "base64" - Base64 encoded transaction
  • "json" - JSON parsed transaction (larger response size)
  • "jsonParsed" - JSON with parsed instructions (largest response size)
{
  encoding: "base64"
}

transactionDetails

Level of detail to include. Default: "full"

Options:

  • "full" - Complete transaction with all details
  • "signatures" - Only signatures
  • "accounts" - Only account keys
  • "none" - Minimal details
{
  transactionDetails: "full"
}

maxSupportedTransactionVersion

Support for versioned transactions (v0 transactions with address lookup tables).

{
  maxSupportedTransactionVersion: 0 // Support v0 transactions
}

Even with maxSupportedTransactionVersion: 0, address lookup tables are not resolved in shredstream data.

showRewards

Include block rewards information. Default: false

{
  showRewards: true
}

Complete Examples

Example 1: Monitor Token Program Transactions

Stream all transactions involving the Token Program:

const ws = new WebSocket('wss://your-api.com/?api_key=YOUR_API_KEY');
 
ws.onopen = () => {
  ws.send(JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "shredSubscribe",
    params: [
      {
        accountInclude: ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"]
      },
      {
        encoding: "base64",
        transactionDetails: "full",
        maxSupportedTransactionVersion: 0
      }
    ]
  }));
};
 
ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  
  if (data.method === "shredTransaction") {
    const { signature, slot, transaction } = data.params.result;
    console.log(`New transaction: ${signature} at slot ${slot}`);
  }
};

Example 2: Monitor Specific Wallet

Track all transactions for a specific wallet address:

ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 2,
  method: "shredSubscribe",
  params: [
    {
      accountInclude: ["YourWalletAddress111111111111111111111111"]
    },
    {
      encoding: "jsonParsed",
      transactionDetails: "full",
      maxSupportedTransactionVersion: 0
    }
  ]
}));

Example 3: Monitor DEX with Multiple Programs

Track Raydium transactions (requires both Raydium program and Token Program):

ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 3,
  method: "shredSubscribe",
  params: [
    {
      accountRequired: [
        "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8", // Raydium AMM
        "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"   // Token Program
      ],
      vote: false // Exclude vote transactions
    },
    {
      encoding: "base64",
      transactionDetails: "full",
      maxSupportedTransactionVersion: 0
    }
  ]
}));

Example 4: Exclude Vote Transactions

Stream all non-vote transactions:

ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 4,
  method: "shredSubscribe",
  params: [
    {
      vote: false
    },
    {
      encoding: "base64",
      transactionDetails: "full"
    }
  ]
}));

Example 5: Complex Filter

Monitor Jupiter swaps (include Jupiter program, exclude vote program):

ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 5,
  method: "shredSubscribe",
  params: [
    {
      accountInclude: [
        "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4" // Jupiter v6
      ],
      accountExclude: [
        "Vote111111111111111111111111111111111111111"
      ],
      vote: false
    },
    {
      encoding: "base64",
      transactionDetails: "full",
      maxSupportedTransactionVersion: 0
    }
  ]
}));

Notification Format

When a matching transaction is found, you'll receive a notification:

{
  "jsonrpc": "2.0",
  "method": "shredTransaction",
  "params": {
    "subscription": 123456,
    "result": {
      "signature": "5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7",
      "slot": 280405926,
      "transaction": {
        "transaction": ["base64EncodedData..."],
        "meta": null,
        "version": 0
      }
    }
  }
}

Note: The meta field is always null or a placeholder for shredstream transactions.

Unsubscribe

To stop receiving notifications:

ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 10,
  method: "shredUnsubscribe",
  params: [123456] // Subscription ID from subscribe response
}));

Response:

{
  "jsonrpc": "2.0",
  "id": 10,
  "result": true
}

Best Practices

  1. Use Specific Filters: Avoid subscribing to all transactions - use filters to reduce bandwidth and processing.

  2. Handle Missing Metadata: Don't rely on meta fields. If you need transaction outcomes, fees, or logs, you'll need to fetch the transaction from RPC after confirmation.

  3. Decode Transactions Carefully: With encoding: "base64", you'll need to decode the transaction yourself. Consider using "jsonParsed" for easier parsing.

  4. Monitor Subscription Count: Keep track of your active subscriptions to avoid hitting the 100 subscription limit.

  5. Implement Reconnection Logic: WebSocket connections can drop. Implement automatic reconnection with exponential backoff.

  6. Use Account Filters Efficiently:

    • Use accountInclude for broad matching (OR logic)
    • Use accountRequired when you need multiple specific programs (AND logic)
    • Use accountExclude to filter out unwanted transactions (like vote txs)

Common Use Cases

Pump.Amm Monitoring

{
  accountInclude: [
    "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA"
  ]
}

Error Handling

ws.onerror = (error) => {
  console.error('WebSocket error:', error);
};
 
ws.onclose = (event) => {
  console.log('WebSocket closed:', event.code, event.reason);
  // Implement reconnection logic
};

Performance Considerations

  • Base64 encoding is most efficient for bandwidth
  • jsonParsed encoding is easier to parse but uses more bandwidth
  • Empty filters will stream ALL transactions (very high volume)
  • Use accountInclude to reduce unnecessary traffic
  • Consider batching processing on the client side for high-volume streams

Simple Example

 
const WebSocket = require('ws');
 
const WS_URL = 'wss://rpc-mainnet.solanatracker.io/?api_key=YOUR_API_KEY';
const ACCOUNT = 'pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA';
 
// Connect to WebSocket
const ws = new WebSocket(WS_URL);
 
ws.on('open', () => {
  console.log('Connected to shred stream');
  
  // Subscribe to transactions
  ws.send(JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "shredSubscribe",
    params: [
      {
        accountInclude: [ACCOUNT],
        vote: false  // Exclude vote transactions
      },
      {
        encoding: "jsonParsed",
        transactionDetails: "full",
        maxSupportedTransactionVersion: 0
      }
    ]
  }));
});
 
ws.on('message', (data) => {
  const message = JSON.parse(data);
  
  // Handle transaction notifications
  if (message.method === 'shredTransaction') {
    const { signature, slot, transaction } = message.params.result;
    
    console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    console.log(`New Transaction Detected!`);
    console.log(`Signature: ${signature}`);
    console.log(`Slot: ${slot}`);
    console.log(`Time: ${new Date().toISOString()}`);
    console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
    
    // Note: transaction.meta will be null (shredstream limitation)
  }
});
 
ws.on('error', (error) => {
  console.error('WebSocket error:', error.message);
});
 
ws.on('close', () => {
  console.log('Disconnected from shred stream');
  console.log('Reconnecting in 5 seconds...');
  setTimeout(() => {
    console.log('Restarting...');
    process.exit(1); // Let process manager restart
  }, 5000);
});