Websocket - Data Stream Documentation

The Websocket API is only available for Premium, Business and Enterprise plans. With the Websocket API you can stream: Parsed transactions (per pair or for a wallet), receive new pools/tokens, price updates and more.

This document provides information on how to use the WebSocket and the various room types available for WebSocket communication.

WebSocketService Class

Below is the WebSocketService class that can be used to establish WebSocket connections and manage room subscriptions:

import EventEmitter from "eventemitter3";
 
class WebSocketService {
  constructor(wsUrl) {
    this.wsUrl = wsUrl;
    this.socket = null;
    this.transactionSocket = null;
    this.reconnectAttempts = 0;
    this.reconnectDelay = 2500;
    this.reconnectDelayMax = 4500;
    this.randomizationFactor = 0.5;
    this.emitter = new EventEmitter();
    this.subscribedRooms = new Set();
    this.transactions = new Set();
 
    this.connect();
 
    if (typeof window !== "undefined") {
      window.addEventListener("beforeunload", this.disconnect.bind(this));
    }
  }
 
  async connect() {
    if (this.socket && this.transactionSocket) {
      return;
    }
 
    try {
      this.socket = new WebSocket(this.wsUrl);
      this.transactionSocket = new WebSocket(this.wsUrl);
 
      this.setupSocketListeners(this.socket, "main");
      this.setupSocketListeners(this.transactionSocket, "transaction");
    } catch (e) {
      console.error("Error connecting to WebSocket:", e);
      this.reconnect();
    }
  }
 
  setupSocketListeners(socket, type) {
    socket.onopen = () => {
      console.log(`Connected to ${type} WebSocket server`);
      this.reconnectAttempts = 0;
      this.resubscribeToRooms();
    };
 
    socket.onclose = () => {
      console.log(`Disconnected from ${type} WebSocket server`);
      if (type === "main") this.socket = null;
      if (type === "transaction") this.transactionSocket = null;
      this.reconnect();
    };
 
    socket.onmessage = (event) => {
      try {
        const message = JSON.parse(event.data);
        if (message.type === "message") {
          if (message.data?.tx && this.transactions.has(message.data.tx)) {
            return;
          } else if (message.data?.tx) {
            this.transactions.add(message.data.tx);
          }
          if (message.room.includes('price:')) {
            this.emitter.emit(`price-by-token:${message.data.token}`, message.data);
          }
          this.emitter.emit(message.room, message.data);
        }
      } catch (error) {
        console.error("Error processing message:", error);
      }
    };
  }
 
  disconnect() {
    if (this.socket) {
      this.socket.close();
      this.socket = null;
    }
    if (this.transactionSocket) {
      this.transactionSocket.close();
      this.transactionSocket = null;
    }
    this.subscribedRooms.clear();
    this.transactions.clear();
  }
 
  reconnect() {
    console.log("Reconnecting to WebSocket server");
    const delay = Math.min(
      this.reconnectDelay * Math.pow(2, this.reconnectAttempts),
      this.reconnectDelayMax
    );
    const jitter = delay * this.randomizationFactor;
    const reconnectDelay = delay + Math.random() * jitter;
 
    setTimeout(() => {
      this.reconnectAttempts++;
      this.connect();
    }, reconnectDelay);
  }
 
  joinRoom(room) {
    this.subscribedRooms.add(room);
    const socket = room.includes("transaction")
      ? this.transactionSocket
      : this.socket;
    if (socket && socket.readyState === WebSocket.OPEN) {
      socket.send(JSON.stringify({ type: "join", room }));
    }
  }
 
  leaveRoom(room) {
    this.subscribedRooms.delete(room);
    const socket = room.includes("transaction")
      ? this.transactionSocket
      : this.socket;
    if (socket && socket.readyState === WebSocket.OPEN) {
      socket.send(JSON.stringify({ type: "leave", room }));
    }
  }
 
  on(room, listener) {
    this.emitter.on(room, listener);
  }
 
  off(room, listener) {
    this.emitter.off(room, listener);
  }
 
  getSocket() {
    return this.socket;
  }
 
  resubscribeToRooms() {
    if (
      this.socket &&
      this.socket.readyState === WebSocket.OPEN &&
      this.transactionSocket &&
      this.transactionSocket.readyState === WebSocket.OPEN
    ) {
      for (const room of this.subscribedRooms) {
        const socket = room.includes("transaction")
          ? this.transactionSocket
          : this.socket;
        socket.send(JSON.stringify({ type: "join", room }));
      }
    }
  }
}
 
export default WebSocketService;

Room Types and Usage

The WebSocketService supports various room types for different purposes. Here’s a breakdown of the available rooms:

Room Types

  1. Latest Tokens/Pools
    • Room Name: latest
    • Description: Receive updates about the latest tokens and pools.
{
  "token": {
    "name": "Token Name",
    "symbol": "DANCE",
    "mint": "AmJaZvdNptvofC4qe3tvuBNgqLm65p1of5pk6JFHpump",
    "uri": "https://cf-ipfs.com/ipfs/QmVrh4ER81fns3S4QU48WiBuhiusc1KsCxsM8mSs1bEGPv",
    "decimals": 6,
    "hasFileMetaData": true,
    "createdOn": "https://pump.fun"
  },
  "pools": [
    {
      "liquidity": {
        "quote": 62,
        "usd": 8907.761583907999
      },
      "price": {
        "quote": 2.9853991922957425e-8,
        "usd": 0.000004289229715768062
      },
      "tokenSupply": 1000000000000000,
      "lpBurn": 100,
      "tokenAddress": "AmJaZvdNptvofC4qe3tvuBNgqLm65p1of5pk6JFHpump",
      "marketCap": {
        "quote": 29.853991922957423,
        "usd": 4289.229715768061
      },
      "decimals": 6,
      "security": {
        "freezeAuthority": null,
        "mintAuthority": null
      },
      "quoteToken": "So11111111111111111111111111111111111111112",
      "market": "pumpfun",
      "deployer": "4Rz5xqikxtZ2s7wE9uQ6n2oLXQi6K65XGoYpKxf24Hqo",
      "openTime": 0,
      "poolId": "GmJaZvdNptvofC4qe3tvuBNgqLm65p1of5pk6JFHpump"
    }
  ],
  "events": {
    "30m": {
      "priceChangePercentage": 0
    },
    "1h": {
      "priceChangePercentage": 0
    },
    "4h": {
      "priceChangePercentage": 0
    },
    "24h": {
      "priceChangePercentage": 0
    }
  },
  "risk": {
    "rugged": false,
    "risks": [
      {
        "name": "No social media",
        "description": "This token has no social media links",
        "level": "warning",
        "score": 2000
      },
      {
        "name": "Pump.fun contracts can be changed at any time",
        "description": "Pump.fun contracts can be changed by Pump.fun at any time",
        "level": "warning",
        "score": 10
      },
      {
        "name": "Bonding curve not complete",
        "description": "No raydium liquidity pool, bonding curve not complete",
        "level": "warning",
        "score": 4000
      }
    ],
    "score": 5
  }
}
  1. Pool Changes

    • Room Name: pool:poolId
    • Description: Receive updates about changes in a specific pool.

    Example Response

{
  "liquidity": {
    "quote": 62.280000004,
    "usd": 8947.990185184213
  },
  "price": {
    "quote": 3.012424976894315e-8,
    "usd": 0.000004328058626384536
  },
  "tokenSupply": 1000000000000000,
  "lpBurn": 100,
  "tokenAddress": "HCuFjMcDaSNAyT6mXegLXvrYdBZdT4Xh1YajS8vrpump",
  "marketCap": {
    "quote": 30.124249768943148,
    "usd": 4328.058626384535
  },
  "decimals": 6,
  "security": {
    "freezeAuthority": null,
    "mintAuthority": null
  },
  "quoteToken": "So11111111111111111111111111111111111111112",
  "market": "pumpfun",
  "deployer": "EB58aFKZ3bXSFcPvVNDB9P5QXaG1AiMykmsNo6XmsV4Y",
  "lastUpdated": 1723727796824,
  "createdAt": 1723727770351,
  "poolId": "HCuFjMcDaSNAyT6mXegLXvrYdBZdT4Xh1YajS8vrpump"
}
  1. Pair Transactions
    • Room Name: transaction:tokenAddress:poolId
    • Description: Receive updates about the latest transactions for a specific token pair.

Example Response Returns an array of transactions, can contain 1 or more transactions.

[
  {
    "tx": "2BN6pJ2zJE4cVerXxeBxbRCMZ8ZzcpPmEeBmoB2gESLRxeNNShxtyhKRhDZST6QcWuYBQWf6dJxV4TVQMHJ85fs",
    "amount": 946904.652554,
    "priceUsd": 0.000007945268449484616,
    "volume": 7.625805739043482,
    "type": "sell",
    "wallet": "orcACRJYTFjTeo2pV8TfYRTpmqfoYgbVi9GeANXTCc8",
    "time": 1723728022856,
    "program": "pump"
  },
  {
    "tx": "2BN6pJ2zJE4cVerXxeBxbRCMZ8ZzcpPmEeBmoB2gESLRxeNNShxtyhKRhDZST6QcWuYBQWf6dJxV4TVQMHJ85fs",
    "amount": 946904.652554,
    "priceUsd": 0.000007945268449484616,
    "volume": 7.625805739043482,
    "type": "sell",
    "wallet": "orcACRJYTFjTeo2pV8TfYRTpmqfoYgbVi9GeANXTCc8",
    "time": 1723728022861,
    "program": "pump"
  }
]
  1. Transactions
    • Room Name: transaction:tokenAddress
    • Description: Receive updates about the latest transactions for a specific token.

Example Response Returns an array of transactions, can contain 1 or more transactions.

[
  {
    "tx": "2BN6pJ2zJE4cVerXxeBxbRCMZ8ZzcpPmEeBmoB2gESLRxeNNShxtyhKRhDZST6QcWuYBQWf6dJxV4TVQMHJ85fs",
    "amount": 946904.652554,
    "priceUsd": 0.000007945268449484616,
    "volume": 7.625805739043482,
    "type": "sell",
    "wallet": "orcACRJYTFjTeo2pV8TfYRTpmqfoYgbVi9GeANXTCc8",
    "time": 1723728022856,
    "program": "pump"
  },
  {
    "tx": "2BN6pJ2zJE4cVerXxeBxbRCMZ8ZzcpPmEeBmoB2gESLRxeNNShxtyhKRhDZST6QcWuYBQWf6dJxV4TVQMHJ85fs",
    "amount": 946904.652554,
    "priceUsd": 0.000007945268449484616,
    "volume": 7.625805739043482,
    "type": "sell",
    "wallet": "orcACRJYTFjTeo2pV8TfYRTpmqfoYgbVi9GeANXTCc8",
    "time": 1723728022861,
    "program": "pump"
  }
]
  1. Pair and Wallet Transactions
    • Room Name: transaction:tokenAddress:poolId:wallet
    • Description: Receive updates about the latest transactions for a specific token pair and wallet.

Example Response Returns an array of transactions, can contain 1 or more transactions.

[
  {
    "tx": "2BN6pJ2zJE4cVerXxeBxbRCMZ8ZzcpPmEeBmoB2gESLRxeNNShxtyhKRhDZST6QcWuYBQWf6dJxV4TVQMHJ85fs",
    "amount": 946904.652554,
    "priceUsd": 0.000007945268449484616,
    "volume": 7.625805739043482,
    "type": "sell",
    "wallet": "orcACRJYTFjTeo2pV8TfYRTpmqfoYgbVi9GeANXTCc8",
    "time": 1723728022856,
    "program": "pump"
  },
  {
    "tx": "2BN6pJ2zJE4cVerXxeBxbRCMZ8ZzcpPmEeBmoB2gESLRxeNNShxtyhKRhDZST6QcWuYBQWf6dJxV4TVQMHJ85fs",
    "amount": 946904.652554,
    "priceUsd": 0.000007945268449484616,
    "volume": 7.625805739043482,
    "type": "sell",
    "wallet": "orcACRJYTFjTeo2pV8TfYRTpmqfoYgbVi9GeANXTCc8",
    "time": 1723728022861,
    "program": "pump"
  }
]
  1. Price Updates
    • Room Name: price:poolId or price-by-token:tokenId
    • Description: Receive price updates for a specific pool or token

Example response

{
  "price": 0.000008006158441370585,
  "pool": "EWiYmq3nWQpoTkcU4UfGYEoYvDHduDsXhpPvqmoqpump",
  "token": "EWiYmq3nWQpoTkcU4UfGYEoYvDHduDsXhpPvqmoqpump",
  "time": 1723728065246
}
  1. Wallet Transactions
    • Room Name: wallet:walletAddress
    • Description: Receive updates about transactions for a specific wallet.

Example response

{
  "tx": "5zdzU3ShXomxL8c7EoknkzSzke4xGoRvcUHQe2kkSX2kVh5W5RToasEJCDcPg1n7eq2sXW5nqJQzTAX9tiWtkkdL-jup1",
  "from": {
    "address": "2QfkDa6p4cJtUmzwf6yZ9YSUrfvFzW52BpEmGZ7YibnH",
    "amount": 26818.398267,
    "token": {
      "name": "Trump 2024",
      "symbol": "Trump",
      "image": "https://image.solanatracker.io/proxy?=https%3A%2F%2Fimage.solanatracker.io%2Fproxy%3Furl%3Dhttps%253A%252F%252Fipfs-forward.solanatracker.io%252Fipfs%252FQmVpn8VqxmXynEcMJt9hupctAqUWcfci1n7YZPHXFT2Fvu",
      "decimals": 6
    }
  },
  "to": {
    "address": "So11111111111111111111111111111111111111112",
    "amount": 0.000007249,
    "token": {
      "name": "Wrapped SOL",
      "symbol": "SOL",
      "image": "https://image.solanatracker.io/proxy?url=https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png",
      "decimals": 9
    }
  },
  "wallet": "5Er9zJ1VJRyqU8cYrqCjan8vXtMMfhBmkBff7m2fdEsS",
  "type": "buy",
  "time": 1725269187701,
  "price": { "quote": 0.000007548017247183529, "usd": 0.0009806094852284164 },
  "volume": { "usd": 0.0009390480358769071, "sol": 0.000007249 },
  "program": "jupiter",
  "pools": ["HC7Ycaq9GDzoTFcxQVtCATdpLgJE93idYiFsJpNwDGMB"]
}
  1. Graduating
    • Room Name: graduating or set a market cap like this: graduating:sol:170 (this will send a websocket message when market cap reaches 170 SOL)
    • Description: Receive latest graduating tokens, graduating means tokens that are close to completing their bonding curve on pumpfun / moonshot
{
  "token": {
    "name": "Token Name",
    "symbol": "DANCE",
    "mint": "AmJaZvdNptvofC4qe3tvuBNgqLm65p1of5pk6JFHpump",
    "uri": "https://cf-ipfs.com/ipfs/QmVrh4ER81fns3S4QU48WiBuhiusc1KsCxsM8mSs1bEGPv",
    "decimals": 6,
    "hasFileMetaData": true,
    "createdOn": "https://pump.fun"
  },
  "pools": [
    {
      "liquidity": {
        "quote": 62,
        "usd": 8907.761583907999
      },
      "price": {
        "quote": 2.9853991922957425e-8,
        "usd": 0.000004289229715768062
      },
      "tokenSupply": 1000000000000000,
      "lpBurn": 100,
      "tokenAddress": "AmJaZvdNptvofC4qe3tvuBNgqLm65p1of5pk6JFHpump",
      "marketCap": {
        "quote": 29.853991922957423,
        "usd": 4289.229715768061
      },
      "decimals": 6,
      "security": {
        "freezeAuthority": null,
        "mintAuthority": null
      },
      "quoteToken": "So11111111111111111111111111111111111111112",
      "market": "pumpfun",
      "deployer": "4Rz5xqikxtZ2s7wE9uQ6n2oLXQi6K65XGoYpKxf24Hqo",
      "openTime": 0,
      "poolId": "GmJaZvdNptvofC4qe3tvuBNgqLm65p1of5pk6JFHpump"
    }
  ],
  "events": {
    "30m": {
      "priceChangePercentage": 0
    },
    "1h": {
      "priceChangePercentage": 0
    },
    "4h": {
      "priceChangePercentage": 0
    },
    "24h": {
      "priceChangePercentage": 0
    }
  },
  "risk": {
    "rugged": false,
    "risks": [
      {
        "name": "No social media",
        "description": "This token has no social media links",
        "level": "warning",
        "score": 2000
      },
      {
        "name": "Pump.fun contracts can be changed at any time",
        "description": "Pump.fun contracts can be changed by Pump.fun at any time",
        "level": "warning",
        "score": 10
      }
    ],
    "score": 5
  }
}
  1. Graduated
    • Room Name: graduated
    • Description: Receive latest graduated tokens, graduating means tokens that just completed their bonding curve on pumpfun/moonshot and are now on Raydium.
{
  "token": {
    "name": "Token Name",
    "symbol": "DANCE",
    "mint": "AmJaZvdNptvofC4qe3tvuBNgqLm65p1of5pk6JFHpump",
    "uri": "https://cf-ipfs.com/ipfs/QmVrh4ER81fns3S4QU48WiBuhiusc1KsCxsM8mSs1bEGPv",
    "decimals": 6,
    "hasFileMetaData": true,
    "createdOn": "https://pump.fun"
  },
  "pools": [
    {
      "liquidity": {
        "quote": 62,
        "usd": 8907.761583907999
      },
      "price": {
        "quote": 2.9853991922957425e-8,
        "usd": 0.000004289229715768062
      },
      "tokenSupply": 1000000000000000,
      "lpBurn": 100,
      "tokenAddress": "AmJaZvdNptvofC4qe3tvuBNgqLm65p1of5pk6JFHpump",
      "marketCap": {
        "quote": 29.853991922957423,
        "usd": 4289.229715768061
      },
      "decimals": 6,
      "security": {
        "freezeAuthority": null,
        "mintAuthority": null
      },
      "quoteToken": "So11111111111111111111111111111111111111112",
      "market": "pumpfun",
      "deployer": "4Rz5xqikxtZ2s7wE9uQ6n2oLXQi6K65XGoYpKxf24Hqo",
      "openTime": 0,
      "poolId": "GmJaZvdNptvofC4qe3tvuBNgqLm65p1of5pk6JFHpump"
    }
  ],
  "events": {
    "30m": {
      "priceChangePercentage": 0
    },
    "1h": {
      "priceChangePercentage": 0
    },
    "4h": {
      "priceChangePercentage": 0
    },
    "24h": {
      "priceChangePercentage": 0
    }
  },
  "risk": {
    "rugged": false,
    "risks": [
      {
        "name": "No social media",
        "description": "This token has no social media links",
        "level": "warning",
        "score": 2000
      },
      {
        "name": "Pump.fun contracts can be changed at any time",
        "description": "Pump.fun contracts can be changed by Pump.fun at any time",
        "level": "warning",
        "score": 10
      }
    ],
    "score": 5
  }
}

Usage Examples

Here are examples of how to use each room type:

const wsService = new WebSocketService("wss://websocket-url-here.com");
 
// 1. Latest Tokens/Pools
wsService.joinRoom("latest");
wsService.on("latest", (data) => {
  console.log("Latest token/pool update:", data);
});
 
// 2. Pool Changes
wsService.joinRoom(`pool:${poolId}`);
wsService.on(`pool:${poolId}`, (data) => {
  console.log(`Pool ${poolId} update:`, data);
});
 
// 3. Pair Transactions
wsService.joinRoom(`transaction:${tokenAddress}:${poolId}`);
wsService.on(`transaction:${tokenAddress}:${poolId}`, (data) => {
  console.log(`New transaction for ${tokenAddress} in pool ${poolId}:`, data);
});
 
// 4. Transactions
wsService.joinRoom(`transaction:${tokenAddress}`);
wsService.on(`transaction:${tokenAddress}`, (data) => {
  console.log(`New transaction for ${tokenAddress}:`, data);
});
 
// 5. Pair and Wallet Transactions
wsService.joinRoom(`transaction:${tokenAddress}:${poolId}:${walletAddress}`);
wsService.on(
  `transaction:${tokenAddress}:${poolId}:${walletAddress}`,
  (data) => {
    console.log(
      `New transaction for ${tokenAddress} in pool ${poolId} for wallet ${walletAddress}:`,
      data
    );
  }
);
 
// 6. Price Updates
wsService.joinRoom(`price:${poolId}`);
wsService.on(`price:${poolId}`, (data) => {
  console.log(`Price update for pool ${poolId}:`, data);
});
 
wsService.joinRoom(`price-by-token:${tokenId}`); // Make sure to use latest version of websocket service.
wsService.on(`price-by-token:${tokenId}`, (data) => {
  console.log(`Price update for token ${tokenId}:`, data);
});
 
// 7. Wallet Transactions
wsService.joinRoom(`wallet:${walletAddress}`);
wsService.on(`wallet:${walletAddress}`, (data) => {
  console.log(`New transaction for wallet ${walletAddress}:`, data);
});
 
// 8. Graduating tokens
wsService.joinRoom("graduating");
wsService.on("graduating", (data) => {
  console.log("Latest graduating token", data);
});
 
// Graduating with custom market cap
wsService.joinRoom("graduating:sol:175");
wsService.on("graduating:sol:175", (data) => {
  console.log("Latest graduating token", data);
});
 
// 9. Graduating tokens
wsService.joinRoom("graduated");
wsService.on("graduated", (data) => {
  console.log("Latest graduated token", data);
});