You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js中Solana WebSocket的programSubscribe如何过滤仅获取新事件?

如何过滤Solana programSubscribe WebSocket仅获取连接后的新事件?

使用Solana的JSON RPC WebSocket方法programSubscribe时,会收到早至一年前的旧事件,需要实现仅获取WebSocket连接建立后的新事件。

相关代码

const socket = 'https://api.mainnet-beta.solana.com';
socket.open();

try{
socket.onopen = () => {
  isWebSocketConnected(socket); 
  
  try{
    socket.send(
          JSON.stringify({
              jsonrpc: '2.0',
              id: 1,
              method: 'programSubscribe',
              params: [
                programID,
                  {
                      encoding: 'jsonParsed',
                      commitment: 'finalized',
                  },
              ],
          })
      )
      isSubscribed = true;
      logToLogFile("Socket", "Subscription message sent"); 
    }catch(error){
      logToLogFile("SocketError", `Subscription message failed ${error}`); 
    }
}

}catch (error){
logToLogFile("SocketError", `Socket failed to open ${error}`);
}

已尝试的方法

曾尝试获取最新slot并与当前slot对比,但仍有旧数据返回。

解决方案

利用Solana RPC的programSubscribe方法支持的startSlot参数,在订阅时指定连接建立时的最新finalized slot,让服务端仅推送该slot之后的新事件。

修改后的代码如下:

const socket = 'https://api.mainnet-beta.solana.com';
socket.open();

try {
  socket.onopen = () => {
    isWebSocketConnected(socket); 

    try {
      // 先获取当前最新的finalized slot
      socket.send(JSON.stringify({
        jsonrpc: '2.0',
        id: 2,
        method: 'getSlot',
        params: ['finalized']
      }));

      socket.onmessage = (msg) => {
        const response = JSON.parse(msg.data);
        // 处理getSlot的响应
        if (response.id === 2) {
          const currentFinalizedSlot = response.result;
          // 发送订阅请求,指定从当前slot开始接收事件
          socket.send(
            JSON.stringify({
              jsonrpc: '2.0',
              id: 1,
              method: 'programSubscribe',
              params: [
                programID,
                {
                  encoding: 'jsonParsed',
                  commitment: 'finalized',
                  startSlot: currentFinalizedSlot // 关键参数:过滤旧事件
                },
              ],
            })
          );
          isSubscribed = true;
          logToLogFile("Socket", "Subscription message sent");
        } else if (response.method === 'programNotification') {
          // 处理新的程序事件
          const eventData = response.params.result;
          // ... 你的事件处理逻辑
        }
      };
    } catch(error) {
      logToLogFile("SocketError", `Subscription setup failed ${error}`);
    }
  };
} catch (error) {
  logToLogFile("SocketError", `Socket failed to open ${error}`);
}

原理说明

  • startSlot参数会告诉Solana RPC服务端,仅推送该slot及之后的finalized区块中与目标程序相关的事件,从根源上过滤掉连接建立前的旧数据。
  • 先调用getSlot获取当前finalized slot,确保订阅的起点是连接建立时的最新状态,避免遗漏刚发生的事件。

内容的提问来源于stack exchange,提问作者HelplessInWeb3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 07:30:41