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

# Pump.fun Account Streaming

> Stream and parse Pump.fun account updates in real-time

Learn how to stream and parse Pump.fun account data using Yellowstone gRPC. This guide demonstrates efficient account monitoring for trading bots, analytics platforms, and real-time DeFi applications.

## Overview

For any Solana dApp, trading bot, or real-time analytics platform, efficient account data access is crucial. Yellowstone gRPC streaming offers a high-performance, low-latency alternative to traditional RPC polling and WebSockets.

<Info>
  **What you'll learn:**

  * Stream all Pump.fun account updates in real-time
  * Decode account data using the program's IDL
  * Track bonding curve and global account changes
  * Build production-ready account monitoring systems
</Info>

## Installation

```bash theme={null}
npm install @triton-one/yellowstone-grpc @coral-xyz/anchor
```

## Complete Working Example

Here's a production-ready Pump.fun account monitor with bonding curve tracking:

```javascript theme={null}
const Client = require("@triton-one/yellowstone-grpc").default;
const { CommitmentLevel } = require("@triton-one/yellowstone-grpc");
const { BorshAccountsCoder } = require("@coral-xyz/anchor");
const fs = require('fs');

const PUMP_PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";

// Load Pump.fun IDL
const pumpFunIdl = JSON.parse(
  fs.readFileSync('./idl/pump_0.1.0.json', 'utf8')
);
const accountCoder = new BorshAccountsCoder(pumpFunIdl);

// Initialize and connect to Yellowstone gRPC
const getClient = async () => {
  let client = false;
  try {
    client = new Client(
      process.env.GRPC_ENDPOINT || "https://grpc.solanatracker.io",
      process.env.GRPC_API_KEY,
      {
        "grpc.max_receive_message_length": 100 * 1024 * 1024,
      }
    );
    const version = await client.getVersion();
    if (version) {
      console.log("Connected to Yellowstone gRPC! Version:", version);
      return client;
    }
  } catch (e) {
    console.error("Failed to connect:", e);
  }
  if (!client) {
    throw new Error("Failed to connect!");
  }
};

// Track account statistics
const stats = {
  totalUpdates: 0,
  bondingCurves: new Set(),
  completedCurves: 0,
  lastReportTime: Date.now()
};

// Handle bonding curve updates
function handleBondingCurve(data, account) {
  stats.bondingCurves.add(account.pubkey);
  
  console.log(`\n[Bonding Curve Update]`);
  console.log(`  Address: ${account.pubkey}`);
  console.log(`  Virtual Token Reserves: ${data.virtualTokenReserves}`);
  console.log(`  Virtual Sol Reserves: ${data.virtualSolReserves}`);
  console.log(`  Real Token Reserves: ${data.realTokenReserves}`);
  console.log(`  Real Sol Reserves: ${data.realSolReserves}`);
  console.log(`  Token Total Supply: ${data.tokenTotalSupply}`);
  console.log(`  Complete: ${data.complete}`);
  
  // Calculate current price
  const price = Number(data.virtualSolReserves) / Number(data.virtualTokenReserves);
  console.log(`  Current Price: ${price.toFixed(9)} SOL/token`);
  
  if (data.complete && !stats.bondingCurves.has(account.pubkey + '_completed')) {
    stats.completedCurves++;
    stats.bondingCurves.add(account.pubkey + '_completed');
    
    console.log(`\n🎉 BONDING CURVE COMPLETED!`);
    console.log(`  Address: ${account.pubkey}`);
    console.log(`  Final Sol Reserves: ${(Number(data.realSolReserves) / 1e9).toFixed(4)} SOL`);
    console.log(`  Token Supply: ${data.tokenTotalSupply}`);
  }
}

// Handle global account updates
function handleGlobalAccount(data, account) {
  console.log(`\n[Global Configuration Update]`);
  console.log(`  Address: ${account.pubkey}`);
  console.log(`  Fee Recipient: ${data.feeRecipient}`);
  console.log(`  Initial Virtual Token Reserves: ${data.initialVirtualTokenReserves}`);
  console.log(`  Initial Virtual Sol Reserves: ${data.initialVirtualSolReserves}`);
}

(async () => {
  const client = await getClient();
  const stream = await client.subscribe();

  // Handle stream lifecycle
  const streamClosed = new Promise((resolve, reject) => {
    stream.on("error", (error) => {
      console.error("Stream error:", error);
    });
    stream.on("end", () => {
      console.log("Stream ended");
      resolve();
    });
    stream.on("close", () => {
      console.log("Stream closed");
      resolve();
    });
  });

  // Handle incoming account updates
  stream.on("data", (data) => {
    if (data?.account) {
      stats.totalUpdates++;
      const accountData = data.account.account;
      
      try {
        // Decode account data
        const decodedData = accountCoder.decodeAny(accountData.data);
        
        console.log(`\n[Account Update #${stats.totalUpdates}]`);
        console.log(`  Address: ${accountData.pubkey}`);
        console.log(`  Type: ${decodedData.discriminator}`);
        console.log(`  Slot: ${data.account.slot}`);
        
        // Process based on account type
        if (decodedData.discriminator === 'BondingCurve') {
          handleBondingCurve(decodedData, accountData);
        } else if (decodedData.discriminator === 'Global') {
          handleGlobalAccount(decodedData, accountData);
        }
      } catch (error) {
        // Ignore decoding errors for unknown account types
      }
      
      // Report statistics every 100 updates
      if (stats.totalUpdates % 100 === 0) {
        const now = Date.now();
        const elapsed = (now - stats.lastReportTime) / 1000;
        const rate = 100 / elapsed;

        console.log(`\n=== Statistics ===`);
        console.log(`  Total Updates: ${stats.totalUpdates}`);
        console.log(`  Update Rate: ${rate.toFixed(2)}/sec`);
        console.log(`  Bonding Curves Tracked: ${stats.bondingCurves.size}`);
        console.log(`  Completed Curves: ${stats.completedCurves}`);

        stats.lastReportTime = now;
      }
    }
  });

  // Subscribe to Pump.fun accounts
  const request = {
    accounts: {
      pumpfun: {
        account: [],
        owner: [PUMP_PROGRAM_ID], // Stream all accounts owned by Pump.fun
        filters: []
      }
    },
    slots: {},
    transactions: {},
    transactionsStatus: {},
    entry: {},
    blocks: {},
    blocksMeta: {},
    accountsDataSlice: [],
    ping: undefined,
    commitment: CommitmentLevel.PROCESSED, // Fastest updates
  };

  // Send subscribe request
  await new Promise((resolve, reject) => {
    stream.write(request, (err) => {
      if (err === null || err === undefined) {
        console.log("✅ Monitoring Pump.fun accounts...\n");
        resolve();
      } else {
        reject(err);
      }
    });
  }).catch((reason) => {
    console.error("Subscribe failed:", reason);
    throw reason;
  });

  await streamClosed;
})();

// Graceful shutdown
process.on('SIGINT', () => {
  console.log('\n\nShutting down gracefully...');
  console.log(`Final Stats - Updates: ${stats.totalUpdates}, Curves: ${stats.bondingCurves.size}, Completed: ${stats.completedCurves}`);
  process.exit(0);
});
```

## Pump.fun Account Types

### Bonding Curve Account

The bonding curve account contains the token economics and liquidity information:

```javascript theme={null}
{
  virtualTokenReserves: bigint,  // Virtual token reserves for pricing
  virtualSolReserves: bigint,    // Virtual SOL reserves for pricing
  realTokenReserves: bigint,     // Actual tokens in the curve
  realSolReserves: bigint,       // Actual SOL in the curve
  tokenTotalSupply: bigint,      // Total token supply
  complete: boolean              // Whether bonding curve is complete
}
```

**Use cases:**

* Calculate current token price
* Monitor liquidity changes
* Detect when bonding curve completes
* Track token supply distribution

### Global Account

The global account contains program-wide configuration:

```javascript theme={null}
{
  feeRecipient: string,                    // Address receiving fees
  initialVirtualTokenReserves: bigint,     // Initial virtual token reserves
  initialVirtualSolReserves: bigint,       // Initial virtual SOL reserves
  initialRealTokenReserves: bigint,        // Initial real token reserves
  tokenTotalSupply: bigint,                // Standard token total supply
  feeBasisPoints: number                   // Fee in basis points
}
```

## Advanced Examples

### Example 2: Track Specific Bonding Curves

Monitor only specific bonding curve addresses:

```javascript theme={null}
const BONDING_CURVES = [
  "BondingCurve1...",
  "BondingCurve2...",
  "BondingCurve3..."
];

const request = {
  accounts: {
    specificCurves: {
      account: BONDING_CURVES, // Monitor specific accounts
      owner: [],
      filters: []
    }
  },
  // ... other fields
  commitment: CommitmentLevel.CONFIRMED,
};
```

### Example 3: Filter for Active Bonding Curves

Filter for incomplete bonding curves only:

```javascript theme={null}
const request = {
  accounts: {
    activeBondingCurves: {
      account: [],
      owner: [PUMP_PROGRAM_ID],
      filters: [
        { dataSize: 120 }, // Bonding curve account size
        {
          memcmp: {
            offset: 108, // Offset to 'complete' field
            bytes: Buffer.from([0]).toString('base64') // Filter for incomplete
          }
        }
      ]
    }
  },
  // ... other fields
  commitment: CommitmentLevel.CONFIRMED,
};
```

### Example 4: Price Tracking

Track price movements across all bonding curves:

```javascript theme={null}
const priceHistory = new Map(); // curve address -> array of prices

function trackPrice(address, virtualSol, virtualToken) {
  const price = Number(virtualSol) / Number(virtualToken);
  
  if (!priceHistory.has(address)) {
    priceHistory.set(address, []);
  }
  
  const history = priceHistory.get(address);
  history.push({ price, timestamp: Date.now() });
  
  // Keep only last 100 prices
  if (history.length > 100) {
    history.shift();
  }
  
  // Calculate price change
  if (history.length > 1) {
    const oldPrice = history[0].price;
    const priceChange = ((price - oldPrice) / oldPrice) * 100;
    
    if (Math.abs(priceChange) > 50) { // 50% change
      console.log(`\n🚨 PRICE ALERT`);
      console.log(`  Curve: ${address}`);
      console.log(`  Change: ${priceChange.toFixed(2)}%`);
      console.log(`  Current Price: ${price.toFixed(9)} SOL`);
    }
  }
}

// Call in handleBondingCurve:
trackPrice(
  account.pubkey,
  data.virtualSolReserves,
  data.virtualTokenReserves
);
```

### Example 5: Liquidity Monitoring

Track liquidity changes:

```javascript theme={null}
const liquidityTracker = new Map(); // curve -> last liquidity

function trackLiquidity(address, realSol) {
  const liquidity = Number(realSol) / 1e9; // Convert to SOL
  const previous = liquidityTracker.get(address);
  
  if (previous) {
    const change = liquidity - previous;
    const percentChange = (change / previous) * 100;
    
    if (Math.abs(percentChange) > 10) { // 10% change
      console.log(`\n💧 LIQUIDITY CHANGE`);
      console.log(`  Curve: ${address}`);
      console.log(`  Current: ${liquidity.toFixed(4)} SOL`);
      console.log(`  Change: ${change > 0 ? '+' : ''}${change.toFixed(4)} SOL (${percentChange.toFixed(1)}%)`);
    }
  }
  
  liquidityTracker.set(address, liquidity);
}
```

## Dynamic Subscription Management

Modify your subscription on-the-fly without restarting:

```javascript theme={null}
async function addCurveToMonitor(stream, bondingCurveAddress) {
  await new Promise((resolve, reject) => {
    stream.write({
      accounts: {
        newCurve: {
          account: [bondingCurveAddress],
          owner: [],
          filters: []
        }
      }
    }, (err) => {
      if (err === null || err === undefined) {
        console.log(`Added ${bondingCurveAddress} to monitoring`);
        resolve();
      } else {
        reject(err);
      }
    });
  });
}
```

## Performance Tips

<CardGroup cols={2}>
  <Card title="Use PROCESSED Commitment" icon="bolt">
    Get updates faster with `CommitmentLevel.PROCESSED` for time-sensitive applications
  </Card>

  <Card title="Filter Efficiently" icon="filter">
    Use dataSize and memcmp filters to reduce bandwidth and processing load
  </Card>

  <Card title="Batch Processing" icon="layer-group">
    Process account updates in batches for better throughput
  </Card>

  <Card title="Cache Account State" icon="database">
    Maintain local cache of account states to detect changes efficiently
  </Card>
</CardGroup>

## Common Use Cases

<Tabs>
  <Tab title="Trading Bot">
    ```javascript theme={null}
    function handleBondingCurve(data, account) {
      // Calculate current price
      const price = Number(data.virtualSolReserves) / Number(data.virtualTokenReserves);
      
      // Check if price is favorable
      if (price < TARGET_PRICE && !data.complete) {
        executeBuy(account.pubkey, AMOUNT);
      }
    }
    ```
  </Tab>

  <Tab title="Analytics Dashboard">
    ```javascript theme={null}
    const analytics = {
      totalLiquidity: 0,
      averagePrice: 0,
      activeCurves: 0
    };

    function trackAnalytics(data) {
      if (!data.complete) {
        analytics.activeCurves++;
        analytics.totalLiquidity += Number(data.realSolReserves);
      }
    }
    ```
  </Tab>

  <Tab title="Alert System">
    ```javascript theme={null}
    function checkAlerts(data, account) {
      const liquidity = Number(data.realSolReserves) / 1e9;
      
      if (liquidity > LARGE_LIQUIDITY_THRESHOLD) {
        sendAlert(`Large bonding curve: ${liquidity.toFixed(2)} SOL`);
      }
      
      if (data.complete) {
        sendAlert(`Bonding curve completed: ${account.pubkey}`);
      }
    }
    ```
  </Tab>
</Tabs>

## IDL File

Download the Pump.fun IDL and save it as `idl/pump_0.1.0.json`:

```json theme={null}
{
  "version": "0.1.0",
  "name": "pump",
  "accounts": [
    {
      "name": "BondingCurve",
      "type": {
        "kind": "struct",
        "fields": [
          { "name": "virtualTokenReserves", "type": "u64" },
          { "name": "virtualSolReserves", "type": "u64" },
          { "name": "realTokenReserves", "type": "u64" },
          { "name": "realSolReserves", "type": "u64" },
          { "name": "tokenTotalSupply", "type": "u64" },
          { "name": "complete", "type": "bool" }
        ]
      }
    },
    {
      "name": "Global",
      "type": {
        "kind": "struct",
        "fields": [
          { "name": "feeRecipient", "type": "publicKey" },
          { "name": "initialVirtualTokenReserves", "type": "u64" },
          { "name": "initialVirtualSolReserves", "type": "u64" }
        ]
      }
    }
  ]
}
```

## Resources

<CardGroup cols={2}>
  <Card title="Best Practices" icon="star" href="/yellowstone-grpc/best-practices">
    Optimize your implementation
  </Card>

  <Card title="Transaction Parsing" icon="receipt" href="/yellowstone-grpc/examples/pumpfun-transactions">
    Detect buy/sell events
  </Card>

  <Card title="Account Monitoring" icon="user" href="/yellowstone-grpc/account-monitoring">
    General account monitoring guide
  </Card>
</CardGroup>
