Documentation Index
Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
Use this file to discover all available pages before exploring further.
概述
Solana区块链以顺序、仅追加的账本存储数据。这对数据完整性和交易吞吐量有益,但代价是:查询历史数据非常低效且速度极慢。 复杂操作通常涉及从多个来源过滤、聚合或联合数据。在这些情况下,直接查询Solana对于大多数实际应用来说是不切实际的。 为了解决这个问题,大多数企业构建了Solana历史数据的私有索引。索引Solana数据意味着什么?
索引是指从Solana区块链查询数据并将其存储在后端数据库(如PostgreSQL、ClickHouse)中,然后可用来满足客户请求,而无需直接使用Solana RPC调用查询区块链。 索引器通常做四件事:- 回填历史数据: 使用存档RPC方法查询所有历史数据
- 流式传输新数据: 处理网络确认的新区块
- 解析和转换数据: 从确认的区块中提取相关数据(如交易、状态变化等)
- 将数据组织到数据库中: 使用新数据更新索引
为什么大多数公司构建Solana索引?
公司构建Solana索引是因为他们的业务依赖于提供快速、实时访问特定用途的区块链数据,而原生RPC无法提供这些数据(例如,NFT销售历史)。 公司还利用自定义索引将链下数据(如集中交易所价格、KYC信息等)与链上数据结合使用。钱包示例
例如,如果一个Solana钱包需要快速返回用户的代币账户和余额,直接通过getTokenAccountsByOwner和getTokenAccountBalance查询Solana太慢,并可能导致产品无法使用。因此,钱包通常会维护自己的客户地址、代币和账户余额索引。
交易示例
类似地,加密交易公司可能希望记录在特定交易对(例如,SOL-USDC)或特定市场上发生的所有交易活动,以便对其交易算法进行回测。 直接查询区块链来获取这些数据对于任何实际的交易分析来说都太慢了。相反,量化交易员可能会选择为SOL-USDC市场构建索引,并使用诸如LaserStream之类的实时流产品持续更新最新交易。过滤示例
想象一下,用户希望在其前端应用中按照特定标准过滤交易(例如,按代币类型、转账金额、日期或钱包地址)。 没有索引器,您的应用需要扫描成千上万个区块中的数百万笔交易,检查每一笔是否符合过滤条件。 这个过程对于现代产品用户体验来说太慢了。盈亏示例
要计算交易员的盈亏(PnL),您需要:- 找出在给定时间范围内与其钱包相关的所有交易
- 过滤掉兑换交易并将其标记为买入或卖出
- 确定用户在每次兑换中支付的费用
- 获取每次交易时每种代币的历史价格数据
- 汇总每笔交易的盈亏以计算交易员的总盈亏
步骤 1:获取历史数据
构建 Solana 索引的第一步是获取您所关心的所有历史数据。 主要有三种方法:- getTransactionsForAddress (推荐)
- getSignaturesForAddress 和 getTransaction
- getBlock
方法 1:getTransactionsForAddress(推荐)
getTransactionsForAddress RPC方法允许您获取区块链数据任意段落的完整交易详情。由于其强大的过滤功能,您不会浪费时间检索不需要的数据,而且由于其反向搜索功能,您可以按时间顺序获取交易。
使用此方法的步骤
- 确定所需数据的时间范围并相应设置过滤器
- 设置
transactionDetails为full以获取所有交易详情 - 如果需要,配置
tokenAccounts过滤器以包含相关的代币账户交易 - 使用
paginationToken分页浏览结果 - 在每次迭代中,提取所需数据并存储在数据库中
使用 getTransactionsForAddress 的好处
使用gTFA endpoint的主要优势是快速和简便。通过slot和基于时间的过滤器、代币账户支持、反向搜索和分页,您可以在Solana的历史记录中通过单次调用获取所需的任何数据,无需复杂的循环或重试逻辑。与getSignaturesForAddress不同,它还可以包括与地址关联的代币账户相关的交易。
方法 2:getSignaturesForAddress 和 getTransaction
在发布 gTFA 之前,查询历史数据的标准方法是递归地循环使用getSignaturesForAddress 从最新到最老的签名,然后调用 getTransaction 来提取完整的交易详情。
使用此方法的步骤
以下是使用此方法的基本步骤:- 调用
getSignaturesForAddress - 存储此调用中最后接收到的交易的签名
- 对于下一次调用
getSignaturesForAddress,将before参数设置为此签名 - 按需重复此循环
- 对于以这种方式检索到的每个交易签名,调用
getTransaction以获取其完整的交易详情 - 将相关数据插入你的数据库中
此方法的缺点
不幸的是,要使用此方法,您需要:- 从最新的交易开始并向后工作
- 对每笔交易多进行一次 RPC 调用
- 构建一个线程安全队列来处理并发处理
- 构建重试和退避逻辑以防止数据丢失和速率限制
- 不包括涉及由地址拥有的关联代币账户的交易
getTransactionsForAddress。
方法 3:使用 getBlock
getBlock 方法在目标区块中高比例交易与分析相关时最为有效,例如索引 经常使用的 Solana 程序 的交易,如 DFlow 的 Aggregator、Pump.fun 程序或 Solana 的 Token 程序。
使用此方法的步骤
使用getBlock 查询历史数据的基本过程包括:
- 决定要查询的时间范围
- 将此时间范围转换为槽编号
- 顺序获取相应的区块(前向或后向)
- 对于每个区块,筛选与您的索引相关的交易
- 将其中的相关信息存储在您的索引中
步骤 2:将 Solana 数据与您的数据库同步
获取历史数据后,您需要对其进行转换并有效地存储在数据库中。 您的存储选择应该针对您的具体用例量身定制 —— 没有一种通用的解决方案。适合的数据库取决于数据集的大小、延迟要求、查询模式和团队专业知识。选项 1:SQL 数据库
对于大多数用例,建议将 Solana 数据存储在关系数据库如 PostgreSQL 中。SQL 灵活、普遍且易于学习。现代关系数据库可以扩展到超过 1 亿行,同时仍为您提供 ACID 合规性、复杂联接和强大的二级索引的好处。 使用 SQLite 进行原型设计、本地开发或当您想要使用单文件数据库进行零配置时。它非常适合数据集保持在几 GB 以下的情况。 对于需要数据复制、多个客户端并发访问或者高级功能(如全文搜索和 JSON 操作符)的生产应用程序,使用 PostgreSQL。 对于大多数生产级别的 Solana 索引器,我们推荐使用 PostgreSQL。实现示例:
作为示例,我们将展示如何在 PostgreSQL 数据库中存储令牌转移。 首先,创建一个表:选项 2:列式数据库
列式数据库针对分析查询、聚合和高容量时间序列数据进行了优化。如果需要索引数十亿笔交易,像 ClickHouse 或 Cassandra 这样的列式数据库是最佳选择。 当您需要对大数据集进行实时分析查询时,使用 ClickHouse——它针对快速读取、聚合和时间序列分析进行了优化。 当您需要极高的写入吞吐量、轻松的水平扩展和高容错性时,使用 Cassandra。这使得它非常适合持续摄取大量 Solana 数据。实现示例:
我们将展示如何在 ClickHouse 数据库中存储令牌转移。 为此,创建一个使用 MergeTree 表引擎的表。它设计用于高摄取速率,因此非常适合索引。 使用以下命令:(token_mint, date) 被设置为主键和排序键。ClickHouse 将根据你的排序键在磁盘上排序数据。这对于查询单个 token mint 并按日期范围缩小响应范围是最佳的。
这是一个查询示例:
FixedString(N) 数据格式存储,精确存储 N 字节。ClickHouse 自动压缩数据,从而将存储成本降低 10-20 倍并提高查询性能。
为了优化查询性能,使用物化视图来预计算常见的聚合。
例如,可以预计算代币的每日转移量,以便在仪表板上的与量相关的图表中使用。
选项 3:数据湖
数据湖是存储大量原始和处理后的区块链数据的理想选择,用于长期存档和分析查询。 一个简单的实现是使用 Parquet 数据格式与 Amazon Athena。 Parquet 是一种面向列的数据文件格式,旨在实现高效的数据存储和检索。 Amazon Athena 是一种交互式查询服务,允许您使用标准 SQL 分析存储在 Amazon S3 中的数据,而无需设置基础设施或将数据加载到一个单独的数据库中。实施示例:
我们想要创建一个代币转移的存档并查询它们。 首先,我们需要将它们存储在S3中:创建一个命名为solana_index的bucket,并使用此键结构按时间对您的令牌转移数据进行分区:
使用索引框架
使用Carbon和类似框架,以避免编写样板代码,并在数小时而不是数天内设置索引器。主要功能:
- 为流行程序(Token 程序、DeFi 协议、Metaplex)预构建解码器
- 可配置的数据源(RPC、LaserStream、增强 WebSockets)
- 内建对回填和实时流的支持
- 输出到多个存储后端(开箱即用的 Postgres)
- 完全可定制:您可以设置自己的数据源、解码器和数据接收器
步骤 3:保持索引最新
在回填历史数据后,您需要一个实时流解决方案,以便让索引跟踪新的区块链活动。否则,您的索引将变得陈旧。方法 1:LaserStream(推荐)
我们推荐LaserStream gRPC作为所有生产索引用例的默认选择。它专为可靠、超低延迟和容错数据流而设计。 使用 LaserStream 的一些好处包括:- 24 小时历史重播:如果索引器断开连接,LaserStream 会自动重播您未处理的所有事务
- 自动重新连接:我们的LaserStream SDK(Rust、Go、JS/TS)无缝处理网络中断
- 节点故障转移:您的 LaserStream 连接同时从多个节点汇聚数据,确保最大正常运行时间
如何使用 LaserStream 进行索引
使用subscribe方法订阅区块链事件。
以下是一些最佳实践:
- 尽量缩小您的过滤器范围:仅订阅您实际需要索引的数据,以最小化带宽消耗和处理需求。
- 使用
confirmed承诺级别:这在延迟和最终性之间取得平衡。processed级别可能不够可靠,而finalized增加了~13秒的延迟。 - 设置
failed: false,除非您特别需要跟踪失败的交易。 - 排除投票交易(
vote: false),因为它们与索引无关。
方法 2:使用 LaserStream WebSocket
LaserStream WebSocket 是 LaserStream 的 WebSocket 版本,包括特定于 Helius 的transactionSubscribe 扩展,它在与 LaserStream gRPC 相同的后端上运行,当您不需要 gRPC 时,是一种具有成本效益的实时流媒体替代方案。
应在以下情况下使用 LaserStream WebSocket:
- 您的应用可以忍受偶尔的数据差距
- 实时更新很重要,但不是关键任务
- 您拥有可检测和弥补数据缺失的现有基础设施
- 预算限制很重要,需要最大限度地减少流媒体成本
- 您正在原型或测试,在承诺使用 LaserStream 之前
- 速度:LaserStream WebSocket 在与 LaserStream gRPC 相同的后端上运行,但 WebSocket 协议添加了 JSON 框架和每条消息的开销——如果希望在相同数据上达到最低延迟,请使用 LaserStream gRPC
- 可靠性:没有历史重播保证。如果您的 WebSocket 断开连接,您需要使用 RPC 方法手动检测并回填缺口
- 复杂性:需要额外的监控基础设施以确保数据完整性
如何使用 WebSockets 进行索引
要更新存储所有代币转移的索引,您可以这样订阅transactionSubscribe:
开始使用
构建一个强大的 Solana 索引并填充数据需要解决三个核心挑战:- 高效获取历史数据
- 转换和存储数据以便快速检索
- 实时更新已索引的 Solana 数据
下一步:
- 注册免费的 Helius 账户 以获取 API 访问权限
- 阅读 gTFA 文档 了解回填信息
- 浏览 LaserStream 快速入门指南 以进行实时流处理