Solana Stream SDK 作为开源软件提供。更多详情请访问以下 GitHub 仓库。
gRPC 过滤器概述
Solana Geyser gRPC 使用过滤器高效获取您感兴趣的数据,如特定账户、程序、交易、slot 和区块。
以下是使用 Solana Stream SDK 的 TypeScript 示例,清楚地说明了每个过滤器的具体作用。使用 Rust 时,过滤器的结构和含义完全相同。
当前 Shared 的过滤器规则
在当前的 Shared 方案中,任何非空的 blocks map 都仅限 Dedicated,包括使用 accountInclude 或排除交易来缩小范围的请求。如果交易订阅或 blocksMeta 能满足需求,请使用它们;但两者都不等同于完整区块。完整区块需要 Dedicated Geyser gRPC 流。
每个账户过滤器条目都必须包含 account、owner 或受支持的 cuckoo 过滤器。仅有 memcmp 或 dataSize 条件,无法选出受支持的账户订阅形式。请使用上述选择器之一缩小请求范围;如需完整的账户流,请使用 Dedicated Geyser gRPC。
各过滤器的作用和示例
订阅账户
订阅特定账户的实时更新。以下示例以 Confirmed 确认级别订阅 SOL-USDC OpenBook 账户:
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: { slots: {} },
accounts: {
'wsol/usdc': {
account: ['8BnEgHoWFysVcuFFX7QztDmzuH8r5ZFvyP3sYwn1XTh6'],
},
},
transactions: {},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.CONFIRMED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: { slots: {} },
accounts: {
'wsol/usdc': {
account: ['8BnEgHoWFysVcuFFX7QztDmzuH8r5ZFvyP3sYwn1XTh6'],
},
},
transactions: {},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.CONFIRMED,
}
"wsol/usdc" 是客户端自定义的标签。
- 账户、程序、区块和 slot 的多个过滤器可以在单个 JSON 请求中组合使用。
使用 account_data_slice 订阅账户
此示例演示仅检索账户数据的特定部分。不获取 USDC 代币账户的全部数据(165 字节),而是从偏移量 32 开始检索 40 字节。此范围包含所有者和 lamports 余额等信息。
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {},
accounts: {
usdc: {
owner: ['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'],
filters: [
{
tokenAccountState: true,
},
{
memcmp: {
offset: 0,
data: {
base58: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
},
},
},
],
},
},
transactions: {},
blocks: {},
blocksMeta: {},
entry: {},
commitment: CommitmentLevel.CONFIRMED,
accountsDataSlice: [{ offset: 32, length: 40 }],
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {},
accounts: {
usdc: {
owner: ['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'],
filters: [
{
tokenAccountState: true,
},
{
memcmp: {
offset: 0,
data: {
base58: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
},
},
},
],
},
},
transactions: {},
blocks: {},
blocksMeta: {},
entry: {},
commitment: CommitmentLevel.CONFIRMED,
accountsDataSlice: [{ offset: 32, length: 40 }],
}
订阅程序
此示例演示订阅与特定程序关联的账户更新。
以下以 Processed 确认级别订阅 Solend 程序拥有的账户更新。
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {
solend: {
owner: ['So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo'],
},
},
transactions: {},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {
solend: {
owner: ['So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo'],
},
},
transactions: {},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
"solend" 是客户端可以自由设置的自定义标签。
- 要订阅多个程序,请参阅下一节"订阅多个程序"。
订阅多个程序
此示例演示如何同时订阅与多个程序关联的账户更新。
以下示例订阅 Solend 和 Serum 程序拥有的账户更新。
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {
programs: {
owner: [
'So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo',
'9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin',
],
},
},
transactions: {},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {
programs: {
owner: [
'So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo',
'9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin',
],
},
},
transactions: {},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
如果您希望为每个程序分配单独的标签,请使用以下方式:
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {
solend: {
owner: ['So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo'],
},
serum: {
owner: ['9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'],
},
},
transactions: {},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {
solend: {
owner: ['So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo'],
},
serum: {
owner: ['9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'],
},
},
transactions: {},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
订阅所有已最终确认的非投票且未失败的交易
此示例演示以 Finalized 确认级别订阅所有交易,排除投票交易和失败交易。
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {},
transactions: {
alltxs: {
vote: false,
failed: false,
},
},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.FINALIZED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {},
transactions: {
alltxs: {
vote: false,
failed: false,
},
},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.FINALIZED,
}
vote: false 排除投票交易。
failed: false 排除失败交易。
- 如果字段留空,将检索所有交易。
- 指定多个字段时,它们以 AND 条件运行。
订阅涉及特定账户的非投票交易
此示例演示订阅涉及特定账户但排除投票交易的交易。
以下示例订阅涉及 Serum 程序关联账户的非投票交易。
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {},
transactions: {
serum: {
vote: false,
accountInclude: ['9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'],
},
},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {},
transactions: {
serum: {
vote: false,
accountInclude: ['9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'],
},
},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
订阅排除特定账户的交易
此示例演示订阅排除涉及特定账户的交易。
以下示例检索排除 Serum 和 Tokenkeg 程序拥有的任何账户的交易。
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {},
transactions: {
serum: {
accountExclude: [
'9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin',
'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
],
},
},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {},
transactions: {
serum: {
accountExclude: [
'9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin',
'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
],
},
},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
订阅涉及特定账户并排除某些账户的交易
此示例演示订阅涉及某些账户的交易,同时明确排除其他指定账户。
以下示例订阅涉及 Serum 账户的交易,但排除指定账户:
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {},
transactions: {
serum: {
accountInclude: ['9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'],
accountExclude: ['9wFFyRfZBsuAha4YcuxcXLKwMxJR43S7fPfQLusDBzvT'],
},
},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
slots: {},
},
accounts: {},
transactions: {
serum: {
accountInclude: ['9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'],
accountExclude: ['9wFFyRfZBsuAha4YcuxcXLKwMxJR43S7fPfQLusDBzvT'],
},
},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
订阅交易签名
此示例演示订阅特定交易签名的实时更新,直到它达到 Confirmed 或 Finalized 状态。
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {},
accounts: {},
transactions: {
sign: {
signature:
'5rp2hL9b6kexex11Mugfs3vfU9GhieKruj4CkFFSnu52WLxiGn4VcLLwsB62XURhMmT1j4CZiXT6FFtYbXsLq2Zs',
},
},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {},
accounts: {},
transactions: {
sign: {
signature:
'5rp2hL9b6kexex11Mugfs3vfU9GhieKruj4CkFFSnu52WLxiGn4VcLLwsB62XURhMmT1j4CZiXT6FFtYbXsLq2Zs',
},
},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
订阅 slot
此示例演示订阅传入 slot 的通知。除了分配自定义标签名称外,无需其他详细信息:
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
incoming_slots: {},
},
accounts: {},
transactions: {},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {
incoming_slots: {},
},
accounts: {},
transactions: {},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
订阅区块(在当前的 Shared 方案中仅限 Dedicated)
订阅所有生成区块的实时更新。默认情况下,将检索区块内的所有交易:
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {},
accounts: {},
transactions: {},
blocks: {
blocks: {},
},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {},
accounts: {},
transactions: {},
blocks: {
blocks: {},
},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
排除交易,仅检索更新的账户信息(在当前的 Shared 方案中仅限 Dedicated):
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {},
accounts: {},
transactions: {},
blocks: {
blocks: {
includeTransactions: false,
includeAccounts: true,
},
},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {},
accounts: {},
transactions: {},
blocks: {
blocks: {
includeTransactions: false,
includeAccounts: true,
},
},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
仅检索涉及特定账户的交易/账户(在当前的 Shared 方案中仅限 Dedicated):
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {},
accounts: {},
transactions: {},
blocks: {
blocks: {
accountInclude: ['So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo'],
},
},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {},
accounts: {},
transactions: {},
blocks: {
blocks: {
accountInclude: ['So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo'],
},
},
blocksMeta: {},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
订阅区块元数据
仅订阅区块处理时的区块元数据通知。不包含详细的交易数据。
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {},
accounts: {},
transactions: {},
blocks: {},
blocksMeta: {
blockmetadata: {},
},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
const request = {
slots: {},
accounts: {},
transactions: {},
blocks: {},
blocksMeta: {
blockmetadata: {},
},
accountsDataSlice: [],
commitment: CommitmentLevel.PROCESSED,
}
管理确认级别
Solana Geyser gRPC 流默认使用 Processed 确认级别。
您可以指定更高的确认级别,如 Confirmed 或 Finalized。在这些情况下,Geyser 会缓冲数据并在达到指定的确认级别后发送通知。
为获得最佳性能,建议在客户端管理确认级别。
以下是指定确认级别的方法:
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
enum CommitmentLevel {
PROCESSED = 0,
CONFIRMED = 1,
FINALIZED = 2,
}
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'
enum CommitmentLevel {
PROCESSED = 0,
CONFIRMED = 1,
FINALIZED = 2,
}
PROCESSED:处理后的即时数据。检索速度快,但尚未确认。
CONFIRMED:经集群确认的数据,提供更高的确定性。
FINALIZED:完全最终确认的数据,没有重组风险。
使用 Processed 的优势
Processed 确认级别的主要优势是即时交易检索,能够快速进行客户端处理。客户端随后可以检测到向 Confirmed 或 Finalized 的转换,提供快速响应能力。
如何管理 Confirmed 和 Finalized
使用 Confirmed 或 Finalized 级别时,应按 slot 缓冲事件(交易或账户更新)。
按 slot 缓冲事件,订阅 slot 通知,并在特定 slot 达到所需确认级别(Confirmed 或 Finalized)后从缓冲区释放事件。
事件最初会在 slot 达到 Confirmed 或 Finalized 之前接收。
Finalized 的特殊之处
由于 Solana Geyser 规范,并非所有 slot 都会收到明确的最终确认通知。因此,当您收到某个 slot 的最终确认通知时,必须将所有祖先 slot 也视为已最终确认,即使没有收到明确的通知。
具体来说,收到最终确认通知后,追溯地将所有祖先 slot 视为已最终确认。