docs: clarify Shred ordering and verify metadata passthrough

This commit is contained in:
0xfnzero
2026-10-19 04:26:55 +08:00
parent b7fa14044d
commit 13e1a0fbcf
6 changed files with 52 additions and 18 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "solana-streamer-sdk"
version = "3.0.15"
version = "3.0.16"
edition = "2021"
rust-version = "1.91"
authors = ["William <byteblock6@gmail.com>", "sgxiang <sgxiang@gmail.com>", "wei <1415121722@qq.com>"]
@@ -22,7 +22,7 @@ sdk-perf-stats = ["sol-parser-sdk/perf-stats"]
sdk-ultra-perf = ["sol-parser-sdk/ultra-perf"]
[dependencies]
sol-parser-sdk = { path = "../sol-parser-sdk", version = "=0.7.17", default-features = false }
sol-parser-sdk = { path = "../sol-parser-sdk", version = "=0.7.18", default-features = false }
solana-sdk = "=4.0.1"
solana-client = "=4.2.2"
solana-transaction-status = { version = "=4.2.2", features = ["agave-unstable-api"] }
+14 -7
View File
@@ -1,11 +1,16 @@
<div align="center">
## v3.0.15 — DEX-scoped RawInstruction and typed DEX identifiers
## v3.0.16 — Shred metadata passthrough and ordering scope
Preserve and verify transaction position and receive time through raw instruction callbacks. Entries indexes are message-local, unlike Yellowstone node indexes; use signatures for cross-message deduplication. This release clarifies API documentation and adds regression protection without changing metadata fields or numbering behavior.
## v3.0.16 — DEX-scoped RawInstruction and typed DEX identifiers
Raw instructions now respect DEX subscriptions using programs referenced by each instruction. `RawInstructionDexType` provides typed identifiers with unchanged JSON strings. Unknown router layouts do not establish pool addresses, trade direction, or method versions.
## v3.0.15 — Pump execution replay
## v3.0.16 — Pump execution replay
Current Anchor TradeEvent CPI decoding is supported alongside the historical encoding. RPC/gRPC instruction budgets and minimum outputs remain in instruction fields. Execution fields `sol_amount`, `quote_amount`, and `token_amount` come from execution events; without logs or event CPIs they remain zero (unavailable, not a proven zero fill).
@@ -13,7 +18,7 @@ Run `cargo run --offline --example rpc_transaction_replay` from this repository
The current Delta sell signature is `4ARos3Yq1SMNE3izDpy9YdKrRgMmD7UCDxvnVrBRaGCJHiifPHSmQWc4DPfjUaEUcxS7puGmEN64K7EZdeXLJaj2` (slot 458542546). Older five-combination multi-hop fixtures are retained as regression tests, not labeled as new mainnet captures.
## v3.0.15 — raw Shred instructions
## v3.0.16 — raw Shred instructions
Protocol filters apply to raw DEX associations as well as decoded events.
@@ -21,6 +26,8 @@ Default Shred parsing emits `RawInstruction` for unsupported third-party program
The payload contains `program_id`, `instruction_index`, `accounts`, `account_indices`, `instruction_data`, and transaction metadata. Account order and duplicates are preserved. Unresolved ALT addresses are null/None, with original indices retained; supply cached loaded addresses or a resolver. No hot-path RPC is performed. Data is copied verbatim without requiring a known layout.
The raw event retains `metadata.tx_index` and `metadata.grpc_recv_us` from the parser arguments (streamer names the receive field `metadata.recv_us`). The default Entries client index is local to one received Entries message and restarts at zero for the next message; it is not a confirmed slot-wide transaction index. `instruction_index` orders outer instructions within a transaction. Receive time is a local microsecond timestamp, not an execution-order guarantee. Standalone replay APIs may default these values to zero; pass the upstream values when available.
Without a filter, unknown third-party instructions are returned. Broad trade/swap filters (for example `PumpFunTrade` or `RaydiumCpmmSwap`) also return raw instructions associated with that DEX; direction-specific filters do not infer a buy or sell. Explicit `RawInstruction` selects all outer instructions only when no protocol restriction is set; streamer protocol restrictions always apply. Excluding `RawInstruction` wins. `dex_type` uses the public `RawInstructionDexType` enum (typed string constants in Go); JSON values remain unchanged, such as `"pumpfun"` and `"raydium_cpmm"`. `dexes` contains `{ dex_type, program_id, pool }` for each recognized DEX program targeted or referenced by this instruction, not other instructions in the transaction. Multi-DEX wrappers retain every association. Unknown or unresolved ALT references cannot satisfy a DEX subscription. `pool` is currently null: an unknown wrapper layout cannot establish the pool account. A program reference is not proof of an executed CPI. Raw callbacks are not fills.
Wrapper adapter functions remain explicit compatibility helpers only; default Shred parsing does not call them. The released-version history below describes previous behavior.
@@ -156,24 +163,24 @@ Add the dependency to your `Cargo.toml`:
```toml
# Add to your Cargo.toml
solana-streamer-sdk = { path = "./solana-streamer", version = "3.0.15" }
solana-streamer-sdk = { path = "./solana-streamer", version = "3.0.16" }
```
### Use crates.io
```toml
# Add to your Cargo.toml
solana-streamer-sdk = "3.0.15"
solana-streamer-sdk = "3.0.16"
```
Parser backend features:
```toml
# Default: sol-parser-sdk parse-borsh backend
solana-streamer-sdk = "3.0.15"
solana-streamer-sdk = "3.0.16"
# Zero-copy parser backend for latency-sensitive bots
solana-streamer-sdk = { version = "3.0.15", default-features = false, features = ["sdk-parse-zero-copy"] }
solana-streamer-sdk = { version = "3.0.16", default-features = false, features = ["sdk-parse-zero-copy"] }
```
If both `sdk-parse-borsh` and `sdk-parse-zero-copy` are enabled, `sol-parser-sdk 0.6.1+` uses the zero-copy backend.
+14 -7
View File
@@ -1,11 +1,16 @@
<div align="center">
## v3.0.15 — RawInstruction 协议过滤与 DEX 枚举
## v3.0.16 — Shred 元数据透传与顺序范围
保留并验证 `tx_index`、接收时间从解析入口传到原始指令回调。明确 Entries 消息内序号与 Yellowstone 节点 index 的区别:本地序号不是全 slot 索引;跨消息去重使用交易签名。此版本完善文档和回归保护,不改变现有字段或编号规则。
## v3.0.16 — RawInstruction 协议过滤与 DEX 枚举
修复原始指令绕过 DEX 订阅范围的问题。按单条指令引用的官方程序识别 DEX,使用 `RawInstructionDexType` 枚举;JSON 字符串保持不变。未知 router 不推断池子地址、买卖方向或方法版本。
## v3.0.15 — Pump 执行事件与最新回放示例
## v3.0.16 — Pump 执行事件与最新回放示例
修复官方 Anchor CPI TradeEvent 前缀识别,保留历史编码兼容。RPC/gRPC 的实际 `sol_amount`、`quote_amount`、`token_amount` 只从执行事件合并;预算和最小输出保留在指令参数字段。如果日志及事件 CPI 均缺失,实际金额字段为 0(表示无执行数据,不代表已确认零成交)。非 SOL 报价金额不能当作 SOL。
@@ -13,7 +18,7 @@
新 Delta 卖出样本:`4ARos3Yq1SMNE3izDpy9YdKrRgMmD7UCDxvnVrBRaGCJHiifPHSmQWc4DPfjUaEUcxS7puGmEN64K7EZdeXLJaj2`,slot 458542546。旧的五种双跳组合仅作为回归样本,未冒充本次新抓取交易。
## v3.0.15 — Shred 原始指令透传
## v3.0.16 — Shred 原始指令透传
协议过滤同时作用于原始指令的 DEX 关联和已解码事件。
@@ -21,6 +26,8 @@
事件包含 `program_id`、`instruction_index`、`accounts`、`account_indices`、`instruction_data` 和交易 metadata。账户保留原顺序与重复项;未解析 ALT 地址为 null/None,原始索引仍保留。使用缓存 loaded-addresses/resolver 补齐,热路径不请求 RPC。data 是完整原始字节,不要求已知布局。
原始事件保留调用方传入的 `metadata.tx_index` 和 `metadata.grpc_recv_us`(streamer 对应 `metadata.recv_us`)。默认 Entries 客户端的交易序号仅在单条接收消息内递增,下一条消息从 0 重新计数,不等于已确认的整个 slot 交易序号。`instruction_index` 表示交易内外层指令顺序;接收时间是本地微秒时间戳,不保证链上执行顺序。独立回放 API 可能默认填 0,调用时应传入上游已有的序号与接收时间。
无过滤器时返回未知第三方指令。宽泛交易/Swap 订阅(如 `PumpFunTrade`、`RaydiumCpmmSwap`)也返回关联该 DEX 的原始指令;买/卖方向订阅不推测方向。显式 `RawInstruction` 仅在未限制协议时返回全部外层指令,streamer 的协议限制始终生效;显式排除 `RawInstruction` 优先。`dex_type` 使用公开枚举 `RawInstructionDexType`(Go 为命名字符串类型与常量);JSON 仍为 `"pumpfun"`、`"raydium_cpmm"` 等原有字符串。`dexes` 数组包含各关联 DEX 的 `{ dex_type, program_id, pool }`,只识别本条指令直接调用或账户中引用的 DEX 程序,不借用同笔其他指令的账户;多 DEX 包装保留所有关联。未知或未解析 ALT 中的程序不能匹配 DEX 订阅。`pool` 当前为 null:未知包装布局无法确定池子账户。program 引用不证明执行了 CPI,原始回调不是成交。
已有 wrapper 适配函数仅作为显式调用的兼容接口保留,不参与默认 Shred 解码。以下已发布版本的历史说明描述旧行为。
@@ -155,24 +162,24 @@ git clone https://github.com/0xfnzero/solana-streamer
```toml
# 添加到您的 Cargo.toml
solana-streamer-sdk = { path = "./solana-streamer", version = "3.0.15" }
solana-streamer-sdk = { path = "./solana-streamer", version = "3.0.16" }
```
### 使用 crates.io
```toml
# 添加到您的 Cargo.toml
solana-streamer-sdk = "3.0.15"
solana-streamer-sdk = "3.0.16"
```
解析后端 feature:
```toml
# 默认:sol-parser-sdk parse-borsh 后端
solana-streamer-sdk = "3.0.15"
solana-streamer-sdk = "3.0.16"
# 面向低延迟 Bot 的 zero-copy 解析后端
solana-streamer-sdk = { version = "3.0.15", default-features = false, features = ["sdk-parse-zero-copy"] }
solana-streamer-sdk = { version = "3.0.16", default-features = false, features = ["sdk-parse-zero-copy"] }
```
如果同时启用 `sdk-parse-borsh` 和 `sdk-parse-zero-copy`,`sol-parser-sdk 0.6.1+` 会优先使用 zero-copy 后端。
+15
View File
@@ -0,0 +1,15 @@
# v3.0.16 — Shred metadata passthrough and ordering scope
Released 2026-10-19.
RawInstruction and PumpRouteIntent retain the tx_index and receive timestamp supplied to the parser. Parser SDKs expose metadata.tx_index and metadata.grpc_recv_us; streamer exposes metadata.tx_index and metadata.recv_us. Regression assertions use nonzero values and cover the final streamer callback and JSON round trips.
The default Entries clients enumerate transactions within each received Entries message and reset to zero for the next message. This is a local position, not the final transaction index across a slot. Yellowstone supplies a node transaction index. Receive timestamps are local microsecond timestamps, not execution-order guarantees. Use signatures to deduplicate across Shred messages, and instruction_index to order outer instructions within a transaction.
## Compatibility
No metadata fields were removed or renamed. Existing values and numbering behavior are unchanged. Low-level/replay callers should provide upstream metadata when available rather than relying on zero defaults. This release adds documentation and regression protection; it does not synthesize a global chain ordering or add execution information to Shred data.
## Validation
Nonzero metadata propagation tests pass for Rust parser, sol-shred-sdk, streamer, TypeScript, Python and Go. Existing PumpRouteIntent metadata assertions continue to pass.
+2 -1
View File
@@ -472,7 +472,7 @@ mod tests {
tx.signatures[0],
rpc.slot,
Some(7),
0,
123456,
&protocols,
None,
None,
@@ -486,6 +486,7 @@ mod tests {
assert_eq!(raw.instruction_data, ix.data);
assert_eq!(raw.account_indices, ix.accounts);
assert_eq!(raw.metadata.tx_index, Some(7));
assert_eq!(raw.metadata.recv_us, 123456);
assert_eq!(raw.metadata.slot, rpc.slot);
}
let filter = EventTypeFilter::include_only(vec![EventType::PumpFunTrade]);
+5 -1
View File
@@ -289,9 +289,13 @@ pub struct SwapData {
pub struct EventMetadata {
pub signature: Signature,
pub slot: u64,
pub tx_index: Option<u64>, // 新增:交易在slot中的索引
/// Position supplied by the source. Yellowstone uses its node index;
/// Shred positions may be local to an Entries message. None means unavailable.
/// Do not use (slot, tx_index) as a cross-message Shred deduplication key.
pub tx_index: Option<u64>,
pub block_time: i64,
pub block_time_ms: i64,
/// Local receive timestamp in microseconds; not chain execution order.
pub recv_us: i64,
pub handle_us: i64,
pub protocol: ProtocolType,