跳转到主要内容

概述

LaserStream 是一个托管的 Solana gRPC 流式服务。它与开放的 Yellowstone gRPC 协议线兼容,因此任何 Yellowstone 客户端都可以直接使用,并增加了生产功能,如历史重放、多节点故障转移和完全托管的环境。 LaserStream使用开源的gRPC协议,确保没有供应商锁定,并与现有的gRPC实现最大限度兼容。 您可以使用标准 @triton-one/yellowstone-grpc 客户端连接,或使用性能优化的 Helius LaserStream SDK 以获得更高的吞吐量、自动重连、订阅管理、错误处理等额外优势。

LaserStream SDK比JavaScript Yellowstone客户端快40倍

了解我们如何使用Rust Core与零拷贝NAPI绑定来最大化JavaScript SDK的性能
性能提示:如果您在使用LaserStream连接时遇到任何延迟或性能问题,请参考故障排除部分以了解常见原因和解决方案。
无压缩:为了最小化延迟,LaserStream 不会压缩 gRPC 响应消息。将 Accept-Encoding 设置为 gzip 或 zstd 将无效——响应始终以未压缩形式返回。

终端节点和地区

LaserStream 在全球多个地区提供。 选择离您的应用程序最近的终端节点以获得最佳性能:

主网端点

地区位置终端节点
ewr纽瓦克,新泽西(纽约附近)https://laserstream-mainnet-ewr.helius-rpc.com
pitt匹兹堡,美国(中部)https://laserstream-mainnet-pitt.helius-rpc.com
slc盐湖城,美国(西海岸)https://laserstream-mainnet-slc.helius-rpc.com
lax洛杉矶,美国(西海岸)https://laserstream-mainnet-lax.helius-rpc.com
lon伦敦,欧洲https://laserstream-mainnet-lon.helius-rpc.com
ams阿姆斯特丹,欧洲https://laserstream-mainnet-ams.helius-rpc.com
fra法兰克福,欧洲https://laserstream-mainnet-fra.helius-rpc.com
tyo东京,亚洲https://laserstream-mainnet-tyo.helius-rpc.com
sgp新加坡,亚洲https://laserstream-mainnet-sgp.helius-rpc.com

开发网端点

网络位置终端节点
Devnet纽瓦克,新泽西(纽约附近)https://laserstream-devnet-ewr.helius-rpc.com
网络和地区选择
  • 对于 生产应用,选择最靠近服务器的 mainnet 终端节点以获得最佳性能(例如,如果在欧洲部署,请使用阿姆斯特丹 (ams) 或法兰克福 (fra))
  • 对于 测试,使用:https://laserstream-devnet-ewr.helius-rpc.com

快速入门

有兴趣尝试 LaserStream 吗?申请一个 2 天的试用;我们会审核每个申请。
1

创建新项目

mkdir laserstream-grpc-demo
cd laserstream-grpc-demo
npm init -y
2

安装依赖项

npm install helius-laserstream
npm install --save-dev typescript tsx @types/node
我们使用 tsx,因为在 TypeScript 5.x 上默认的 npx tsc --init 设置 verbatimModuleSyntaxmodule: "nodenext"types: [],这都会导致快速 ts-node index.ts 运行中断。tsx 在没有 tsconfig 的情况下运行 .ts 文件。
3

获取您的 API Key

Helius Dashboard 生成一个密钥。此密钥将作为您的 LaserStream 认证令牌。
计划要求:LaserStream 开发网需要 Developer 或更高的计划。LaserStream 主网需要 Business 或 Professional 计划。
4

创建订阅脚本

创建 index.ts,内容如下:
import { subscribe, CommitmentLevel, LaserstreamConfig, SubscribeRequest } from 'helius-laserstream'

async function main() {
  const subscriptionRequest: SubscribeRequest = {
    transactions: {
      "token-filter": { // user-defined label for this filter
        accountInclude: ['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'],
        accountExclude: [],
        accountRequired: [],
        vote: false,
        failed: false
      }
    },
    commitment: CommitmentLevel.CONFIRMED,
    accounts: {},
    slots: {},
    transactionsStatus: {},
    blocks: {},
    blocksMeta: {},
    entry: {},
    accountsDataSlice: [],
    // Optionally, you can replay missed data by specifying a `fromSlot` (u64 number):
    // fromSlot: currentSlot - 1000,
    // Note: replay is currently limited to the last ~216,000 slots (≈24 hours).
  };

// Replace the values below with your actual LaserStream API key and endpoint
const config: LaserstreamConfig = {
  apiKey: 'YOUR_API_KEY', // Replace with your key from https://dashboard.helius.dev/
  endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com', // Choose your closest region
}

  await subscribe(config, subscriptionRequest, async (data) => {
    
    console.log(data);

  }, async (error) => {
    console.error(error);
  });
}

main().catch(console.error);
5

替换您的API密钥并选择您的区域

index.ts中,更新config对象:
  1. 您的实际API密钥来自Helius Dashboard
  2. 离您的服务器位置最近的LaserStream端点
const config: LaserstreamConfig = {
  apiKey: 'YOUR_ACTUAL_API_KEY', // Replace with your key from Helius Dashboard
  endpoint: 'https://laserstream-mainnet-fra.helius-rpc.com', // Example: Frankfurt mainnet
  // For devnet: endpoint: 'https://laserstream-devnet-ewr.helius-rpc.com'
}
网络和区域选择示例:
  • 用于生产(Mainnet)
    • 欧洲:使用fra(法兰克福)、ams(阿姆斯特丹)或lon(伦敦)
    • 美国东部:使用ewr(纽约)
    • 美国西部:使用slc(盐湖城)或lax(洛杉矶)
    • 亚洲:使用tyo(东京)或sgp(新加坡)
  • 用于开发(Devnet)
    • 使用https://laserstream-devnet-ewr.helius-rpc.com
6

运行并查看结果

npx tsx index.ts
每当一个confirmed令牌交易涉及TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA时,您将在控制台中看到数据。

常见工作流程

您可以参考我们最常见的工作流程分步指南。每个指南都使用带有自动重连和历史重播功能的 helius-laserstream SDK。

账户订阅

通过过滤器监控特定账户的余额、数据和所有权变更。

交易监控

流式传输涉及目标账户的交易,并按程序、投票或失败状态进行过滤。

插槽和区块监控

跟踪网络共识、区块生产和承诺级别转换。

解码交易数据

将二进制 transactionUpdate 有效负载解析为可读的 Solana 交易。

流式传输 Pump AMM 数据

真实示例:使用重连安全过滤器监控 Pump AMM 交易。
如果您更喜欢原始Yellowstone协议,@triton-one/yellowstone-grpc客户端也可以使用相同的端点。查看Yellowstone gRPC参考以获取协议级别的详细信息。

订阅请求

在订阅请求中,您需要包括以下一般参数:
历史重播: 您可以选择在主SubscribeRequest对象中包括一个fromSlot字段(一个u64数字),以从特定槽位开始重播数据。目前,重播限制在最近216,000个槽位(≈24小时)。
const subscriptionRequest: SubscribeRequest = {
  commitment: CommitmentLevel.CONFIRMED,
  accountsDataSlice: [],
  transactions: {},
  accounts: {},
  slots: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
}
接下来,您需要指定要订阅的数据过滤器,例如账户、区块、槽位或交易。
定义槽位更新的过滤器。您使用的键(例如,mySlotLabel)是此特定过滤器配置的用户定义标签,如果需要,可以定义多个命名配置(尽管通常一个就足够了)。
slots: {
  // mySlotLabel is a user-defined name for this slot update filter configuration
  mySlotLabel: {
    // filterByCommitment: true => Only broadcast slot updates at the specified subscribeRequest commitment
    filterByCommitment: true
    // interslotUpdates: true allows receiving updates for changes occurring within a slot, not just new slots.
    interslotUpdates: true
  }
},
为账户数据更新定义过滤器。使用的键(例如,tokenAccounts)是此特定过滤器配置的用户定义标签如果所有字段为空,则所有账户都会被广播。否则:
  • 字段作为逻辑AND操作。
  • 数组内的值作为逻辑OR操作(除了在filters中的情况外,那里作为逻辑AND操作)。
accounts: {
  // tokenAccounts is a user-defined label for this account filter configuration
  tokenAccounts: {
    // Matches any of these public keys (logical OR)
    account: ["9SHQTA66Ekh7ZgMnKWsjxXk6DwXku8przs45E8bcEe38"],
    // Matches owners that are any of these public keys
    owner: ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"],
    // Filters - all must match (AND logic)
    filters: [
      { datasize: 165 },
      {
        memcmp: {
          offset: 0,
          base58: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
        }
      }
    ]
  }
},
为交易更新定义过滤器。使用的键(例如,myTxSubscription)是此特定过滤器配置的用户定义标签如果所有字段都留空,则所有交易都会被广播。否则:
  • 字段作为逻辑AND操作。
  • 数组内的值作为逻辑OR处理(除了对于accountRequired,所有必须匹配的情况)。
transactions: {
  // myTxSubscription is a user-defined label for this transaction filter configuration
  myTxSubscription: {
    vote: false,
    failed: false,
    signature: "",
    // Transaction must include at least one of these public keys (OR)
    accountInclude: ["86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY"],
    // Exclude if it matches any of these
    accountExclude: [],
    // Require all accounts in this array (AND)
    accountRequired: []
  }
},
为块更新定义过滤器。您使用的键(例如,myBlockLabel)是这个特定过滤器配置的用户定义标签
blocks: {
  // myBlockLabel is a user-defined label for this block filter configuration
  myBlockLabel: {
    // Only broadcast blocks referencing these accounts
    accountInclude: ["86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY"],
    includeTransactions: true,
    includeAccounts: false,
    includeEntries: false
  }
},
其功能类似于块,但不包括交易、账户和条目。您使用的键(例如,blockmetadata)是此订阅的用户定义标签。目前,不提供块元数据的过滤器——所有消息默认广播。
blocksMeta: {
  blockmetadata: {}
},
订阅账本条目。您使用的键(例如,entrySubscribe)是此订阅的用户定义标签。目前,条目没有可用的过滤器;所有条目都被广播。
entry: {
  entrySubscribe: {}
},

代码示例(LaserStream SDK)

import { subscribe, CommitmentLevel, LaserstreamConfig, SubscribeRequest } from 'helius-laserstream'

async function main() {
    const subscriptionRequest: SubscribeRequest = {
        transactions: {},
        commitment: CommitmentLevel.CONFIRMED,
        accounts: {},
        slots: {
            slot: { filterByCommitment: true },
        },
        transactionsStatus: {},
        blocks: {},
        blocksMeta: {},
        entry: {},
        accountsDataSlice: [],
    };

    const config: LaserstreamConfig = {
        apiKey: 'YOUR_API_KEY', // Replace with your key
        endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com', // Choose your closest region
    }

    await subscribe(config, subscriptionRequest, async (data) => {
        console.log(data);
    }, async (error) => {
        console.error(error);
    });
}

main().catch(console.error);

SDK 选项

我们为多种编程语言提供了官方 SDK: 对于其他语言或自定义实现,您可以直接使用 Yellowstone gRPC proto files 来生成您喜欢语言的 gRPC 客户端。

疑难解答 / 常见问题

A: LaserStream 连接的性能问题通常由以下原因导致:
  • JavaScript 客户端缓慢:JavaScript 客户端在处理过多消息或消耗过多带宽时可能会滞后。请考虑更精确地过滤您的订阅以减少消息量,切换到 LaserStream JavaScript SDK,或尝试使用其他语言。
  • 本地带宽有限:大量订阅可能会使带宽有限的客户端不堪重负。监控您的网络使用情况,并考虑升级您的连接或减少订阅范围。
  • 地理距离:较长的网络路径会增加延迟和数据包丢失。请使用 距离您服务器最近的端点。对于高延迟连接,请增加网络读取缓冲区大小(可以提高5倍以上的带宽):
    sudo sysctl -w net.core.rmem_max=67108864 net.ipv4.tcp_rmem="4096 87380 67108864"
    
    为在重启后保持配置,添加到 /etc/sysctl.conf
    net.core.rmem_max=67108864
    net.ipv4.tcp_rmem=4096 87380 67108864
    
    增加 HTTP/2 流窗口大小到 64MB 以防止流量控制瓶颈:
    // Rust (tonic)
    Channel::from_static("https://laserstream-mainnet-ewr.helius-rpc.com")
        .initial_stream_window_size(1024 * 1024 * 64)  // 64MB window
        .connect()
        .await?;
    
  • 客户端处理瓶颈:确保您的消息处理逻辑经过优化,并且不会长时间堵塞主线程。
调试客户端延迟:为帮助您调试客户端,我们构建了一个工具来测试从您的节点到 Laserstream gRPC 服务器的最大带宽。要使用它,请运行:
cargo install helius-laserstream-bandwidth
helius-laserstream-bandwidth --laserstream-url $LASERSTREAM_URL --api-key $API_KEY
输出返回您的服务器和Laserstream服务器之间的最大网络容量。至少需要10MB/s来订阅所有交易数据,80MB/s来订阅所有账户数据。我们建议至少具备所需容量的2倍以获得最佳性能。
A: 验证您的API密钥和端点是否正确,并确保您的网络允许向指定端点的外发gRPC连接。检查Helius状态页面是否有正在进行的事件。
A: 重新检查过滤器部分描述的逻辑运算符(AND/OR)。确保公钥正确。查看请求中指定的承诺级别。
A: 可以,您可以在同一个SubscribeRequest对象下定义多个键(例如,accountstransactions)的过滤器配置。
A: 我们不实现消费组。相反,LaserStream提供团队所需的相同结果:恢复、重放和多节点可靠性,而无需协调层(以及随之而来的延迟/开销)。我们认为大多数工作负载不需要消费组,而且消费组会增加延迟和操作开销。举个例子,单个LaserStream gRPC连接可以发出多达10倍Solana的交易和账户数据,而大多数客户端只订阅一个小的、过滤后的片段。在这种情况下使用消费组会消耗性能空间并引入另一个故障点。
A: 在您的初始 ping 中包含一个字段会导致 LaserStream 静默忽略所有订阅过滤器,仅返回一个不包含账户、交易或插槽数据的 Pong。要解决此问题,请从初始订阅请求中移除 ping,然后在订阅建立后,通过流的 sink 单独发送 ping。这可以保持连接活跃而不干扰您的过滤器。