Release v1.5.5 parser SDK sync

This commit is contained in:
0xfnzero
2026-06-01 20:20:01 +08:00
parent 5a282bd84d
commit 83c5476ff3
45 changed files with 979 additions and 211 deletions
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "solana-streamer-sdk"
version = "1.5.4"
version = "1.5.5"
edition = "2021"
authors = ["William <byteblock6@gmail.com>", "sgxiang <sgxiang@gmail.com>", "wei <1415121722@qq.com>"]
repository = "https://github.com/0xfnzero/solana-streamer"
@@ -15,13 +15,13 @@ crate-type = ["cdylib", "rlib"]
[features]
default = ["sdk-parse-borsh"]
sdk-parse-borsh = ["sol-parser-sdk/parse-borsh"]
# If both parser backend features are enabled, sol-parser-sdk 0.5.4+ uses zero-copy.
# If both parser backend features are enabled, sol-parser-sdk 0.5.5+ uses zero-copy.
sdk-parse-zero-copy = ["sol-parser-sdk/parse-zero-copy"]
sdk-perf-stats = ["sol-parser-sdk/perf-stats"]
sdk-ultra-perf = ["sol-parser-sdk/ultra-perf"]
[dependencies]
sol-parser-sdk = { version = "0.5.4", default-features = false }
sol-parser-sdk = { version = "0.5.5", default-features = false }
solana-sdk = "3.0.0"
solana-client = "3.1.12"
solana-transaction-status = "3.1.12"
+14 -8
View File
@@ -77,13 +77,14 @@
- **PumpFun**: Meme coin trading platform events
- **Pump Fees**: Pump fee-sharing configuration events
- **PumpSwap**: PumpFun's swap protocol events
- **Raydium Launchpad / Bonk**: Token launch platform events (letsbonk.fun / LaunchLab)
- **Raydium LaunchLab**: Token launch platform events; `Protocol::Bonk` and `Protocol::RaydiumLaunchpad` remain compatible aliases
- **Raydium CPMM**: Raydium's Concentrated Pool Market Maker events
- **Raydium CLMM**: Raydium's Concentrated Liquidity Market Maker events
- **Raydium AMM V4**: Raydium's Automated Market Maker V4 events
- **Meteora DAMM v2**: Meteora DAMM v2 swap and liquidity events
- **Orca Whirlpool**: Orca Whirlpool swap and liquidity events
- **Meteora Pools**: Meteora Pools swap, liquidity, bootstrap, and fee events
- **Meteora DBC**: Meteora Dynamic Bonding Curve log-side swap, initialize-pool, and curve-complete events
- **Meteora DLMM**: Meteora DLMM swap, liquidity, pool, bin-array, and fee events
### Advanced Features
@@ -123,30 +124,34 @@ Add the dependency to your `Cargo.toml`:
```toml
# Add to your Cargo.toml
solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.4" }
solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.5" }
```
### Use crates.io
```toml
# Add to your Cargo.toml
solana-streamer-sdk = "1.5.4"
solana-streamer-sdk = "1.5.5"
```
Parser backend features:
```toml
# Default: sol-parser-sdk parse-borsh backend
solana-streamer-sdk = "1.5.4"
solana-streamer-sdk = "1.5.5"
# Zero-copy parser backend for latency-sensitive bots
solana-streamer-sdk = { version = "1.5.4", default-features = false, features = ["sdk-parse-zero-copy"] }
solana-streamer-sdk = { version = "1.5.5", default-features = false, features = ["sdk-parse-zero-copy"] }
```
If both `sdk-parse-borsh` and `sdk-parse-zero-copy` are enabled, `sol-parser-sdk 0.5.4+` uses the zero-copy backend.
If both `sdk-parse-borsh` and `sdk-parse-zero-copy` are enabled, `sol-parser-sdk 0.5.5+` uses the zero-copy backend.
## 🔄 Migration Guide
### Upgrading to v1.5.5
Version 1.5.5 uses `sol-parser-sdk 0.5.5` from crates.io. The SDK now exposes Raydium LaunchLab as `RaydiumLaunchlab*`; streamer keeps the existing `Bonk*` event structs and `Protocol::Bonk` / `Protocol::RaydiumLaunchpad` aliases for source compatibility, while routing parser calls and upstream gRPC event filters to the new LaunchLab SDK variants. This release also syncs the CLMM/CPMM/Orca account bridges, Meteora DAMM v2 initialize-pool events, Meteora DBC events, and parser warmup on client creation.
### Upgrading to v1.5.4
Version 1.5.4 uses `sol-parser-sdk 0.5.4` from crates.io. Pump.fun `create` and `create_v2` are delivered as one canonical `PumpFunCreateTokenEvent`; subscribing to either `PumpFunCreateToken` or `PumpFunCreateV2Token` receives the same complete create-family data. This prevents duplicate new-mint callbacks from gRPC log + instruction parsing while preserving create_v2 account fields on the canonical create event.
@@ -442,15 +447,16 @@ Note: Multiple subscription attempts on the same client return an error.
- **PumpFun**: Primary meme coin trading platform
- **Pump Fees**: Pump fee-sharing configuration events
- **PumpSwap**: PumpFun's swap protocol
- **Raydium Launchpad / Bonk**: Token launch platform (letsbonk.fun / LaunchLab)
- **Raydium LaunchLab**: Token launch platform; `Bonk` and `RaydiumLaunchpad` are kept as compatibility aliases
- **Raydium CPMM**: Raydium's Concentrated Pool Market Maker protocol
- **Raydium CLMM**: Raydium's Concentrated Liquidity Market Maker protocol
- **Raydium AMM V4**: Raydium's Automated Market Maker V4 protocol
- **Meteora DAMM v2**: Meteora DAMM v2 protocol
- **Orca Whirlpool**: Orca Whirlpool protocol
- **Meteora Pools**: Meteora Pools protocol
- **Meteora DBC**: Meteora Dynamic Bonding Curve protocol
- **Meteora DLMM**: Meteora Dynamic Liquidity Market Maker protocol
- **Common events**: Token accounts, token metadata, nonce accounts, block metadata, and ComputeBudget events
- **Common/account events**: Token accounts, token metadata, nonce accounts, block metadata, ComputeBudget events, and supported protocol account states such as Raydium CLMM/CPMM, Pump/PumpSwap, and Orca Whirlpool accounts
## 🌐 Event Streaming Services
+14 -8
View File
@@ -76,13 +76,14 @@
- **PumpFun**: 迷因币交易平台事件
- **Pump Fees**: Pump 费用分成配置事件
- **PumpSwap**: PumpFun 的交换协议事件
- **Raydium Launchpad / Bonk**: 代币发射平台事件 (letsbonk.fun / LaunchLab)
- **Raydium LaunchLab**: 代币发射平台事件`Protocol::Bonk``Protocol::RaydiumLaunchpad` 仍作为兼容别名保留
- **Raydium CPMM**: Raydium 集中池做市商事件
- **Raydium CLMM**: Raydium 集中流动性做市商事件
- **Raydium AMM V4**: Raydium 自动做市商 V4 事件
- **Meteora DAMM v2**: Meteora DAMM v2 交易和流动性事件
- **Orca Whirlpool**: Orca Whirlpool 交易和流动性事件
- **Meteora Pools**: Meteora Pools 交易、流动性、启动流动性和费用事件
- **Meteora DBC**: Meteora Dynamic Bonding Curve 的 log-side swap、initialize-pool 和 curve-complete 事件
- **Meteora DLMM**: Meteora DLMM 交易、流动性、池、bin array 和费用事件
### 高级功能
@@ -122,30 +123,34 @@ git clone https://github.com/0xfnzero/solana-streamer
```toml
# 添加到您的 Cargo.toml
solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.4" }
solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.5" }
```
### 使用 crates.io
```toml
# 添加到您的 Cargo.toml
solana-streamer-sdk = "1.5.4"
solana-streamer-sdk = "1.5.5"
```
解析后端 feature
```toml
# 默认:sol-parser-sdk parse-borsh 后端
solana-streamer-sdk = "1.5.4"
solana-streamer-sdk = "1.5.5"
# 面向低延迟 Bot 的 zero-copy 解析后端
solana-streamer-sdk = { version = "1.5.4", default-features = false, features = ["sdk-parse-zero-copy"] }
solana-streamer-sdk = { version = "1.5.5", default-features = false, features = ["sdk-parse-zero-copy"] }
```
如果同时启用 `sdk-parse-borsh``sdk-parse-zero-copy``sol-parser-sdk 0.5.4+` 会优先使用 zero-copy 后端。
如果同时启用 `sdk-parse-borsh``sdk-parse-zero-copy``sol-parser-sdk 0.5.5+` 会优先使用 zero-copy 后端。
## 🔄 迁移指南
### 升级到 v1.5.5
v1.5.5 使用 crates.io 上的 `sol-parser-sdk 0.5.5`。底层 SDK 已将 Raydium LaunchLab 事件统一暴露为 `RaydiumLaunchlab*`streamer 仍保留现有 `Bonk*` 事件结构以及 `Protocol::Bonk` / `Protocol::RaydiumLaunchpad` 兼容别名,同时把解析调用和上游 gRPC 事件过滤映射到新的 LaunchLab SDK variant。该版本也同步了 CLMM/CPMM/Orca account bridge、Meteora DAMM v2 initialize-pool、Meteora DBC 事件,以及客户端创建时的 parser warmup。
### 升级到 v1.5.4
v1.5.4 使用 crates.io 上的 `sol-parser-sdk 0.5.4`。Pump.fun `create``create_v2` 会统一投递为 canonical `PumpFunCreateTokenEvent`;订阅 `PumpFunCreateToken``PumpFunCreateV2Token` 任意一个,都能收到同一份完整 create-family 数据。该版本避免 gRPC log + instruction 双路径解析导致新 mint 回调重复,同时在 canonical create 事件上保留 create_v2 账户字段。
@@ -441,15 +446,16 @@ grpc.update_subscription(
- **PumpFun**: 主要迷因币交易平台
- **Pump Fees**: Pump 费用分成配置事件
- **PumpSwap**: PumpFun 的交换协议
- **Raydium Launchpad / Bonk**: 代币发射平台 (letsbonk.fun / LaunchLab)
- **Raydium LaunchLab**: 代币发射平台;`Bonk``RaydiumLaunchpad` 作为兼容别名保留
- **Raydium CPMM**: Raydium 集中池做市商协议
- **Raydium CLMM**: Raydium 集中流动性做市商协议
- **Raydium AMM V4**: Raydium 自动做市商 V4 协议
- **Meteora DAMM v2**: Meteora DAMM v2 协议
- **Orca Whirlpool**: Orca Whirlpool 协议
- **Meteora Pools**: Meteora Pools 协议
- **Meteora DBC**: Meteora Dynamic Bonding Curve 协议
- **Meteora DLMM**: Meteora 动态流动性做市商协议
- **通用事件**: Token 账户、Token 元信息、Nonce 账户、区块元数据ComputeBudget 事件
- **通用/账户事件**: Token 账户、Token 元信息、Nonce 账户、区块元数据ComputeBudget 事件,以及 Raydium CLMM/CPMM、Pump/PumpSwap、Orca Whirlpool 等已支持协议账户状态
## 🌐 事件流服务
+1 -1
View File
@@ -125,7 +125,7 @@ async fn main() -> Result<()> {
accounts.extend(address_table_lookups);
let slot = transaction.slot;
let block_time = transaction.block_time.map(|t| Timestamp { seconds: t as i64, nanos: 0 });
let block_time = transaction.block_time.map(|t| Timestamp { seconds: t, nanos: 0 });
let recv_us =
std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_micros()
as i64;
+1 -1
View File
@@ -104,7 +104,7 @@ async fn main() -> Result<()> {
accounts.extend(address_table_lookups);
let slot = transaction.slot;
let block_time = transaction.block_time.map(|t| Timestamp { seconds: t as i64, nanos: 0 });
let block_time = transaction.block_time.map(|t| Timestamp { seconds: t, nanos: 0 });
let recv_us =
std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_micros()
as i64;
+4 -2
View File
@@ -31,9 +31,11 @@ async fn test_grpc() -> Result<(), Box<dyn std::error::Error>> {
println!("Subscribing to Yellowstone gRPC events...");
// Create low-latency configuration.
let mut config: ClientConfig = ClientConfig::default();
// Metrics add overhead; enable explicitly with STREAMER_ENABLE_METRICS=1.
config.enable_metrics = std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1");
let config = ClientConfig {
enable_metrics: std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1"),
..Default::default()
};
let grpc = YellowstoneGrpc::new_with_config(
"https://solana-yellowstone-grpc.publicnode.com:443".to_string(),
None,
@@ -26,9 +26,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn test_grpc() -> Result<(), Box<dyn std::error::Error>> {
println!("Subscribing to Yellowstone gRPC events...");
// Create low-latency configuration.
let mut config: ClientConfig = ClientConfig::default();
// Metrics add overhead; enable explicitly with STREAMER_ENABLE_METRICS=1.
config.enable_metrics = std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1");
let config = ClientConfig {
enable_metrics: std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1"),
..Default::default()
};
let grpc = YellowstoneGrpc::new_with_config(
"https://solana-yellowstone-grpc.publicnode.com:443".to_string(),
None,
@@ -103,10 +105,9 @@ async fn test_grpc() -> Result<(), Box<dyn std::error::Error>> {
}
fn create_event_callback() -> impl Fn(DexEvent) {
|event: DexEvent| match event {
DexEvent::TokenAccountEvent(e) => {
|event: DexEvent| {
if let DexEvent::TokenAccountEvent(e) = event {
println!("TokenAccount: {:?} amount: {:?}", e.pubkey, e.amount);
}
_ => {}
}
}
+4 -2
View File
@@ -18,9 +18,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn test_grpc() -> Result<(), Box<dyn std::error::Error>> {
println!("Subscribing to Yellowstone gRPC events...");
// Create low-latency configuration.
let mut config: ClientConfig = ClientConfig::default();
// Metrics add overhead; enable explicitly with STREAMER_ENABLE_METRICS=1.
config.enable_metrics = std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1");
let config = ClientConfig {
enable_metrics: std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1"),
..Default::default()
};
let grpc = YellowstoneGrpc::new_with_config(
"https://solana-yellowstone-grpc.publicnode.com:443".to_string(),
None,
+1 -1
View File
@@ -139,7 +139,7 @@ async fn parse_local_ix_path(
accounts.extend(address_table_lookups);
let slot = transaction.slot;
let block_time = transaction.block_time.map(|t| Timestamp { seconds: t as i64, nanos: 0 });
let block_time = transaction.block_time.map(|t| Timestamp { seconds: t, nanos: 0 });
let bot_wallet = None;
let tx_index = None;
+4 -2
View File
@@ -18,9 +18,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("🚀 Quick Test - Subscribing to PumpFun events...");
let mut config = ClientConfig::default();
// Metrics add overhead; enable explicitly with STREAMER_ENABLE_METRICS=1.
config.enable_metrics = std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1");
let config = ClientConfig {
enable_metrics: std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1"),
..Default::default()
};
let grpc = YellowstoneGrpc::new_with_config(
std::env::var("GRPC_ENDPOINT")
+4 -2
View File
@@ -25,9 +25,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("🚀 PumpFun Trade Event Filter (solana-streamer)\n");
let mut config = ClientConfig::default();
// Metrics add overhead; enable explicitly with STREAMER_ENABLE_METRICS=1.
config.enable_metrics = std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1");
let config = ClientConfig {
enable_metrics: std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1"),
..Default::default()
};
let grpc = YellowstoneGrpc::new_with_config(
std::env::var("GRPC_ENDPOINT")
+1 -2
View File
@@ -15,8 +15,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("PumpFun with metrics (solana-streamer)\n");
let mut config = ClientConfig::default();
config.enable_metrics = true;
let config = ClientConfig { enable_metrics: true, ..Default::default() };
let grpc = YellowstoneGrpc::new_with_config(
std::env::var("GRPC_ENDPOINT")
@@ -26,9 +26,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn test_grpc() -> Result<(), Box<dyn std::error::Error>> {
println!("Subscribing to Yellowstone gRPC events...");
// Create low-latency configuration.
let mut config: ClientConfig = ClientConfig::default();
// Metrics add overhead; enable explicitly with STREAMER_ENABLE_METRICS=1.
config.enable_metrics = std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1");
let config = ClientConfig {
enable_metrics: std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1"),
..Default::default()
};
let grpc = YellowstoneGrpc::new_with_config(
"https://solana-yellowstone-grpc.publicnode.com:443".to_string(),
None,
@@ -105,10 +107,9 @@ async fn test_grpc() -> Result<(), Box<dyn std::error::Error>> {
}
fn create_event_callback() -> impl Fn(DexEvent) {
|event: DexEvent| match event {
DexEvent::TokenAccountEvent(e) => {
|event: DexEvent| {
if let DexEvent::TokenAccountEvent(e) = event {
println!("TokenAccount: {:?} amount: {:?}", e.pubkey, e.amount);
}
_ => {}
}
}
+1 -2
View File
@@ -15,8 +15,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("PumpSwap with metrics (solana-streamer)\n");
let mut config = ClientConfig::default();
config.enable_metrics = true;
let config = ClientConfig { enable_metrics: true, ..Default::default() };
let grpc = YellowstoneGrpc::new_with_config(
std::env::var("GRPC_ENDPOINT")
+6 -7
View File
@@ -16,9 +16,11 @@ async fn test_shreds() -> Result<(), Box<dyn std::error::Error>> {
println!("Subscribing to ShredStream events...");
// Create low-latency configuration.
let mut config = StreamClientConfig::default();
// Metrics add overhead; enable explicitly with STREAMER_ENABLE_METRICS=1.
config.enable_metrics = std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1");
let config = StreamClientConfig {
enable_metrics: std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1"),
..Default::default()
};
let shred_stream =
ShredStreamGrpc::new_with_config("http://127.0.0.1:10800".to_string(), config).await?;
@@ -57,11 +59,8 @@ fn create_event_callback() -> impl Fn(DexEvent) {
event.metadata().event_type,
event.metadata().tx_index
);
match event {
DexEvent::BlockMetaEvent(e) => {
println!("BlockMetaEvent: {:?}", e.metadata.handle_us);
}
_ => {}
if let DexEvent::BlockMetaEvent(e) = event {
println!("BlockMetaEvent: {:?}", e.metadata.handle_us);
}
}
}
+4 -2
View File
@@ -18,9 +18,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn test_grpc() -> Result<(), Box<dyn std::error::Error>> {
println!("Subscribing to Yellowstone gRPC events...");
// Create low-latency configuration.
let mut config: ClientConfig = ClientConfig::default();
// Metrics add overhead; enable explicitly with STREAMER_ENABLE_METRICS=1.
config.enable_metrics = std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1");
let config = ClientConfig {
enable_metrics: std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1"),
..Default::default()
};
let grpc = YellowstoneGrpc::new_with_config(
"https://solana-yellowstone-grpc.publicnode.com:443".to_string(),
None,
+6 -5
View File
@@ -18,9 +18,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn test_grpc() -> Result<(), Box<dyn std::error::Error>> {
println!("Subscribing to Yellowstone gRPC events...");
// Create low-latency configuration.
let mut config: ClientConfig = ClientConfig::default();
// Metrics add overhead; enable explicitly with STREAMER_ENABLE_METRICS=1.
config.enable_metrics = std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1");
let config = ClientConfig {
enable_metrics: std::env::var("STREAMER_ENABLE_METRICS").as_deref() == Ok("1"),
..Default::default()
};
let grpc = YellowstoneGrpc::new_with_config(
"https://solana-yellowstone-grpc.publicnode.com:443".to_string(),
None,
@@ -80,10 +82,9 @@ async fn test_grpc() -> Result<(), Box<dyn std::error::Error>> {
}
fn create_event_callback() -> impl Fn(DexEvent) {
|event: DexEvent| match event {
DexEvent::TokenInfoEvent(e) => {
|event: DexEvent| {
if let DexEvent::TokenInfoEvent(e) = event {
println!("TokenInfo pubkey={} decimals={} supply={}", e.pubkey, e.decimals, e.supply);
}
_ => {}
}
}
+2 -3
View File
@@ -69,8 +69,7 @@ pub fn parse_grpc_transaction_events(
let recv_us = transaction_pretty.recv_us;
let grpc_tx = transaction_pretty.grpc_tx;
let block_time_us = block_time.map(|t| t.seconds * 1_000_000 + t.nanos as i64 / 1_000);
let update =
SubscribeUpdateTransaction { slot, transaction: Some(grpc_tx), ..Default::default() };
let update = SubscribeUpdateTransaction { slot, transaction: Some(grpc_tx) };
let sdk_parse_filter = build_sdk_parse_event_filter(event_type_filter);
let sdk_events = parse_subscribe_update_transaction_low_latency(
&update,
@@ -116,7 +115,7 @@ pub async fn process_grpc_transaction(
AccountParseResult::Event(mut event) => {
event.metadata_mut().handle_us = elapsed_micros_since(account_pretty.recv_us);
let processing_time_us = event.metadata().handle_us as f64;
callback(event);
callback(*event);
update_metrics(MetricsEventType::Account, 1, processing_time_us);
return Ok(());
}
+8 -2
View File
@@ -194,6 +194,12 @@ impl PerformanceMetrics {
}
}
impl Default for PerformanceMetrics {
fn default() -> Self {
Self::new()
}
}
/// High-performance metrics system
#[derive(Debug)]
pub struct HighPerformanceMetrics {
@@ -525,7 +531,7 @@ impl MetricsManager {
let new_count = GLOBAL_METRICS.dropped_events_count.fetch_add(1, Ordering::Relaxed) + 1;
// 每丢弃1000个事件记录一次警告日志
if new_count % 1000 == 0 {
if new_count.is_multiple_of(1000) {
log::debug!("Dropped events count reached: {}", new_count);
}
}
@@ -547,7 +553,7 @@ impl MetricsManager {
}
// 每丢弃1000个事件记录一次警告日志
if new_count % 1000 == 0 || (new_count / 1000) != ((new_count - count) / 1000) {
if new_count.is_multiple_of(1000) || (new_count / 1000) != ((new_count - count) / 1000) {
log::debug!("Dropped events count reached: {}", new_count);
}
}
+70 -36
View File
@@ -136,17 +136,18 @@ pub(crate) fn build_sdk_shred_parse_event_filter(
protocols: &[Protocol],
filter: Option<&EventTypeFilter>,
) -> Option<SdkGrpcEventTypeFilter> {
if protocols.is_empty() {
return build_sdk_parse_event_filter(filter);
}
if let Some(f) = filter.filter(|f| !f.include.is_empty()) {
if let Some(exact) = build_sdk_parse_event_filter(Some(f)) {
return Some(exact);
}
if !f.include_transaction_event() {
return Some(SdkGrpcEventTypeFilter::include_only(Vec::new()));
}
if protocols.is_empty() {
return build_sdk_parse_event_filter(Some(f));
}
if let Some(exact) = build_sdk_parse_event_filter(Some(f)) {
return Some(exact);
}
} else if protocols.is_empty() {
return build_sdk_parse_event_filter(filter);
}
let mut raw = Vec::with_capacity(protocols.len() * 8);
@@ -229,12 +230,12 @@ fn push_streamer_event_sdk_grpc_types(
St::PumpSwapDeposit => out.push(Sdk::PumpSwapLiquidityAdded),
St::PumpSwapWithdraw => out.push(Sdk::PumpSwapLiquidityRemoved),
St::BonkBuyExactIn | St::BonkBuyExactOut | St::BonkSellExactIn | St::BonkSellExactOut => {
out.push(Sdk::BonkTrade)
out.push(Sdk::RaydiumLaunchlabTrade)
}
St::BonkInitialize | St::BonkInitializeV2 | St::BonkInitializeWithToken2022 => {
out.push(Sdk::BonkPoolCreate)
out.push(Sdk::RaydiumLaunchlabPoolCreate)
}
St::BonkMigrateToAmm => out.push(Sdk::BonkMigrateAmm),
St::BonkMigrateToAmm => out.push(Sdk::RaydiumLaunchlabMigrateAmm),
St::RaydiumCpmmSwapBaseInput | St::RaydiumCpmmSwapBaseOutput => {
out.push(Sdk::RaydiumCpmmSwap)
}
@@ -278,8 +279,12 @@ fn push_streamer_event_sdk_grpc_types(
St::MeteoraDammV2Swap | St::MeteoraDammV2Swap2 => out.push(Sdk::MeteoraDammV2Swap),
St::MeteoraDammV2AddLiquidity => out.push(Sdk::MeteoraDammV2AddLiquidity),
St::MeteoraDammV2RemoveLiquidity => out.push(Sdk::MeteoraDammV2RemoveLiquidity),
St::MeteoraDammV2InitializePool => out.push(Sdk::MeteoraDammV2InitializePool),
St::MeteoraDammV2CreatePosition => out.push(Sdk::MeteoraDammV2CreatePosition),
St::MeteoraDammV2ClosePosition => out.push(Sdk::MeteoraDammV2ClosePosition),
St::MeteoraDbcSwap => out.push(Sdk::MeteoraDbcSwap),
St::MeteoraDbcInitializePool => out.push(Sdk::MeteoraDbcInitializePool),
St::MeteoraDbcCurveComplete => out.push(Sdk::MeteoraDbcCurveComplete),
St::MeteoraDlmmSwap => out.push(Sdk::MeteoraDlmmSwap),
St::MeteoraDlmmAddLiquidity => out.push(Sdk::MeteoraDlmmAddLiquidity),
St::MeteoraDlmmRemoveLiquidity => out.push(Sdk::MeteoraDlmmRemoveLiquidity),
@@ -302,6 +307,16 @@ fn push_streamer_event_sdk_grpc_types(
}
St::AccountPumpSwapGlobalConfig => out.push(Sdk::AccountPumpSwapGlobalConfig),
St::AccountPumpSwapPool => out.push(Sdk::AccountPumpSwapPool),
St::AccountRaydiumClmmAmmConfig => out.push(Sdk::AccountRaydiumClmmAmmConfig),
St::AccountRaydiumClmmPoolState => out.push(Sdk::AccountRaydiumClmmPoolState),
St::AccountRaydiumClmmTickArrayState => out.push(Sdk::AccountRaydiumClmmTickArrayState),
St::AccountRaydiumCpmmAmmConfig => out.push(Sdk::AccountRaydiumCpmmAmmConfig),
St::AccountRaydiumCpmmPoolState => out.push(Sdk::AccountRaydiumCpmmPoolState),
St::AccountOrcaWhirlpool => out.push(Sdk::AccountOrcaWhirlpool),
St::AccountOrcaPosition => out.push(Sdk::AccountOrcaPosition),
St::AccountOrcaTickArray => out.push(Sdk::AccountOrcaTickArray),
St::AccountOrcaFeeTier => out.push(Sdk::AccountOrcaFeeTier),
St::AccountOrcaWhirlpoolsConfig => out.push(Sdk::AccountOrcaWhirlpoolsConfig),
_ => return false,
}
true
@@ -351,9 +366,11 @@ fn push_protocol_sdk_grpc_event_types(protocol: &Protocol, out: &mut Vec<SdkGrpc
Sdk::PumpSwapLiquidityAdded,
Sdk::PumpSwapLiquidityRemoved,
]),
StProtocol::Bonk | StProtocol::RaydiumLaunchpad => {
out.extend_from_slice(&[Sdk::BonkTrade, Sdk::BonkPoolCreate, Sdk::BonkMigrateAmm])
}
StProtocol::Bonk | StProtocol::RaydiumLaunchpad => out.extend_from_slice(&[
Sdk::RaydiumLaunchlabTrade,
Sdk::RaydiumLaunchlabPoolCreate,
Sdk::RaydiumLaunchlabMigrateAmm,
]),
StProtocol::RaydiumCpmm => out.extend_from_slice(&[
Sdk::RaydiumCpmmSwap,
Sdk::RaydiumCpmmDeposit,
@@ -390,9 +407,15 @@ fn push_protocol_sdk_grpc_event_types(protocol: &Protocol, out: &mut Vec<SdkGrpc
Sdk::MeteoraDammV2Swap,
Sdk::MeteoraDammV2AddLiquidity,
Sdk::MeteoraDammV2RemoveLiquidity,
Sdk::MeteoraDammV2InitializePool,
Sdk::MeteoraDammV2CreatePosition,
Sdk::MeteoraDammV2ClosePosition,
]),
StProtocol::MeteoraDbc => out.extend_from_slice(&[
Sdk::MeteoraDbcSwap,
Sdk::MeteoraDbcInitializePool,
Sdk::MeteoraDbcCurveComplete,
]),
StProtocol::OrcaWhirlpool => out.extend_from_slice(&[
Sdk::OrcaWhirlpoolSwap,
Sdk::OrcaWhirlpoolLiquidityIncreased,
@@ -499,11 +522,7 @@ mod tests {
#[test]
fn exclude_blocks_even_when_include_empty() {
let f = EventTypeFilter {
include: vec![],
exclude: vec![EventType::PumpFunSell],
..Default::default()
};
let f = EventTypeFilter { include: vec![], exclude: vec![EventType::PumpFunSell] };
let ev = DexEvent::ParserSdkErrorEvent(ParserSdkErrorEvent {
metadata: mk_meta(EventType::PumpFunSell),
message: "x".into(),
@@ -528,7 +547,6 @@ mod tests {
let f = EventTypeFilter {
include: vec![EventType::PumpFunBuy, EventType::PumpFunSell],
exclude: vec![EventType::PumpFunSell],
..Default::default()
};
let buy = DexEvent::ParserSdkErrorEvent(ParserSdkErrorEvent {
metadata: mk_meta(EventType::PumpFunBuy),
@@ -544,11 +562,7 @@ mod tests {
#[test]
fn build_sdk_filter_exclude_only_pumpfun_sell() {
let f = EventTypeFilter {
include: vec![],
exclude: vec![EventType::PumpFunSell],
..Default::default()
};
let f = EventTypeFilter { include: vec![], exclude: vec![EventType::PumpFunSell] };
let sdk_f = build_sdk_parse_event_filter(Some(&f)).expect("mapped");
assert!(sdk_f.should_include(SdkGrpcEventType::PumpFunBuy));
assert!(!sdk_f.should_include(SdkGrpcEventType::PumpFunSell));
@@ -725,8 +739,12 @@ mod tests {
EventType::MeteoraDammV2Swap2,
EventType::MeteoraDammV2AddLiquidity,
EventType::MeteoraDammV2RemoveLiquidity,
EventType::MeteoraDammV2InitializePool,
EventType::MeteoraDammV2CreatePosition,
EventType::MeteoraDammV2ClosePosition,
EventType::MeteoraDbcSwap,
EventType::MeteoraDbcInitializePool,
EventType::MeteoraDbcCurveComplete,
EventType::MeteoraDlmmSwap,
EventType::MeteoraDlmmAddLiquidity,
EventType::MeteoraDlmmRemoveLiquidity,
@@ -746,6 +764,16 @@ mod tests {
EventType::AccountPumpFunUserVolumeAccumulator,
EventType::AccountPumpSwapGlobalConfig,
EventType::AccountPumpSwapPool,
EventType::AccountRaydiumClmmAmmConfig,
EventType::AccountRaydiumClmmPoolState,
EventType::AccountRaydiumClmmTickArrayState,
EventType::AccountRaydiumCpmmAmmConfig,
EventType::AccountRaydiumCpmmPoolState,
EventType::AccountOrcaWhirlpool,
EventType::AccountOrcaPosition,
EventType::AccountOrcaTickArray,
EventType::AccountOrcaFeeTier,
EventType::AccountOrcaWhirlpoolsConfig,
];
for event_type in sdk_filter_backed {
@@ -760,7 +788,10 @@ mod tests {
#[test]
fn build_sdk_filter_none_when_public_sdk_filter_enum_cannot_express_requested_type() {
let f = EventTypeFilter {
include: vec![EventType::PumpFunBuy, EventType::MeteoraDammV2InitializePool],
include: vec![
EventType::PumpFunBuy,
EventType::MeteoraDammV2InitializeCustomizablePool,
],
..Default::default()
};
assert!(build_sdk_parse_event_filter(Some(&f)).is_none());
@@ -769,7 +800,7 @@ mod tests {
#[test]
fn build_sdk_shred_filter_falls_back_to_protocol_group_for_sdk_enum_gap() {
let f = EventTypeFilter {
include: vec![EventType::MeteoraDammV2InitializePool],
include: vec![EventType::MeteoraDammV2InitializeCustomizablePool],
..Default::default()
};
let sdk_f =
@@ -792,12 +823,20 @@ mod tests {
}
#[test]
fn build_sdk_filter_exclude_only_orca_maps_upstream() {
fn build_sdk_shred_filter_skips_transaction_parse_for_account_only_without_protocols() {
let f = EventTypeFilter {
include: vec![],
exclude: vec![EventType::OrcaWhirlpoolSwap],
include: vec![EventType::AccountRaydiumClmmPoolState],
..Default::default()
};
let sdk_f = build_sdk_shred_parse_event_filter(&[], Some(&f)).unwrap();
assert!(!sdk_f.should_include(SdkGrpcEventType::RaydiumClmmSwap));
assert!(!sdk_f.should_include(SdkGrpcEventType::PumpFunBuy));
}
#[test]
fn build_sdk_filter_exclude_only_orca_maps_upstream() {
let f = EventTypeFilter { include: vec![], exclude: vec![EventType::OrcaWhirlpoolSwap] };
let sdk_f = build_sdk_parse_event_filter(Some(&f)).expect("mapped");
assert!(!sdk_f.should_include(SdkGrpcEventType::OrcaWhirlpoolSwap));
assert!(sdk_f.should_include(SdkGrpcEventType::PumpFunBuy));
@@ -807,19 +846,14 @@ mod tests {
fn build_sdk_filter_exclude_only_none_when_only_sdk_filter_enum_gap() {
let f = EventTypeFilter {
include: vec![],
exclude: vec![EventType::MeteoraDammV2InitializePool],
..Default::default()
exclude: vec![EventType::MeteoraDammV2InitializeCustomizablePool],
};
assert!(build_sdk_parse_event_filter(Some(&f)).is_none());
}
#[test]
fn build_sdk_filter_exclude_only_none_when_only_unmapped_types() {
let f = EventTypeFilter {
include: vec![],
exclude: vec![EventType::SetComputeUnitLimit],
..Default::default()
};
let f = EventTypeFilter { include: vec![], exclude: vec![EventType::SetComputeUnitLimit] };
assert!(build_sdk_parse_event_filter(Some(&f)).is_none());
}
}
@@ -49,6 +49,7 @@ pub enum ProtocolType {
RaydiumClmm,
RaydiumAmmV4,
MeteoraDammV2,
MeteoraDbc,
OrcaWhirlpool,
MeteoraPools,
MeteoraDlmm,
@@ -153,6 +154,11 @@ pub enum EventType {
MeteoraDammV2AddLiquidity,
MeteoraDammV2RemoveLiquidity,
// Meteora DBC
MeteoraDbcSwap,
MeteoraDbcInitializePool,
MeteoraDbcCurveComplete,
// Orca Whirlpool
OrcaWhirlpoolSwap,
OrcaWhirlpoolLiquidityIncreased,
@@ -196,6 +202,11 @@ pub enum EventType {
AccountRaydiumClmmTickArrayState,
AccountRaydiumCpmmAmmConfig,
AccountRaydiumCpmmPoolState,
AccountOrcaWhirlpool,
AccountOrcaPosition,
AccountOrcaTickArray,
AccountOrcaFeeTier,
AccountOrcaWhirlpoolsConfig,
NonceAccount,
TokenAccount,
@@ -228,6 +239,11 @@ pub const ACCOUNT_EVENT_TYPES: &[EventType] = &[
EventType::AccountRaydiumClmmTickArrayState,
EventType::AccountRaydiumCpmmAmmConfig,
EventType::AccountRaydiumCpmmPoolState,
EventType::AccountOrcaWhirlpool,
EventType::AccountOrcaPosition,
EventType::AccountOrcaTickArray,
EventType::AccountOrcaFeeTier,
EventType::AccountOrcaWhirlpoolsConfig,
EventType::TokenAccount,
EventType::TokenInfo,
EventType::NonceAccount,
+10 -3
View File
@@ -70,7 +70,7 @@ impl EventDispatcher {
}
Protocol::PumpFees => all_inner::pump_fees::parse(&disc, inner_instruction_data, pm),
Protocol::Bonk | Protocol::RaydiumLaunchpad => {
all_inner::bonk::parse(&disc, inner_instruction_data, pm)
all_inner::raydium_launchlab::parse(&disc, inner_instruction_data, pm)
}
Protocol::RaydiumCpmm => {
all_inner::raydium_cpmm::parse(&disc, inner_instruction_data, pm)
@@ -86,6 +86,8 @@ impl EventDispatcher {
Protocol::MeteoraDammV2 => {
all_inner::meteora_damm::parse(&disc, inner_instruction_data, pm)
}
// Meteora DBC is currently log-side in sol-parser-sdk; direct inner dispatch is absent.
Protocol::MeteoraDbc => None,
Protocol::OrcaWhirlpool => all_inner::orca::parse(&disc, inner_instruction_data, pm),
Protocol::MeteoraPools => {
all_inner::meteora_amm::parse(&disc, inner_instruction_data, pm)
@@ -108,7 +110,7 @@ impl EventDispatcher {
Some(Protocol::PumpFees)
} else if program_id == &program_ids::PUMPSWAP_PROGRAM_ID {
Some(Protocol::PumpSwap)
} else if program_id == &program_ids::BONK_PROGRAM_ID {
} else if program_id == &program_ids::RAYDIUM_LAUNCHLAB_PROGRAM_ID {
Some(Protocol::Bonk)
} else if program_id == &program_ids::RAYDIUM_CPMM_PROGRAM_ID {
Some(Protocol::RaydiumCpmm)
@@ -118,6 +120,8 @@ impl EventDispatcher {
Some(Protocol::RaydiumAmmV4)
} else if program_id == &program_ids::METEORA_DAMM_V2_PROGRAM_ID {
Some(Protocol::MeteoraDammV2)
} else if program_id == &program_ids::METEORA_DBC_PROGRAM_ID {
Some(Protocol::MeteoraDbc)
} else if program_id == &program_ids::ORCA_WHIRLPOOL_PROGRAM_ID {
Some(Protocol::OrcaWhirlpool)
} else if program_id == &program_ids::METEORA_POOLS_PROGRAM_ID {
@@ -148,11 +152,14 @@ impl EventDispatcher {
Protocol::PumpFun => program_ids::PUMPFUN_PROGRAM_ID,
Protocol::PumpFees => program_ids::PUMP_FEES_PROGRAM_ID,
Protocol::PumpSwap => program_ids::PUMPSWAP_PROGRAM_ID,
Protocol::Bonk | Protocol::RaydiumLaunchpad => program_ids::BONK_PROGRAM_ID,
Protocol::Bonk | Protocol::RaydiumLaunchpad => {
program_ids::RAYDIUM_LAUNCHLAB_PROGRAM_ID
}
Protocol::RaydiumCpmm => program_ids::RAYDIUM_CPMM_PROGRAM_ID,
Protocol::RaydiumClmm => program_ids::RAYDIUM_CLMM_PROGRAM_ID,
Protocol::RaydiumAmmV4 => program_ids::RAYDIUM_AMM_V4_PROGRAM_ID,
Protocol::MeteoraDammV2 => program_ids::METEORA_DAMM_V2_PROGRAM_ID,
Protocol::MeteoraDbc => program_ids::METEORA_DBC_PROGRAM_ID,
Protocol::OrcaWhirlpool => program_ids::ORCA_WHIRLPOOL_PROGRAM_ID,
Protocol::MeteoraPools => program_ids::METEORA_POOLS_PROGRAM_ID,
Protocol::MeteoraDlmm => program_ids::METEORA_DLMM_PROGRAM_ID,
@@ -9,6 +9,7 @@ pub(crate) mod helpers;
pub struct EventParser;
impl EventParser {
#[allow(clippy::too_many_arguments)]
pub async fn parse_grpc_transaction(
protocols: &[crate::streaming::event_parser::Protocol],
event_type_filter: Option<&crate::streaming::event_parser::common::filter::EventTypeFilter>,
@@ -32,7 +33,6 @@ impl EventParser {
let update = yellowstone_grpc_proto::geyser::SubscribeUpdateTransaction {
slot: slot.unwrap_or(0),
transaction: Some(grpc_tx),
..Default::default()
};
let sdk_parse_filter =
crate::streaming::event_parser::common::filter::build_sdk_parse_event_filter(
@@ -1,3 +1,5 @@
#![allow(clippy::single_match)]
use crate::streaming::event_parser::DexEvent;
use solana_sdk::{pubkey, pubkey::Pubkey};
+26 -7
View File
@@ -14,14 +14,16 @@ use crate::streaming::event_parser::protocols::raydium_amm_v4::events::*;
use crate::streaming::event_parser::protocols::raydium_clmm::events::*;
use crate::streaming::event_parser::protocols::raydium_cpmm::events::*;
use crate::streaming::event_parser::protocols::sol_parser_forward::events::{
MeteoraDbcCurveCompleteEvent, MeteoraDbcInitializePoolEvent, MeteoraDbcSwapEvent,
MeteoraDlmmAddLiquidityEvent, MeteoraDlmmClaimFeeEvent, MeteoraDlmmClosePositionEvent,
MeteoraDlmmCreatePositionEvent, MeteoraDlmmInitializeBinArrayEvent,
MeteoraDlmmInitializePoolEvent, MeteoraDlmmRemoveLiquidityEvent, MeteoraDlmmSwapEvent,
MeteoraPoolsAddLiquidityEvent, MeteoraPoolsBootstrapLiquidityEvent,
MeteoraPoolsPoolCreatedEvent, MeteoraPoolsRemoveLiquidityEvent, MeteoraPoolsSetPoolFeesEvent,
MeteoraPoolsSwapEvent, OrcaWhirlpoolLiquidityDecreasedEvent,
MeteoraPoolsSwapEvent, OrcaFeeTierAccountEvent, OrcaPositionAccountEvent,
OrcaTickArrayAccountEvent, OrcaWhirlpoolAccountEvent, OrcaWhirlpoolLiquidityDecreasedEvent,
OrcaWhirlpoolLiquidityIncreasedEvent, OrcaWhirlpoolPoolInitializedEvent,
OrcaWhirlpoolSwapEvent, ParserSdkErrorEvent,
OrcaWhirlpoolSwapEvent, OrcaWhirlpoolsConfigAccountEvent, ParserSdkErrorEvent,
};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
@@ -96,17 +98,17 @@ pub enum DexEvent {
RaydiumClmmCreatePoolEvent(RaydiumClmmCreatePoolEvent),
RaydiumClmmOpenPositionWithToken22NftEvent(RaydiumClmmOpenPositionWithToken22NftEvent),
RaydiumClmmOpenPositionV2Event(RaydiumClmmOpenPositionV2Event),
RaydiumClmmAmmConfigAccountEvent(RaydiumClmmAmmConfigAccountEvent),
RaydiumClmmPoolStateAccountEvent(RaydiumClmmPoolStateAccountEvent),
RaydiumClmmTickArrayStateAccountEvent(RaydiumClmmTickArrayStateAccountEvent),
RaydiumClmmAmmConfigAccountEvent(Box<RaydiumClmmAmmConfigAccountEvent>),
RaydiumClmmPoolStateAccountEvent(Box<RaydiumClmmPoolStateAccountEvent>),
RaydiumClmmTickArrayStateAccountEvent(Box<RaydiumClmmTickArrayStateAccountEvent>),
// Raydium CPMM events
RaydiumCpmmSwapEvent(RaydiumCpmmSwapEvent),
RaydiumCpmmDepositEvent(RaydiumCpmmDepositEvent),
RaydiumCpmmWithdrawEvent(RaydiumCpmmWithdrawEvent),
RaydiumCpmmInitializeEvent(RaydiumCpmmInitializeEvent),
RaydiumCpmmAmmConfigAccountEvent(RaydiumCpmmAmmConfigAccountEvent),
RaydiumCpmmPoolStateAccountEvent(RaydiumCpmmPoolStateAccountEvent),
RaydiumCpmmAmmConfigAccountEvent(Box<RaydiumCpmmAmmConfigAccountEvent>),
RaydiumCpmmPoolStateAccountEvent(Box<RaydiumCpmmPoolStateAccountEvent>),
// Meteora DAMM v2 events
MeteoraDammV2SwapEvent(MeteoraDammV2SwapEvent),
@@ -122,10 +124,19 @@ pub enum DexEvent {
MeteoraDammV2CreatePositionEvent(MeteoraDammV2CreatePositionEvent),
MeteoraDammV2ClosePositionEvent(MeteoraDammV2ClosePositionEvent),
MeteoraDbcSwapEvent(MeteoraDbcSwapEvent),
MeteoraDbcInitializePoolEvent(MeteoraDbcInitializePoolEvent),
MeteoraDbcCurveCompleteEvent(MeteoraDbcCurveCompleteEvent),
OrcaWhirlpoolSwapEvent(OrcaWhirlpoolSwapEvent),
OrcaWhirlpoolLiquidityIncreasedEvent(OrcaWhirlpoolLiquidityIncreasedEvent),
OrcaWhirlpoolLiquidityDecreasedEvent(OrcaWhirlpoolLiquidityDecreasedEvent),
OrcaWhirlpoolPoolInitializedEvent(OrcaWhirlpoolPoolInitializedEvent),
OrcaWhirlpoolAccountEvent(Box<OrcaWhirlpoolAccountEvent>),
OrcaPositionAccountEvent(Box<OrcaPositionAccountEvent>),
OrcaTickArrayAccountEvent(Box<OrcaTickArrayAccountEvent>),
OrcaFeeTierAccountEvent(Box<OrcaFeeTierAccountEvent>),
OrcaWhirlpoolsConfigAccountEvent(Box<OrcaWhirlpoolsConfigAccountEvent>),
MeteoraPoolsSwapEvent(MeteoraPoolsSwapEvent),
MeteoraPoolsAddLiquidityEvent(MeteoraPoolsAddLiquidityEvent),
@@ -256,10 +267,18 @@ impl_dex_event_metadata!(
MeteoraDammV2RemoveLiquidityEvent,
MeteoraDammV2CreatePositionEvent,
MeteoraDammV2ClosePositionEvent,
MeteoraDbcSwapEvent,
MeteoraDbcInitializePoolEvent,
MeteoraDbcCurveCompleteEvent,
OrcaWhirlpoolSwapEvent,
OrcaWhirlpoolLiquidityIncreasedEvent,
OrcaWhirlpoolLiquidityDecreasedEvent,
OrcaWhirlpoolPoolInitializedEvent,
OrcaWhirlpoolAccountEvent,
OrcaPositionAccountEvent,
OrcaTickArrayAccountEvent,
OrcaFeeTierAccountEvent,
OrcaWhirlpoolsConfigAccountEvent,
MeteoraPoolsSwapEvent,
MeteoraPoolsAddLiquidityEvent,
MeteoraPoolsRemoveLiquidityEvent,
@@ -3,7 +3,7 @@ use crate::streaming::event_parser::{
};
use solana_sdk::pubkey::Pubkey;
pub use sol_parser_sdk::instr::program_ids::BONK_PROGRAM_ID;
pub use sol_parser_sdk::instr::program_ids::RAYDIUM_LAUNCHLAB_PROGRAM_ID as BONK_PROGRAM_ID;
pub fn parse_bonk_instruction_data(
discriminator: &[u8],
@@ -32,32 +32,22 @@ pub struct VestingParams {
pub unlock_period: u64,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
pub enum AmmFeeOn {
#[default]
QuoteToken,
BothToken,
}
impl Default for AmmFeeOn {
fn default() -> Self {
Self::QuoteToken
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
#[borsh(use_discriminant = true)]
#[repr(u8)]
pub enum AmmCreatorFeeOn {
#[default]
QuoteToken = 0,
BothToken = 1,
}
impl Default for AmmCreatorFeeOn {
fn default() -> Self {
Self::QuoteToken
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
pub struct ConstantCurve {
pub supply: u64,
@@ -170,7 +160,7 @@ impl Default for PoolState {
}
}
pub const POOL_STATE_SIZE: usize = 8 + 1 * 5 + 8 * 10 + 32 * 7 + 8 * 8 + 8 * 5 + 1 + 1 + 8 + 54;
pub const POOL_STATE_SIZE: usize = 8 + 5 + 8 * 10 + 32 * 7 + 8 * 8 + 8 * 5 + 1 + 1 + 8 + 54;
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
pub struct GlobalConfig {
pub epoch: u64,
@@ -168,10 +168,10 @@ pub mod discriminators {
// 指令鉴别器
pub const SWAP_BASE_IN: &[u8] = &[9];
pub const SWAP_BASE_OUT: &[u8] = &[11];
pub const DEPOSIT: &[u8] = &[03];
pub const INITIALIZE2: &[u8] = &[01];
pub const WITHDRAW: &[u8] = &[04];
pub const WITHDRAW_PNL: &[u8] = &[07];
pub const DEPOSIT: &[u8] = &[3];
pub const INITIALIZE2: &[u8] = &[1];
pub const WITHDRAW: &[u8] = &[4];
pub const WITHDRAW_PNL: &[u8] = &[7];
/// 池信息鉴别器
pub const AMM_INFO: &[u8] = &[6];
@@ -105,7 +105,7 @@ pub struct PoolState {
pub const POOL_STATE_SIZE: usize = 1536;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
pub struct TickState {
pub tick: i32,
pub liquidity_net: i128,
@@ -120,24 +120,6 @@ pub struct TickState {
pub padding: [u32; 3],
}
impl Default for TickState {
fn default() -> Self {
Self {
tick: 0,
liquidity_net: 0,
liquidity_gross: 0,
fee_growth_outside0_x64: 0,
fee_growth_outside1_x64: 0,
reward_growths_outside_x64: [0; 3],
order_phase: 0,
orders_amount: 0,
part_filled_orders_remaining: 0,
unfilled_ratio_x64: 0,
padding: [0; 3],
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
pub struct TickArrayState {
pub pool_id: Pubkey,
@@ -69,6 +69,185 @@ pub struct OrcaWhirlpoolPoolInitializedEvent {
pub initial_sqrt_price: u128,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaWhirlpoolAccountEvent {
pub metadata: EventMetadata,
pub pubkey: Pubkey,
pub executable: bool,
pub lamports: u64,
pub owner: Pubkey,
pub rent_epoch: u64,
pub whirlpool: OrcaWhirlpoolAccount,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaWhirlpoolAccount {
pub whirlpools_config: Pubkey,
pub whirlpool_bump: u8,
pub tick_spacing: u16,
pub tick_spacing_seed: [u8; 2],
pub fee_rate: u16,
pub protocol_fee_rate: u16,
pub liquidity: u128,
pub sqrt_price: u128,
pub tick_current_index: i32,
pub protocol_fee_owed_a: u64,
pub protocol_fee_owed_b: u64,
pub token_mint_a: Pubkey,
pub token_vault_a: Pubkey,
pub fee_growth_global_a: u128,
pub token_mint_b: Pubkey,
pub token_vault_b: Pubkey,
pub fee_growth_global_b: u128,
pub reward_last_updated_timestamp: u64,
pub reward_infos: [OrcaWhirlpoolRewardInfo; 3],
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaWhirlpoolRewardInfo {
pub mint: Pubkey,
pub vault: Pubkey,
pub authority: Pubkey,
pub emissions_per_second_x64: u128,
pub growth_global_x64: u128,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaPositionAccountEvent {
pub metadata: EventMetadata,
pub pubkey: Pubkey,
pub executable: bool,
pub lamports: u64,
pub owner: Pubkey,
pub rent_epoch: u64,
pub position: OrcaPositionAccount,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaPositionAccount {
pub whirlpool: Pubkey,
pub position_mint: Pubkey,
pub liquidity: u128,
pub tick_lower_index: i32,
pub tick_upper_index: i32,
pub fee_growth_checkpoint_a: u128,
pub fee_owed_a: u64,
pub fee_growth_checkpoint_b: u128,
pub fee_owed_b: u64,
pub reward_infos: [OrcaPositionRewardInfo; 3],
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaPositionRewardInfo {
pub growth_inside_checkpoint: u128,
pub amount_owed: u64,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaTickArrayAccountEvent {
pub metadata: EventMetadata,
pub pubkey: Pubkey,
pub executable: bool,
pub lamports: u64,
pub owner: Pubkey,
pub rent_epoch: u64,
pub tick_array: OrcaTickArrayAccount,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaTickArrayAccount {
pub start_tick_index: i32,
pub ticks: Vec<OrcaTick>,
pub whirlpool: Pubkey,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaTick {
pub initialized: bool,
pub liquidity_net: i128,
pub liquidity_gross: u128,
pub fee_growth_outside_a: u128,
pub fee_growth_outside_b: u128,
pub reward_growths_outside: [u128; 3],
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaFeeTierAccountEvent {
pub metadata: EventMetadata,
pub pubkey: Pubkey,
pub executable: bool,
pub lamports: u64,
pub owner: Pubkey,
pub rent_epoch: u64,
pub fee_tier: OrcaFeeTierAccount,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaFeeTierAccount {
pub whirlpools_config: Pubkey,
pub tick_spacing: u16,
pub default_fee_rate: u16,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaWhirlpoolsConfigAccountEvent {
pub metadata: EventMetadata,
pub pubkey: Pubkey,
pub executable: bool,
pub lamports: u64,
pub owner: Pubkey,
pub rent_epoch: u64,
pub config: OrcaWhirlpoolsConfigAccount,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OrcaWhirlpoolsConfigAccount {
pub fee_authority: Pubkey,
pub collect_protocol_fees_authority: Pubkey,
pub reward_emissions_super_authority: Pubkey,
pub default_protocol_fee_rate: u16,
}
// --- Meteora DBC ---
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct MeteoraDbcSwapEvent {
pub metadata: EventMetadata,
pub pool: Pubkey,
pub config: Pubkey,
pub trade_direction: u8,
pub has_referral: bool,
pub amount_in: u64,
pub minimum_amount_out: u64,
pub actual_input_amount: u64,
pub output_amount: u64,
pub next_sqrt_price: u128,
pub trading_fee: u64,
pub protocol_fee: u64,
pub referral_fee: u64,
pub current_timestamp: u64,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct MeteoraDbcInitializePoolEvent {
pub metadata: EventMetadata,
pub pool: Pubkey,
pub config: Pubkey,
pub creator: Pubkey,
pub base_mint: Pubkey,
pub pool_type: u8,
pub activation_point: u64,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct MeteoraDbcCurveCompleteEvent {
pub metadata: EventMetadata,
pub pool: Pubkey,
pub config: Pubkey,
pub base_reserve: u64,
pub quote_reserve: u64,
}
// --- Meteora Pools ---
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
+10 -3
View File
@@ -1,8 +1,9 @@
use anyhow::{anyhow, Result};
use sol_parser_sdk::instr::program_ids::{
BONK_PROGRAM_ID, METEORA_DAMM_V2_PROGRAM_ID, METEORA_DLMM_PROGRAM_ID, METEORA_POOLS_PROGRAM_ID,
ORCA_WHIRLPOOL_PROGRAM_ID, PUMPFUN_PROGRAM_ID, PUMPSWAP_PROGRAM_ID, PUMP_FEES_PROGRAM_ID,
RAYDIUM_AMM_V4_PROGRAM_ID, RAYDIUM_CLMM_PROGRAM_ID, RAYDIUM_CPMM_PROGRAM_ID,
METEORA_DAMM_V2_PROGRAM_ID, METEORA_DBC_PROGRAM_ID, METEORA_DLMM_PROGRAM_ID,
METEORA_POOLS_PROGRAM_ID, ORCA_WHIRLPOOL_PROGRAM_ID, PUMPFUN_PROGRAM_ID, PUMPSWAP_PROGRAM_ID,
PUMP_FEES_PROGRAM_ID, RAYDIUM_AMM_V4_PROGRAM_ID, RAYDIUM_CLMM_PROGRAM_ID,
RAYDIUM_CPMM_PROGRAM_ID, RAYDIUM_LAUNCHLAB_PROGRAM_ID as BONK_PROGRAM_ID,
};
use solana_sdk::pubkey::Pubkey;
@@ -19,6 +20,7 @@ pub enum Protocol {
RaydiumClmm,
RaydiumAmmV4,
MeteoraDammV2,
MeteoraDbc,
OrcaWhirlpool,
MeteoraPools,
MeteoraDlmm,
@@ -36,6 +38,7 @@ impl Protocol {
Protocol::RaydiumClmm => vec![RAYDIUM_CLMM_PROGRAM_ID],
Protocol::RaydiumAmmV4 => vec![RAYDIUM_AMM_V4_PROGRAM_ID],
Protocol::MeteoraDammV2 => vec![METEORA_DAMM_V2_PROGRAM_ID],
Protocol::MeteoraDbc => vec![METEORA_DBC_PROGRAM_ID],
Protocol::OrcaWhirlpool => vec![ORCA_WHIRLPOOL_PROGRAM_ID],
Protocol::MeteoraPools => vec![METEORA_POOLS_PROGRAM_ID],
Protocol::MeteoraDlmm => vec![METEORA_DLMM_PROGRAM_ID],
@@ -55,6 +58,7 @@ impl std::fmt::Display for Protocol {
Protocol::RaydiumClmm => write!(f, "RaydiumClmm"),
Protocol::RaydiumAmmV4 => write!(f, "RaydiumAmmV4"),
Protocol::MeteoraDammV2 => write!(f, "MeteoraDammV2"),
Protocol::MeteoraDbc => write!(f, "MeteoraDbc"),
Protocol::OrcaWhirlpool => write!(f, "OrcaWhirlpool"),
Protocol::MeteoraPools => write!(f, "MeteoraPools"),
Protocol::MeteoraDlmm => write!(f, "MeteoraDlmm"),
@@ -77,6 +81,7 @@ impl std::str::FromStr for Protocol {
"raydiumclmm" | "raydium_clmm" => Ok(Protocol::RaydiumClmm),
"raydiumammv4" | "raydium_amm_v4" => Ok(Protocol::RaydiumAmmV4),
"meteoradammv2" | "meteoradamm_v2" | "meteora_damm_v2" => Ok(Protocol::MeteoraDammV2),
"meteoradbc" | "meteora_dbc" => Ok(Protocol::MeteoraDbc),
"orcawhirlpool" | "orca_whirlpool" | "orca" => Ok(Protocol::OrcaWhirlpool),
"meteorapools" | "meteora_pools" => Ok(Protocol::MeteoraPools),
"meteoradlmm" | "meteora_dlmm" => Ok(Protocol::MeteoraDlmm),
@@ -99,6 +104,7 @@ mod tests {
Protocol::RaydiumClmm,
Protocol::RaydiumAmmV4,
Protocol::MeteoraDammV2,
Protocol::MeteoraDbc,
Protocol::OrcaWhirlpool,
Protocol::MeteoraPools,
Protocol::MeteoraDlmm,
@@ -116,6 +122,7 @@ mod tests {
assert_eq!(Protocol::from_str("raydium_clmm").unwrap(), Protocol::RaydiumClmm);
assert_eq!(Protocol::from_str("raydium_amm_v4").unwrap(), Protocol::RaydiumAmmV4);
assert_eq!(Protocol::from_str("meteora_damm_v2").unwrap(), Protocol::MeteoraDammV2);
assert_eq!(Protocol::from_str("meteora_dbc").unwrap(), Protocol::MeteoraDbc);
assert_eq!(Protocol::from_str("orca_whirlpool").unwrap(), Protocol::OrcaWhirlpool);
assert_eq!(Protocol::from_str("meteora_pools").unwrap(), Protocol::MeteoraPools);
assert_eq!(Protocol::from_str("meteora_dlmm").unwrap(), Protocol::MeteoraDlmm);
+1 -1
View File
@@ -54,7 +54,7 @@ impl SubscriptionManager {
)> {
// When no filter is set, subscribe to block meta like before; if a filter exists,
// only keep block meta when the filter includes block-related event types.
let blocks_meta = if event_type_filter.map_or(true, |f| f.include_block_event()) {
let blocks_meta = if event_type_filter.is_none_or(|f| f.include_block_event()) {
HashMap::from([("".to_owned(), SubscribeRequestFilterBlocksMeta {})])
} else {
HashMap::new()
+2 -16
View File
@@ -11,6 +11,7 @@ use yellowstone_grpc_proto::{
pub type TransactionsFilterMap = HashMap<String, SubscribeRequestFilterTransactions>;
pub type AccountsFilterMap = HashMap<String, SubscribeRequestFilterAccounts>;
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug)]
pub enum EventPretty {
BlockMeta(BlockMetaPretty),
@@ -65,7 +66,7 @@ impl fmt::Debug for BlockMetaPretty {
}
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct TransactionPretty {
pub slot: u64,
pub tx_index: Option<u64>, // 新增:交易在slot中的索引
@@ -88,18 +89,3 @@ impl fmt::Debug for TransactionPretty {
.finish()
}
}
impl Default for TransactionPretty {
fn default() -> Self {
Self {
slot: 0,
tx_index: None,
block_hash: String::new(),
block_time: None,
signature: Signature::default(),
is_vote: false,
grpc_tx: SubscribeUpdateTransactionInfo::default(),
recv_us: 0,
}
}
}
+58 -3
View File
@@ -11,7 +11,7 @@ use super::convert_parser_event;
use super::filter::event_matches_protocol;
pub(crate) enum AccountParseResult {
Event(DexEvent),
Event(Box<DexEvent>),
Filtered,
Unsupported,
}
@@ -22,7 +22,7 @@ pub(crate) fn parse_account_event(
event_type_filter: Option<&EventTypeFilter>,
) -> Option<DexEvent> {
match parse_account_event_for_streamer(account, protocols, event_type_filter) {
AccountParseResult::Event(event) => Some(event),
AccountParseResult::Event(event) => Some(*event),
AccountParseResult::Filtered | AccountParseResult::Unsupported => None,
}
}
@@ -68,7 +68,7 @@ pub(crate) fn parse_account_event_for_streamer(
return AccountParseResult::Filtered;
}
normalize_account_event(&mut event, account);
AccountParseResult::Event(event)
AccountParseResult::Event(Box::new(event))
}
fn build_sdk_account_event_filter(filter: Option<&EventTypeFilter>) -> SdkGrpcEventTypeFilter {
@@ -124,6 +124,19 @@ fn streamer_account_event_to_sdk_types(t: &EventType) -> Vec<SdkGrpcEventType> {
EventType::AccountRaydiumClmmTickArrayState => {
vec![SdkGrpcEventType::AccountRaydiumClmmTickArrayState]
}
EventType::AccountRaydiumCpmmAmmConfig => {
vec![SdkGrpcEventType::AccountRaydiumCpmmAmmConfig]
}
EventType::AccountRaydiumCpmmPoolState => {
vec![SdkGrpcEventType::AccountRaydiumCpmmPoolState]
}
EventType::AccountOrcaWhirlpool => vec![SdkGrpcEventType::AccountOrcaWhirlpool],
EventType::AccountOrcaPosition => vec![SdkGrpcEventType::AccountOrcaPosition],
EventType::AccountOrcaTickArray => vec![SdkGrpcEventType::AccountOrcaTickArray],
EventType::AccountOrcaFeeTier => vec![SdkGrpcEventType::AccountOrcaFeeTier],
EventType::AccountOrcaWhirlpoolsConfig => {
vec![SdkGrpcEventType::AccountOrcaWhirlpoolsConfig]
}
_ => Vec::new(),
}
}
@@ -195,6 +208,48 @@ fn normalize_account_event(event: &mut DexEvent, account: &AccountPretty) {
e.owner = account.owner;
e.rent_epoch = account.rent_epoch;
}
DexEvent::RaydiumCpmmAmmConfigAccountEvent(e) => {
e.executable = account.executable;
e.lamports = account.lamports;
e.owner = account.owner;
e.rent_epoch = account.rent_epoch;
}
DexEvent::RaydiumCpmmPoolStateAccountEvent(e) => {
e.executable = account.executable;
e.lamports = account.lamports;
e.owner = account.owner;
e.rent_epoch = account.rent_epoch;
}
DexEvent::OrcaWhirlpoolAccountEvent(e) => {
e.executable = account.executable;
e.lamports = account.lamports;
e.owner = account.owner;
e.rent_epoch = account.rent_epoch;
}
DexEvent::OrcaPositionAccountEvent(e) => {
e.executable = account.executable;
e.lamports = account.lamports;
e.owner = account.owner;
e.rent_epoch = account.rent_epoch;
}
DexEvent::OrcaTickArrayAccountEvent(e) => {
e.executable = account.executable;
e.lamports = account.lamports;
e.owner = account.owner;
e.rent_epoch = account.rent_epoch;
}
DexEvent::OrcaFeeTierAccountEvent(e) => {
e.executable = account.executable;
e.lamports = account.lamports;
e.owner = account.owner;
e.rent_epoch = account.rent_epoch;
}
DexEvent::OrcaWhirlpoolsConfigAccountEvent(e) => {
e.executable = account.executable;
e.lamports = account.lamports;
e.owner = account.owner;
e.rent_epoch = account.rent_epoch;
}
_ => {}
}
}
@@ -14,7 +14,7 @@ use crate::streaming::event_parser::protocols::pumpswap::events::{
};
use crate::streaming::event_parser::protocols::pumpswap::types::{GlobalConfig, Pool};
use sol_parser_sdk::core::events::{
BonkTradeEvent as PbBonkTrade, TradeDirection as PbBonkTradeDirection,
RaydiumLaunchlabTradeEvent as PbBonkTrade, TradeDirection as PbBonkTradeDirection,
};
use solana_sdk::pubkey::Pubkey;
@@ -43,7 +43,7 @@ pub(crate) fn sdk_bonk_trade_event_type(
/// SDK Bonk trade events do not expose reserves or fee rates; keep those fields at streamer
/// defaults.
pub(crate) fn bonk_trade_from_parser(
b: sol_parser_sdk::core::events::BonkTradeEvent,
b: sol_parser_sdk::core::events::RaydiumLaunchlabTradeEvent,
meta: EventMetadata,
) -> BonkTradeEvent {
BonkTradeEvent {
@@ -71,7 +71,7 @@ pub(crate) fn bonk_trade_from_parser(
}
pub(crate) fn bonk_pool_create_from_parser(
p: sol_parser_sdk::core::events::BonkPoolCreateEvent,
p: sol_parser_sdk::core::events::RaydiumLaunchlabPoolCreateEvent,
meta: EventMetadata,
) -> BonkPoolCreateEvent {
BonkPoolCreateEvent {
@@ -93,7 +93,7 @@ pub(crate) fn bonk_pool_create_from_parser(
}
pub(crate) fn bonk_migrate_to_amm_from_parser(
m: sol_parser_sdk::core::events::BonkMigrateAmmEvent,
m: sol_parser_sdk::core::events::RaydiumLaunchlabMigrateAmmEvent,
meta: EventMetadata,
) -> BonkMigrateToAmmEvent {
BonkMigrateToAmmEvent {
+154 -12
View File
@@ -338,7 +338,7 @@ pub(crate) fn convert_parser_event(
Some(DexEvent::PumpSwapWithdrawEvent(pumpswap_liquidity_removed_to_withdraw(r, meta)))
}
PbDexEvent::BonkTrade(b) => {
PbDexEvent::RaydiumLaunchlabTrade(b) => {
let et = sdk_bonk_trade_event_type(&b);
let meta = adapt_pm(
b.metadata.clone(),
@@ -350,7 +350,7 @@ pub(crate) fn convert_parser_event(
);
Some(DexEvent::BonkTradeEvent(bonk_trade_from_parser(b, meta)))
}
PbDexEvent::BonkPoolCreate(p) => {
PbDexEvent::RaydiumLaunchlabPoolCreate(p) => {
let meta = adapt_pm(
p.metadata.clone(),
bt,
@@ -361,7 +361,7 @@ pub(crate) fn convert_parser_event(
);
Some(DexEvent::BonkPoolCreateEvent(bonk_pool_create_from_parser(p, meta)))
}
PbDexEvent::BonkMigrateAmm(m) => {
PbDexEvent::RaydiumLaunchlabMigrateAmm(m) => {
let meta = adapt_pm(
m.metadata.clone(),
bt,
@@ -422,6 +422,32 @@ pub(crate) fn convert_parser_event(
);
Some(DexEvent::RaydiumCpmmInitializeEvent(raydium_cpmm_initialize_from_parser(e, meta)))
}
PbDexEvent::RaydiumCpmmAmmConfigAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumCpmm,
EventType::AccountRaydiumCpmmAmmConfig,
raydium_cpmm_program(),
);
Some(DexEvent::RaydiumCpmmAmmConfigAccountEvent(Box::new(
raydium_cpmm_amm_config_account_from_parser(*e, meta),
)))
}
PbDexEvent::RaydiumCpmmPoolStateAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumCpmm,
EventType::AccountRaydiumCpmmPoolState,
raydium_cpmm_program(),
);
Some(DexEvent::RaydiumCpmmPoolStateAccountEvent(Box::new(
raydium_cpmm_pool_state_account_from_parser(*e, meta),
)))
}
PbDexEvent::RaydiumClmmSwap(e) => {
let meta = adapt_pm(
@@ -651,9 +677,9 @@ pub(crate) fn convert_parser_event(
EventType::AccountRaydiumClmmAmmConfig,
raydium_clmm_program(),
);
Some(DexEvent::RaydiumClmmAmmConfigAccountEvent(
raydium_clmm_amm_config_account_from_parser(e, meta),
))
Some(DexEvent::RaydiumClmmAmmConfigAccountEvent(Box::new(
raydium_clmm_amm_config_account_from_parser(*e, meta),
)))
}
PbDexEvent::RaydiumClmmPoolStateAccount(e) => {
let meta = adapt_pm(
@@ -664,9 +690,9 @@ pub(crate) fn convert_parser_event(
EventType::AccountRaydiumClmmPoolState,
raydium_clmm_program(),
);
Some(DexEvent::RaydiumClmmPoolStateAccountEvent(
raydium_clmm_pool_state_account_from_parser(e, meta),
))
Some(DexEvent::RaydiumClmmPoolStateAccountEvent(Box::new(
raydium_clmm_pool_state_account_from_parser(*e, meta),
)))
}
PbDexEvent::RaydiumClmmTickArrayStateAccount(e) => {
let meta = adapt_pm(
@@ -677,9 +703,9 @@ pub(crate) fn convert_parser_event(
EventType::AccountRaydiumClmmTickArrayState,
raydium_clmm_program(),
);
Some(DexEvent::RaydiumClmmTickArrayStateAccountEvent(
raydium_clmm_tick_array_state_account_from_parser(e, meta),
))
Some(DexEvent::RaydiumClmmTickArrayStateAccountEvent(Box::new(
raydium_clmm_tick_array_state_account_from_parser(*e, meta),
)))
}
PbDexEvent::RaydiumAmmV4Swap(e) => {
@@ -758,6 +784,19 @@ pub(crate) fn convert_parser_event(
);
Some(DexEvent::MeteoraDammV2SwapEvent(meteora_damm_v2_swap_from_parser(e, meta)))
}
PbDexEvent::MeteoraDammV2InitializePool(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDammV2,
EventType::MeteoraDammV2InitializePool,
meteora_damm_program(),
);
Some(DexEvent::MeteoraDammV2InitializePoolEvent(
meteora_damm_v2_initialize_pool_from_parser(e, meta),
))
}
PbDexEvent::MeteoraDammV2AddLiquidity(e) => {
let meta = adapt_pm(
e.metadata.clone(),
@@ -811,6 +850,44 @@ pub(crate) fn convert_parser_event(
)))
}
PbDexEvent::MeteoraDbcSwap(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDbc,
EventType::MeteoraDbcSwap,
meteora_dbc_program(),
);
Some(DexEvent::MeteoraDbcSwapEvent(meteora_dbc_swap_from_pb(e, meta)))
}
PbDexEvent::MeteoraDbcInitializePool(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDbc,
EventType::MeteoraDbcInitializePool,
meteora_dbc_program(),
);
Some(DexEvent::MeteoraDbcInitializePoolEvent(meteora_dbc_initialize_pool_from_pb(
e, meta,
)))
}
PbDexEvent::MeteoraDbcCurveComplete(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDbc,
EventType::MeteoraDbcCurveComplete,
meteora_dbc_program(),
);
Some(DexEvent::MeteoraDbcCurveCompleteEvent(meteora_dbc_curve_complete_from_pb(
e, meta,
)))
}
PbDexEvent::TokenAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
@@ -943,6 +1020,71 @@ pub(crate) fn convert_parser_event(
e, meta,
)))
}
PbDexEvent::OrcaWhirlpoolAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::OrcaWhirlpool,
EventType::AccountOrcaWhirlpool,
orca_whirlpool_program(),
);
Some(DexEvent::OrcaWhirlpoolAccountEvent(Box::new(orca_whirlpool_account_from_pb(
*e, meta,
))))
}
PbDexEvent::OrcaPositionAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::OrcaWhirlpool,
EventType::AccountOrcaPosition,
orca_whirlpool_program(),
);
Some(DexEvent::OrcaPositionAccountEvent(Box::new(orca_position_account_from_pb(
*e, meta,
))))
}
PbDexEvent::OrcaTickArrayAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::OrcaWhirlpool,
EventType::AccountOrcaTickArray,
orca_whirlpool_program(),
);
Some(DexEvent::OrcaTickArrayAccountEvent(Box::new(orca_tick_array_account_from_pb(
*e, meta,
))))
}
PbDexEvent::OrcaFeeTierAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::OrcaWhirlpool,
EventType::AccountOrcaFeeTier,
orca_whirlpool_program(),
);
Some(DexEvent::OrcaFeeTierAccountEvent(Box::new(orca_fee_tier_account_from_pb(
*e, meta,
))))
}
PbDexEvent::OrcaWhirlpoolsConfigAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::OrcaWhirlpool,
EventType::AccountOrcaWhirlpoolsConfig,
orca_whirlpool_program(),
);
Some(DexEvent::OrcaWhirlpoolsConfigAccountEvent(Box::new(
orca_whirlpools_config_account_from_pb(*e, meta),
)))
}
PbDexEvent::MeteoraPoolsSwap(e) => {
let meta = adapt_pm(
e.metadata.clone(),
+10 -1
View File
@@ -25,6 +25,7 @@ fn is_protocol_independent_event(ev: &DexEvent) -> bool {
)
}
#[allow(clippy::match_like_matches_macro)]
fn protocol_matches_event(p: &Protocol, ev: &DexEvent) -> bool {
match (p, ev) {
(Protocol::PumpFun, DexEvent::PumpFunCreateTokenEvent(_))
@@ -122,10 +123,18 @@ fn protocol_matches_event(p: &Protocol, ev: &DexEvent) -> bool {
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2RemoveLiquidityEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2CreatePositionEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2ClosePositionEvent(_)) => true,
(Protocol::MeteoraDbc, DexEvent::MeteoraDbcSwapEvent(_))
| (Protocol::MeteoraDbc, DexEvent::MeteoraDbcInitializePoolEvent(_))
| (Protocol::MeteoraDbc, DexEvent::MeteoraDbcCurveCompleteEvent(_)) => true,
(Protocol::OrcaWhirlpool, DexEvent::OrcaWhirlpoolSwapEvent(_))
| (Protocol::OrcaWhirlpool, DexEvent::OrcaWhirlpoolLiquidityIncreasedEvent(_))
| (Protocol::OrcaWhirlpool, DexEvent::OrcaWhirlpoolLiquidityDecreasedEvent(_))
| (Protocol::OrcaWhirlpool, DexEvent::OrcaWhirlpoolPoolInitializedEvent(_)) => true,
| (Protocol::OrcaWhirlpool, DexEvent::OrcaWhirlpoolPoolInitializedEvent(_))
| (Protocol::OrcaWhirlpool, DexEvent::OrcaWhirlpoolAccountEvent(_))
| (Protocol::OrcaWhirlpool, DexEvent::OrcaPositionAccountEvent(_))
| (Protocol::OrcaWhirlpool, DexEvent::OrcaTickArrayAccountEvent(_))
| (Protocol::OrcaWhirlpool, DexEvent::OrcaFeeTierAccountEvent(_))
| (Protocol::OrcaWhirlpool, DexEvent::OrcaWhirlpoolsConfigAccountEvent(_)) => true,
(Protocol::MeteoraPools, DexEvent::MeteoraPoolsSwapEvent(_))
| (Protocol::MeteoraPools, DexEvent::MeteoraPoolsAddLiquidityEvent(_))
| (Protocol::MeteoraPools, DexEvent::MeteoraPoolsRemoveLiquidityEvent(_))
+193 -3
View File
@@ -1,14 +1,18 @@
//! Orca Whirlpool and Meteora Pools / DLMM events with SDK-shaped payloads.
use crate::streaming::event_parser::common::EventMetadata;
use crate::streaming::event_parser::protocols::sol_parser_forward::events::{
MeteoraDbcCurveCompleteEvent, MeteoraDbcInitializePoolEvent, MeteoraDbcSwapEvent,
MeteoraDlmmAddLiquidityEvent, MeteoraDlmmClaimFeeEvent, MeteoraDlmmClosePositionEvent,
MeteoraDlmmCreatePositionEvent, MeteoraDlmmInitializeBinArrayEvent,
MeteoraDlmmInitializePoolEvent, MeteoraDlmmRemoveLiquidityEvent, MeteoraDlmmSwapEvent,
MeteoraPoolsAddLiquidityEvent, MeteoraPoolsBootstrapLiquidityEvent,
MeteoraPoolsPoolCreatedEvent, MeteoraPoolsRemoveLiquidityEvent, MeteoraPoolsSetPoolFeesEvent,
MeteoraPoolsSwapEvent, OrcaWhirlpoolLiquidityDecreasedEvent,
OrcaWhirlpoolLiquidityIncreasedEvent, OrcaWhirlpoolPoolInitializedEvent,
OrcaWhirlpoolSwapEvent,
MeteoraPoolsSwapEvent, OrcaFeeTierAccount, OrcaFeeTierAccountEvent, OrcaPositionAccount,
OrcaPositionAccountEvent, OrcaPositionRewardInfo, OrcaTick, OrcaTickArrayAccount,
OrcaTickArrayAccountEvent, OrcaWhirlpoolAccount, OrcaWhirlpoolAccountEvent,
OrcaWhirlpoolLiquidityDecreasedEvent, OrcaWhirlpoolLiquidityIncreasedEvent,
OrcaWhirlpoolPoolInitializedEvent, OrcaWhirlpoolRewardInfo, OrcaWhirlpoolSwapEvent,
OrcaWhirlpoolsConfigAccount, OrcaWhirlpoolsConfigAccountEvent,
};
pub(crate) fn orca_swap_from_pb(
@@ -85,6 +89,192 @@ pub(crate) fn orca_pool_initialized_from_pb(
}
}
fn orca_whirlpool_reward_from_pb(
r: sol_parser_sdk::core::events::OrcaWhirlpoolRewardInfo,
) -> OrcaWhirlpoolRewardInfo {
OrcaWhirlpoolRewardInfo {
mint: r.mint,
vault: r.vault,
authority: r.authority,
emissions_per_second_x64: r.emissions_per_second_x64,
growth_global_x64: r.growth_global_x64,
}
}
fn orca_position_reward_from_pb(
r: sol_parser_sdk::core::events::OrcaPositionRewardInfo,
) -> OrcaPositionRewardInfo {
OrcaPositionRewardInfo {
growth_inside_checkpoint: r.growth_inside_checkpoint,
amount_owed: r.amount_owed,
}
}
fn orca_tick_from_pb(t: sol_parser_sdk::core::events::OrcaTick) -> OrcaTick {
OrcaTick {
initialized: t.initialized,
liquidity_net: t.liquidity_net,
liquidity_gross: t.liquidity_gross,
fee_growth_outside_a: t.fee_growth_outside_a,
fee_growth_outside_b: t.fee_growth_outside_b,
reward_growths_outside: t.reward_growths_outside,
}
}
pub(crate) fn orca_whirlpool_account_from_pb(
e: sol_parser_sdk::core::events::OrcaWhirlpoolAccountEvent,
meta: EventMetadata,
) -> OrcaWhirlpoolAccountEvent {
OrcaWhirlpoolAccountEvent {
metadata: meta,
pubkey: e.pubkey,
whirlpool: OrcaWhirlpoolAccount {
whirlpools_config: e.whirlpool.whirlpools_config,
whirlpool_bump: e.whirlpool.whirlpool_bump,
tick_spacing: e.whirlpool.tick_spacing,
tick_spacing_seed: e.whirlpool.tick_spacing_seed,
fee_rate: e.whirlpool.fee_rate,
protocol_fee_rate: e.whirlpool.protocol_fee_rate,
liquidity: e.whirlpool.liquidity,
sqrt_price: e.whirlpool.sqrt_price,
tick_current_index: e.whirlpool.tick_current_index,
protocol_fee_owed_a: e.whirlpool.protocol_fee_owed_a,
protocol_fee_owed_b: e.whirlpool.protocol_fee_owed_b,
token_mint_a: e.whirlpool.token_mint_a,
token_vault_a: e.whirlpool.token_vault_a,
fee_growth_global_a: e.whirlpool.fee_growth_global_a,
token_mint_b: e.whirlpool.token_mint_b,
token_vault_b: e.whirlpool.token_vault_b,
fee_growth_global_b: e.whirlpool.fee_growth_global_b,
reward_last_updated_timestamp: e.whirlpool.reward_last_updated_timestamp,
reward_infos: e.whirlpool.reward_infos.map(orca_whirlpool_reward_from_pb),
},
..Default::default()
}
}
pub(crate) fn orca_position_account_from_pb(
e: sol_parser_sdk::core::events::OrcaPositionAccountEvent,
meta: EventMetadata,
) -> OrcaPositionAccountEvent {
OrcaPositionAccountEvent {
metadata: meta,
pubkey: e.pubkey,
position: OrcaPositionAccount {
whirlpool: e.position.whirlpool,
position_mint: e.position.position_mint,
liquidity: e.position.liquidity,
tick_lower_index: e.position.tick_lower_index,
tick_upper_index: e.position.tick_upper_index,
fee_growth_checkpoint_a: e.position.fee_growth_checkpoint_a,
fee_owed_a: e.position.fee_owed_a,
fee_growth_checkpoint_b: e.position.fee_growth_checkpoint_b,
fee_owed_b: e.position.fee_owed_b,
reward_infos: e.position.reward_infos.map(orca_position_reward_from_pb),
},
..Default::default()
}
}
pub(crate) fn orca_tick_array_account_from_pb(
e: sol_parser_sdk::core::events::OrcaTickArrayAccountEvent,
meta: EventMetadata,
) -> OrcaTickArrayAccountEvent {
OrcaTickArrayAccountEvent {
metadata: meta,
pubkey: e.pubkey,
tick_array: OrcaTickArrayAccount {
start_tick_index: e.tick_array.start_tick_index,
ticks: e.tick_array.ticks.into_iter().map(orca_tick_from_pb).collect(),
whirlpool: e.tick_array.whirlpool,
},
..Default::default()
}
}
pub(crate) fn orca_fee_tier_account_from_pb(
e: sol_parser_sdk::core::events::OrcaFeeTierAccountEvent,
meta: EventMetadata,
) -> OrcaFeeTierAccountEvent {
OrcaFeeTierAccountEvent {
metadata: meta,
pubkey: e.pubkey,
fee_tier: OrcaFeeTierAccount {
whirlpools_config: e.fee_tier.whirlpools_config,
tick_spacing: e.fee_tier.tick_spacing,
default_fee_rate: e.fee_tier.default_fee_rate,
},
..Default::default()
}
}
pub(crate) fn orca_whirlpools_config_account_from_pb(
e: sol_parser_sdk::core::events::OrcaWhirlpoolsConfigAccountEvent,
meta: EventMetadata,
) -> OrcaWhirlpoolsConfigAccountEvent {
OrcaWhirlpoolsConfigAccountEvent {
metadata: meta,
pubkey: e.pubkey,
config: OrcaWhirlpoolsConfigAccount {
fee_authority: e.config.fee_authority,
collect_protocol_fees_authority: e.config.collect_protocol_fees_authority,
reward_emissions_super_authority: e.config.reward_emissions_super_authority,
default_protocol_fee_rate: e.config.default_protocol_fee_rate,
},
..Default::default()
}
}
pub(crate) fn meteora_dbc_swap_from_pb(
e: sol_parser_sdk::core::events::MeteoraDbcSwapEvent,
meta: EventMetadata,
) -> MeteoraDbcSwapEvent {
MeteoraDbcSwapEvent {
metadata: meta,
pool: e.pool,
config: e.config,
trade_direction: e.trade_direction,
has_referral: e.has_referral,
amount_in: e.amount_in,
minimum_amount_out: e.minimum_amount_out,
actual_input_amount: e.actual_input_amount,
output_amount: e.output_amount,
next_sqrt_price: e.next_sqrt_price,
trading_fee: e.trading_fee,
protocol_fee: e.protocol_fee,
referral_fee: e.referral_fee,
current_timestamp: e.current_timestamp,
}
}
pub(crate) fn meteora_dbc_initialize_pool_from_pb(
e: sol_parser_sdk::core::events::MeteoraDbcInitializePoolEvent,
meta: EventMetadata,
) -> MeteoraDbcInitializePoolEvent {
MeteoraDbcInitializePoolEvent {
metadata: meta,
pool: e.pool,
config: e.config,
creator: e.creator,
base_mint: e.base_mint,
pool_type: e.pool_type,
activation_point: e.activation_point,
}
}
pub(crate) fn meteora_dbc_curve_complete_from_pb(
e: sol_parser_sdk::core::events::MeteoraDbcCurveCompleteEvent,
meta: EventMetadata,
) -> MeteoraDbcCurveCompleteEvent {
MeteoraDbcCurveCompleteEvent {
metadata: meta,
pool: e.pool,
config: e.config,
base_reserve: e.base_reserve,
quote_reserve: e.quote_reserve,
}
}
pub(crate) fn meteora_pools_swap_from_pb(
e: sol_parser_sdk::core::events::MeteoraPoolsSwapEvent,
meta: EventMetadata,
+8 -5
View File
@@ -32,6 +32,7 @@ pub(crate) use adapt::{block_timestamp_from_stream_meta, fuse_streamer_ix_ctx};
pub(crate) use convert::{adapt_parser_event, adapt_parser_events_list, convert_parser_event};
#[cfg(test)]
#[allow(clippy::field_reassign_with_default)]
mod tests {
use super::filter::event_matches_protocol;
use super::{adapt_parser_event, convert_parser_event};
@@ -40,9 +41,9 @@ mod tests {
use crate::streaming::event_parser::core::account_event_parser::TokenInfoEvent;
use crate::streaming::event_parser::{DexEvent, Protocol};
use sol_parser_sdk::core::events::{
BonkTradeEvent as PbBonkTrade, EventMetadata, MeteoraDlmmSwapEvent as PbDlmmSwap,
OrcaWhirlpoolSwapEvent as PbOrcaSwap, PumpFunCreateV2TokenEvent as PbPumpCreateV2,
PumpFunTradeEvent as PbPumpTrade, TokenInfoEvent as PbTokenInfo,
EventMetadata, MeteoraDlmmSwapEvent as PbDlmmSwap, OrcaWhirlpoolSwapEvent as PbOrcaSwap,
PumpFunCreateV2TokenEvent as PbPumpCreateV2, PumpFunTradeEvent as PbPumpTrade,
RaydiumLaunchlabTradeEvent as PbBonkTrade, TokenInfoEvent as PbTokenInfo,
TradeDirection as PbBonkDir,
};
use sol_parser_sdk::DexEvent as PbDexEvent;
@@ -370,7 +371,8 @@ mod tests {
trade_direction: PbBonkDir::Buy,
exact_in: true,
};
let dex = convert_parser_event(PbDexEvent::BonkTrade(b), None, 0).expect("convert");
let dex =
convert_parser_event(PbDexEvent::RaydiumLaunchlabTrade(b), None, 0).expect("convert");
match dex {
DexEvent::BonkTradeEvent(e) => {
assert_eq!(e.metadata.event_type, EventType::BonkBuyExactIn)
@@ -391,7 +393,8 @@ mod tests {
trade_direction: PbBonkDir::Sell,
exact_in: false,
};
let dex = convert_parser_event(PbDexEvent::BonkTrade(b), None, 0).expect("convert");
let dex =
convert_parser_event(PbDexEvent::RaydiumLaunchlabTrade(b), None, 0).expect("convert");
match dex {
DexEvent::BonkTradeEvent(e) => {
assert_eq!(e.metadata.event_type, EventType::BonkSellExactOut)
@@ -12,7 +12,7 @@ pub(crate) fn pump_fees_program() -> Pubkey {
program_ids::PUMP_FEES_PROGRAM_ID
}
pub(crate) fn bonk_program() -> Pubkey {
program_ids::BONK_PROGRAM_ID
program_ids::RAYDIUM_LAUNCHLAB_PROGRAM_ID
}
pub(crate) fn raydium_cpmm_program() -> Pubkey {
program_ids::RAYDIUM_CPMM_PROGRAM_ID
@@ -27,6 +27,10 @@ pub(crate) fn meteora_damm_program() -> Pubkey {
program_ids::METEORA_DAMM_V2_PROGRAM_ID
}
pub(crate) fn meteora_dbc_program() -> Pubkey {
program_ids::METEORA_DBC_PROGRAM_ID
}
pub(crate) fn orca_whirlpool_program() -> Pubkey {
program_ids::ORCA_WHIRLPOOL_PROGRAM_ID
}
@@ -2,7 +2,8 @@
use crate::streaming::event_parser::common::EventMetadata;
use crate::streaming::event_parser::protocols::meteora_damm_v2::events::{
MeteoraDammV2AddLiquidityEvent, MeteoraDammV2ClosePositionEvent,
MeteoraDammV2CreatePositionEvent, MeteoraDammV2RemoveLiquidityEvent, MeteoraDammV2SwapEvent,
MeteoraDammV2CreatePositionEvent, MeteoraDammV2InitializePoolEvent,
MeteoraDammV2RemoveLiquidityEvent, MeteoraDammV2SwapEvent,
};
use crate::streaming::event_parser::protocols::raydium_amm_v4::events::{
RaydiumAmmV4DepositEvent, RaydiumAmmV4Initialize2Event, RaydiumAmmV4SwapEvent,
@@ -24,8 +25,11 @@ use crate::streaming::event_parser::protocols::raydium_clmm::types::{
RewardInfo as ClmmRewardInfo, TickArrayState as ClmmTickArrayState, TickState as ClmmTickState,
};
use crate::streaming::event_parser::protocols::raydium_cpmm::events::{
RaydiumCpmmDepositEvent, RaydiumCpmmInitializeEvent, RaydiumCpmmSwapEvent,
RaydiumCpmmWithdrawEvent,
RaydiumCpmmAmmConfigAccountEvent, RaydiumCpmmDepositEvent, RaydiumCpmmInitializeEvent,
RaydiumCpmmPoolStateAccountEvent, RaydiumCpmmSwapEvent, RaydiumCpmmWithdrawEvent,
};
use crate::streaming::event_parser::protocols::raydium_cpmm::types::{
AmmConfig as CpmmAmmConfig, PoolState as CpmmPoolState,
};
use solana_sdk::pubkey::Pubkey;
pub(crate) fn meteora_damm_v2_swap_from_parser(
@@ -72,6 +76,38 @@ pub(crate) fn meteora_damm_v2_swap_from_parser(
}
}
pub(crate) fn meteora_damm_v2_initialize_pool_from_parser(
e: sol_parser_sdk::core::events::MeteoraDammV2InitializePoolEvent,
meta: EventMetadata,
) -> MeteoraDammV2InitializePoolEvent {
MeteoraDammV2InitializePoolEvent {
metadata: meta,
pool: e.pool,
token_a_mint: e.token_a_mint,
token_b_mint: e.token_b_mint,
creator: e.creator,
payer: e.payer,
alpha_vault: e.alpha_vault,
sqrt_min_price: e.sqrt_min_price,
sqrt_max_price: e.sqrt_max_price,
activation_type: e.activation_type,
collect_fee_mode: e.collect_fee_mode,
liquidity: e.liquidity,
sqrt_price: e.sqrt_price,
activation_point: e.activation_point.unwrap_or(0),
token_a_flag: e.token_a_flag,
token_b_flag: e.token_b_flag,
token_a_amount: e.token_a_amount,
token_b_amount: e.token_b_amount,
total_amount_a: e.total_amount_a,
total_amount_b: e.total_amount_b,
pool_type: e.pool_type,
position: e.position,
position_nft_mint: e.position_nft_mint,
..Default::default()
}
}
pub(crate) fn raydium_cpmm_swap_from_parser(
e: sol_parser_sdk::core::events::RaydiumCpmmSwapEvent,
meta: EventMetadata,
@@ -164,6 +200,85 @@ pub(crate) fn raydium_cpmm_initialize_from_parser(
}
}
fn raydium_cpmm_amm_config_from_parser(
c: sol_parser_sdk::core::events::RaydiumCpmmAmmConfig,
) -> CpmmAmmConfig {
CpmmAmmConfig {
bump: c.bump,
disable_create_pool: c.disable_create_pool,
index: c.index,
trade_fee_rate: c.trade_fee_rate,
protocol_fee_rate: c.protocol_fee_rate,
fund_fee_rate: c.fund_fee_rate,
create_pool_fee: c.create_pool_fee,
protocol_owner: c.protocol_owner,
fund_owner: c.fund_owner,
creator_fee_rate: c.creator_fee_rate,
padding: c.padding,
}
}
fn raydium_cpmm_pool_state_from_parser(
p: sol_parser_sdk::core::events::RaydiumCpmmPoolState,
) -> CpmmPoolState {
CpmmPoolState {
amm_config: p.amm_config,
pool_creator: p.pool_creator,
token_0_vault: p.token_0_vault,
token_1_vault: p.token_1_vault,
lp_mint: p.lp_mint,
token_0_mint: p.token_0_mint,
token_1_mint: p.token_1_mint,
token_0_program: p.token_0_program,
token_1_program: p.token_1_program,
observation_key: p.observation_key,
auth_bump: p.auth_bump,
status: p.status,
lp_mint_decimals: p.lp_mint_decimals,
mint_0_decimals: p.mint_0_decimals,
mint_1_decimals: p.mint_1_decimals,
lp_supply: p.lp_supply,
protocol_fees_token_0: p.protocol_fees_token_0,
protocol_fees_token_1: p.protocol_fees_token_1,
fund_fees_token_0: p.fund_fees_token_0,
fund_fees_token_1: p.fund_fees_token_1,
open_time: p.open_time,
recent_epoch: p.recent_epoch,
creator_fee_on: p.creator_fee_on,
enable_creator_fee: p.enable_creator_fee,
padding1: p.padding1,
creator_fees_token_0: p.creator_fees_token_0,
creator_fees_token_1: p.creator_fees_token_1,
padding: p.padding,
}
}
pub(crate) fn raydium_cpmm_amm_config_account_from_parser(
e: sol_parser_sdk::core::events::RaydiumCpmmAmmConfigAccountEvent,
meta: EventMetadata,
) -> RaydiumCpmmAmmConfigAccountEvent {
RaydiumCpmmAmmConfigAccountEvent {
metadata: meta,
pubkey: e.pubkey,
owner: super::program_ids::raydium_cpmm_program(),
amm_config: raydium_cpmm_amm_config_from_parser(e.amm_config),
..Default::default()
}
}
pub(crate) fn raydium_cpmm_pool_state_account_from_parser(
e: sol_parser_sdk::core::events::RaydiumCpmmPoolStateAccountEvent,
meta: EventMetadata,
) -> RaydiumCpmmPoolStateAccountEvent {
RaydiumCpmmPoolStateAccountEvent {
metadata: meta,
pubkey: e.pubkey,
owner: super::program_ids::raydium_cpmm_program(),
pool_state: raydium_cpmm_pool_state_from_parser(e.pool_state),
..Default::default()
}
}
pub(crate) fn raydium_amm_v4_swap_from_parser(
e: sol_parser_sdk::core::events::RaydiumAmmV4SwapEvent,
meta: EventMetadata,
+1
View File
@@ -25,6 +25,7 @@ impl ShredStreamGrpc {
/// 创建客户端,使用自定义配置
pub async fn new_with_config(endpoint: String, config: StreamClientConfig) -> AnyResult<Self> {
sol_parser_sdk::warmup_parser();
let shredstream_client = ShredstreamProxyClient::connect(endpoint.clone())
.await?
.max_decoding_message_size(config.connection.max_decoding_message_size);
+1 -1
View File
@@ -63,7 +63,7 @@ impl PooledTransactionWithSlot {
/// 使用优化的工厂方法创建 TransactionWithSlot(移动数据而不是克隆)
pub fn into_transaction_with_slot(mut self) -> TransactionWithSlot {
// 移动数据而不是克隆,避免多余的内存分配
std::mem::replace(self.deref_mut(), TransactionWithSlot::default())
std::mem::take(self.deref_mut())
}
}
+2
View File
@@ -66,6 +66,7 @@ impl YellowstoneGrpc {
x_token: Option<String>,
config: StreamClientConfig,
) -> AnyResult<Self> {
sol_parser_sdk::warmup_parser();
let _ = rustls::crypto::ring::default_provider().install_default().ok();
let subscription_manager =
SubscriptionManager::new(endpoint.clone(), x_token.clone(), config.clone());
@@ -133,6 +134,7 @@ impl YellowstoneGrpc {
///
/// # Returns
/// Returns `AnyResult<()>`, `Ok(())` on success, error information on failure
#[allow(clippy::too_many_arguments)]
pub async fn subscribe_events_immediate<F>(
&self,
protocols: Vec<Protocol>,
+7 -9
View File
@@ -16,6 +16,7 @@ use yellowstone_grpc_proto::geyser::{
const SYSTEM_PROGRAM_ID: Pubkey = pubkey!("11111111111111111111111111111111");
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum SystemEvent {
NewTransfer(TransferInfo),
@@ -101,15 +102,12 @@ impl YellowstoneGrpc {
where
F: Fn(SystemEvent) + Send + Sync,
{
match event_pretty {
EventPretty::Transaction(transaction_pretty) => {
callback(SystemEvent::NewTransfer(TransferInfo {
slot: transaction_pretty.slot,
signature: transaction_pretty.signature.to_string(),
tx: Some(transaction_pretty.grpc_tx),
}));
}
_ => {}
if let EventPretty::Transaction(transaction_pretty) = event_pretty {
callback(SystemEvent::NewTransfer(TransferInfo {
slot: transaction_pretty.slot,
signature: transaction_pretty.signature.to_string(),
tx: Some(transaction_pretty.grpc_tx),
}));
}
Ok(())
}