From 2e8c0a1ee53801f0b5407ff1a6cc78fff63ddd67 Mon Sep 17 00:00:00 2001 From: ysq Date: Tue, 9 Sep 2025 18:21:26 +0800 Subject: [PATCH] refactor: separate examples and improve docs - Split main.rs into focused grpc_example.rs and shred_example.rs - Add example overview table and dynamic subscription docs - Improve documentation structure and user experience --- README.md | 373 +---------------------- README_CN.md | 389 +++--------------------- src/main.rs => examples/grpc_example.rs | 55 +--- examples/shred_example.rs | 253 +++++++++++++++ 4 files changed, 300 insertions(+), 770 deletions(-) rename src/main.rs => examples/grpc_example.rs (88%) mode change 100755 => 100644 create mode 100644 examples/shred_example.rs diff --git a/README.md b/README.md index d301572..97d2871 100755 --- a/README.md +++ b/README.md @@ -117,373 +117,14 @@ let config = StreamClientConfig { ## Usage Examples -### Quick Start - Parse Transaction Events +### Usage Examples Summary Table -You can quickly test the library by running the built-in example that parses transaction events: - -```bash -cargo run --example parse_tx_events -``` - -This example demonstrates: -- How to parse transaction data from Solana mainnet using RPC -- Event parsing for multiple protocols (PumpFun, PumpSwap, Bonk, Raydium CPMM/CLMM/AMM V4) -- Transaction details extraction including fees, logs, and compute units - -The example uses a predefined transaction signature and shows how to extract protocol-specific events from the transaction data. - -### Dynamic Subscription Management Example - -Test runtime filter updates without reconnection: - -```bash -cargo run --example dynamic_subscription -``` - -This example demonstrates: -- Creating initial subscriptions with specific protocol filters -- Updating subscription filters at runtime without reconnection -- Single subscription enforcement and proper error handling -- Clean shutdown and resource management - -### Advanced Usage - Complete Example - -```rust -use solana_streamer_sdk::{ - match_event, - streaming::{ - event_parser::{ - common::{filter::EventTypeFilter, EventType}, - protocols::{ - bonk::{ - parser::BONK_PROGRAM_ID, BonkGlobalConfigAccountEvent, BonkMigrateToAmmEvent, - BonkMigrateToCpswapEvent, BonkPlatformConfigAccountEvent, BonkPoolCreateEvent, - BonkPoolStateAccountEvent, BonkTradeEvent, - }, - pumpfun::{ - parser::PUMPFUN_PROGRAM_ID, PumpFunBondingCurveAccountEvent, - PumpFunCreateTokenEvent, PumpFunGlobalAccountEvent, PumpFunMigrateEvent, - PumpFunTradeEvent, - }, - pumpswap::{ - parser::PUMPSWAP_PROGRAM_ID, PumpSwapBuyEvent, PumpSwapCreatePoolEvent, - PumpSwapDepositEvent, PumpSwapGlobalConfigAccountEvent, - PumpSwapPoolAccountEvent, PumpSwapSellEvent, PumpSwapWithdrawEvent, - }, - raydium_amm_v4::{ - parser::RAYDIUM_AMM_V4_PROGRAM_ID, RaydiumAmmV4AmmInfoAccountEvent, - RaydiumAmmV4DepositEvent, RaydiumAmmV4Initialize2Event, RaydiumAmmV4SwapEvent, - RaydiumAmmV4WithdrawEvent, RaydiumAmmV4WithdrawPnlEvent, - }, - raydium_clmm::{ - parser::RAYDIUM_CLMM_PROGRAM_ID, RaydiumClmmAmmConfigAccountEvent, - RaydiumClmmClosePositionEvent, RaydiumClmmCreatePoolEvent, - RaydiumClmmDecreaseLiquidityV2Event, RaydiumClmmIncreaseLiquidityV2Event, - RaydiumClmmOpenPositionV2Event, RaydiumClmmOpenPositionWithToken22NftEvent, - RaydiumClmmPoolStateAccountEvent, RaydiumClmmSwapEvent, RaydiumClmmSwapV2Event, - RaydiumClmmTickArrayStateAccountEvent, - }, - raydium_cpmm::{ - parser::RAYDIUM_CPMM_PROGRAM_ID, RaydiumCpmmAmmConfigAccountEvent, - RaydiumCpmmDepositEvent, RaydiumCpmmInitializeEvent, - RaydiumCpmmPoolStateAccountEvent, RaydiumCpmmSwapEvent, - RaydiumCpmmWithdrawEvent, - }, - BlockMetaEvent, - }, - Protocol, UnifiedEvent, - }, - grpc::ClientConfig, - shred::StreamClientConfig, - yellowstone_grpc::{AccountFilter, TransactionFilter}, - ShredStreamGrpc, YellowstoneGrpc, - }, -}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - println!("Starting Solana Streamer..."); - test_grpc().await?; - test_shreds().await?; - Ok(()) -} - -async fn test_grpc() -> Result<(), Box> { - println!("Subscribing to Yellowstone gRPC events..."); - - // Create low-latency configuration - let mut config = ClientConfig::low_latency(); - // Enable performance monitoring, has performance overhead, disabled by default - config.enable_metrics = true; - let grpc = YellowstoneGrpc::new_with_config( - "https://solana-yellowstone-grpc.publicnode.com:443".to_string(), - None, - config, - )?; - - println!("GRPC client created successfully"); - - let callback = create_event_callback(); - - // Will try to parse corresponding protocol events from transactions - let protocols = vec![ - Protocol::PumpFun, - Protocol::PumpSwap, - Protocol::Bonk, - Protocol::RaydiumCpmm, - Protocol::RaydiumClmm, - Protocol::RaydiumAmmV4, - ]; - - println!("Protocols to monitor: {:?}", protocols); - - // Filter accounts - let account_include = vec![ - PUMPFUN_PROGRAM_ID.to_string(), // Listen to pumpfun program ID - PUMPSWAP_PROGRAM_ID.to_string(), // Listen to pumpswap program ID - BONK_PROGRAM_ID.to_string(), // Listen to bonk program ID - RAYDIUM_CPMM_PROGRAM_ID.to_string(), // Listen to raydium_cpmm program ID - RAYDIUM_CLMM_PROGRAM_ID.to_string(), // Listen to raydium_clmm program ID - RAYDIUM_AMM_V4_PROGRAM_ID.to_string(), // Listen to raydium_amm_v4 program ID - ]; - let account_exclude = vec![]; - let account_required = vec![]; - - // Transaction filter for monitoring transaction events - let transaction_filter = TransactionFilter { - account_include: account_include.clone(), - account_exclude, - account_required, - }; - - // Account filter for monitoring account state changes - let account_filter = AccountFilter { account: vec![], owner: account_include.clone() }; - - // Event type filtering - optional - // No event filtering, includes all events - let event_type_filter = None; - // Only include PumpSwapBuy and PumpSwapSell events - // let event_type_filter = Some(EventTypeFilter { include: vec![EventType::PumpSwapBuy, EventType::PumpSwapSell] }); - - println!("Starting to listen for events, press Ctrl+C to stop..."); - println!("Monitoring programs: {:?}", account_include); - - println!("Starting subscription..."); - - grpc.subscribe_events_immediate( - protocols, - None, - transaction_filter, - account_filter, - event_type_filter, - None, - callback, - ) - .await?; - - // Support stop method, test code - stop after 1000 seconds asynchronously - let grpc_clone = grpc.clone(); - tokio::spawn(async move { - tokio::time::sleep(std::time::Duration::from_secs(1000)).await; - grpc_clone.stop().await; - }); - - println!("Waiting for Ctrl+C to stop..."); - tokio::signal::ctrl_c().await?; - - Ok(()) -} - -async fn test_shreds() -> Result<(), Box> { - println!("Subscribing to ShredStream events..."); - - // Create low-latency configuration - let mut config = StreamClientConfig::low_latency(); - // Enable performance monitoring, has performance overhead, disabled by default - config.enable_metrics = true; - let shred_stream = - ShredStreamGrpc::new_with_config("http://127.0.0.1:10800".to_string(), config).await?; - - let callback = create_event_callback(); - let protocols = vec![ - Protocol::PumpFun, - Protocol::PumpSwap, - Protocol::Bonk, - Protocol::RaydiumCpmm, - Protocol::RaydiumClmm, - Protocol::RaydiumAmmV4, - ]; - - // Event filtering - // No event filtering, includes all events - let event_type_filter = None; - // Only include PumpSwapBuy events and PumpSwapSell events - // let event_type_filter = - // EventTypeFilter { include: vec![EventType::PumpSwapBuy, EventType::PumpSwapSell] }; - - println!("Listening for events, press Ctrl+C to stop..."); - shred_stream.shredstream_subscribe(protocols, None, event_type_filter, callback).await?; - - // Support stop method, test code - stop after 1000 seconds asynchronously - let shred_clone = shred_stream.clone(); - tokio::spawn(async move { - tokio::time::sleep(std::time::Duration::from_secs(1000)).await; - shred_clone.stop().await; - }); - - println!("Waiting for Ctrl+C to stop..."); - tokio::signal::ctrl_c().await?; - - Ok(()) -} - -fn create_event_callback() -> impl Fn(Box) { - |event: Box| { - println!("🎉 Event received! Type: {:?}, ID: {}", event.event_type(), event.id()); - match_event!(event, { - // -------------------------- block meta ----------------------- - BlockMetaEvent => |e: BlockMetaEvent| { - println!("BlockMetaEvent: {e:?}"); - }, - // -------------------------- bonk ----------------------- - BonkPoolCreateEvent => |e: BonkPoolCreateEvent| { - // When using grpc, you can get block_time from each event - println!("block_time: {:?}, block_time_ms: {:?}", e.metadata.block_time, e.metadata.block_time_ms); - println!("BonkPoolCreateEvent: {:?}", e.base_mint_param.symbol); - }, - BonkTradeEvent => |e: BonkTradeEvent| { - println!("BonkTradeEvent: {e:?}"); - }, - BonkMigrateToAmmEvent => |e: BonkMigrateToAmmEvent| { - println!("BonkMigrateToAmmEvent: {e:?}"); - }, - BonkMigrateToCpswapEvent => |e: BonkMigrateToCpswapEvent| { - println!("BonkMigrateToCpswapEvent: {e:?}"); - }, - // -------------------------- pumpfun ----------------------- - PumpFunTradeEvent => |e: PumpFunTradeEvent| { - println!("PumpFunTradeEvent: {e:?}"); - }, - PumpFunMigrateEvent => |e: PumpFunMigrateEvent| { - println!("PumpFunMigrateEvent: {e:?}"); - }, - PumpFunCreateTokenEvent => |e: PumpFunCreateTokenEvent| { - println!("PumpFunCreateTokenEvent: {e:?}"); - }, - // -------------------------- pumpswap ----------------------- - PumpSwapBuyEvent => |e: PumpSwapBuyEvent| { - println!("Buy event: {e:?}"); - }, - PumpSwapSellEvent => |e: PumpSwapSellEvent| { - println!("Sell event: {e:?}"); - }, - PumpSwapCreatePoolEvent => |e: PumpSwapCreatePoolEvent| { - println!("CreatePool event: {e:?}"); - }, - PumpSwapDepositEvent => |e: PumpSwapDepositEvent| { - println!("Deposit event: {e:?}"); - }, - PumpSwapWithdrawEvent => |e: PumpSwapWithdrawEvent| { - println!("Withdraw event: {e:?}"); - }, - // -------------------------- raydium_cpmm ----------------------- - RaydiumCpmmSwapEvent => |e: RaydiumCpmmSwapEvent| { - println!("RaydiumCpmmSwapEvent: {e:?}"); - }, - RaydiumCpmmDepositEvent => |e: RaydiumCpmmDepositEvent| { - println!("RaydiumCpmmDepositEvent: {e:?}"); - }, - RaydiumCpmmInitializeEvent => |e: RaydiumCpmmInitializeEvent| { - println!("RaydiumCpmmInitializeEvent: {e:?}"); - }, - RaydiumCpmmWithdrawEvent => |e: RaydiumCpmmWithdrawEvent| { - println!("RaydiumCpmmWithdrawEvent: {e:?}"); - }, - // -------------------------- raydium_clmm ----------------------- - RaydiumClmmSwapEvent => |e: RaydiumClmmSwapEvent| { - println!("RaydiumClmmSwapEvent: {e:?}"); - }, - RaydiumClmmSwapV2Event => |e: RaydiumClmmSwapV2Event| { - println!("RaydiumClmmSwapV2Event: {e:?}"); - }, - RaydiumClmmClosePositionEvent => |e: RaydiumClmmClosePositionEvent| { - println!("RaydiumClmmClosePositionEvent: {e:?}"); - }, - RaydiumClmmDecreaseLiquidityV2Event => |e: RaydiumClmmDecreaseLiquidityV2Event| { - println!("RaydiumClmmDecreaseLiquidityV2Event: {e:?}"); - }, - RaydiumClmmCreatePoolEvent => |e: RaydiumClmmCreatePoolEvent| { - println!("RaydiumClmmCreatePoolEvent: {e:?}"); - }, - RaydiumClmmIncreaseLiquidityV2Event => |e: RaydiumClmmIncreaseLiquidityV2Event| { - println!("RaydiumClmmIncreaseLiquidityV2Event: {e:?}"); - }, - RaydiumClmmOpenPositionWithToken22NftEvent => |e: RaydiumClmmOpenPositionWithToken22NftEvent| { - println!("RaydiumClmmOpenPositionWithToken22NftEvent: {e:?}"); - }, - RaydiumClmmOpenPositionV2Event => |e: RaydiumClmmOpenPositionV2Event| { - println!("RaydiumClmmOpenPositionV2Event: {e:?}"); - }, - // -------------------------- raydium_amm_v4 ----------------------- - RaydiumAmmV4SwapEvent => |e: RaydiumAmmV4SwapEvent| { - println!("RaydiumAmmV4SwapEvent: {e:?}"); - }, - RaydiumAmmV4DepositEvent => |e: RaydiumAmmV4DepositEvent| { - println!("RaydiumAmmV4DepositEvent: {e:?}"); - }, - RaydiumAmmV4Initialize2Event => |e: RaydiumAmmV4Initialize2Event| { - println!("RaydiumAmmV4Initialize2Event: {e:?}"); - }, - RaydiumAmmV4WithdrawEvent => |e: RaydiumAmmV4WithdrawEvent| { - println!("RaydiumAmmV4WithdrawEvent: {e:?}"); - }, - RaydiumAmmV4WithdrawPnlEvent => |e: RaydiumAmmV4WithdrawPnlEvent| { - println!("RaydiumAmmV4WithdrawPnlEvent: {e:?}"); - }, - // -------------------------- account ----------------------- - BonkPoolStateAccountEvent => |e: BonkPoolStateAccountEvent| { - println!("BonkPoolStateAccountEvent: {e:?}"); - }, - BonkGlobalConfigAccountEvent => |e: BonkGlobalConfigAccountEvent| { - println!("BonkGlobalConfigAccountEvent: {e:?}"); - }, - BonkPlatformConfigAccountEvent => |e: BonkPlatformConfigAccountEvent| { - println!("BonkPlatformConfigAccountEvent: {e:?}"); - }, - PumpSwapGlobalConfigAccountEvent => |e: PumpSwapGlobalConfigAccountEvent| { - println!("PumpSwapGlobalConfigAccountEvent: {e:?}"); - }, - PumpSwapPoolAccountEvent => |e: PumpSwapPoolAccountEvent| { - println!("PumpSwapPoolAccountEvent: {e:?}"); - }, - PumpFunBondingCurveAccountEvent => |e: PumpFunBondingCurveAccountEvent| { - println!("PumpFunBondingCurveAccountEvent: {e:?}"); - }, - PumpFunGlobalAccountEvent => |e: PumpFunGlobalAccountEvent| { - println!("PumpFunGlobalAccountEvent: {e:?}"); - }, - RaydiumAmmV4AmmInfoAccountEvent => |e: RaydiumAmmV4AmmInfoAccountEvent| { - println!("RaydiumAmmV4AmmInfoAccountEvent: {e:?}"); - }, - RaydiumClmmAmmConfigAccountEvent => |e: RaydiumClmmAmmConfigAccountEvent| { - println!("RaydiumClmmAmmConfigAccountEvent: {e:?}"); - }, - RaydiumClmmPoolStateAccountEvent => |e: RaydiumClmmPoolStateAccountEvent| { - println!("RaydiumClmmPoolStateAccountEvent: {e:?}"); - }, - RaydiumClmmTickArrayStateAccountEvent => |e: RaydiumClmmTickArrayStateAccountEvent| { - println!("RaydiumClmmTickArrayStateAccountEvent: {e:?}"); - }, - RaydiumCpmmAmmConfigAccountEvent => |e: RaydiumCpmmAmmConfigAccountEvent| { - println!("RaydiumCpmmAmmConfigAccountEvent: {e:?}"); - }, - RaydiumCpmmPoolStateAccountEvent => |e: RaydiumCpmmPoolStateAccountEvent| { - println!("RaydiumCpmmPoolStateAccountEvent: {e:?}"); - }, - }); - } -} -``` +| Feature Type | Example File | Description | Run Command | Source Path | +|---------|---------|------|---------|----------| +| Yellowstone gRPC Stream | `grpc_example.rs` | Monitor transaction events using Yellowstone gRPC | `cargo run --example grpc_example` | [examples/grpc_example.rs](examples/grpc_example.rs) | +| ShredStream Stream | `shred_example.rs` | Monitor transaction events using ShredStream | `cargo run --example shred_example` | [examples/shred_example.rs](examples/shred_example.rs) | +| Parse Transaction Events | `parse_tx_events` | Parse Solana mainnet transaction data | `cargo run --example parse_tx_events` | [examples/parse_tx_events.rs](examples/parse_tx_events.rs) | +| Dynamic Subscription Management | `dynamic_subscription` | Update filters at runtime | `cargo run --example dynamic_subscription` | [examples/dynamic_subscription.rs](examples/dynamic_subscription.rs) | ### Event Filtering diff --git a/README_CN.md b/README_CN.md index 9988650..e287f24 100644 --- a/README_CN.md +++ b/README_CN.md @@ -29,6 +29,7 @@ 16. **运行时配置更新**: 支持在运行时动态更新配置参数 17. **全函数性能监控**: 所有subscribe_events函数都支持性能监控,自动收集和报告性能指标 18. **优雅关闭**: 支持编程式 stop() 方法进行干净的关闭 +19. **动态订阅管理**: 运行时过滤器更新而无需重新连接,支持自适应监控策略 ## 安装 @@ -116,359 +117,14 @@ let config = StreamClientConfig { ## 使用示例 -### 快速开始 - 解析交易事件 +### 使用示例概览表 -您可以通过运行内置示例来快速测试库的交易事件解析功能: - -```bash -cargo run --example parse_tx_events -``` - -该示例演示了: -- 如何使用 RPC 从 Solana 主网解析交易数据 -- 多协议事件解析(PumpFun、PumpSwap、Bonk、Raydium CPMM/CLMM/AMM V4) -- 交易详情提取,包括费用、日志和计算单元 - -该示例使用预定义的交易签名,展示如何从交易数据中提取协议特定的事件。 - -### 高级用法 - 完整示例 - -```rust -use solana_streamer_sdk::{ - match_event, - streaming::{ - event_parser::{ - common::{filter::EventTypeFilter, EventType}, - protocols::{ - bonk::{ - parser::BONK_PROGRAM_ID, BonkGlobalConfigAccountEvent, BonkMigrateToAmmEvent, - BonkMigrateToCpswapEvent, BonkPlatformConfigAccountEvent, BonkPoolCreateEvent, - BonkPoolStateAccountEvent, BonkTradeEvent, - }, - pumpfun::{ - parser::PUMPFUN_PROGRAM_ID, PumpFunBondingCurveAccountEvent, - PumpFunCreateTokenEvent, PumpFunGlobalAccountEvent, PumpFunMigrateEvent, - PumpFunTradeEvent, - }, - pumpswap::{ - parser::PUMPSWAP_PROGRAM_ID, PumpSwapBuyEvent, PumpSwapCreatePoolEvent, - PumpSwapDepositEvent, PumpSwapGlobalConfigAccountEvent, - PumpSwapPoolAccountEvent, PumpSwapSellEvent, PumpSwapWithdrawEvent, - }, - raydium_amm_v4::{ - parser::RAYDIUM_AMM_V4_PROGRAM_ID, RaydiumAmmV4AmmInfoAccountEvent, - RaydiumAmmV4DepositEvent, RaydiumAmmV4Initialize2Event, RaydiumAmmV4SwapEvent, - RaydiumAmmV4WithdrawEvent, RaydiumAmmV4WithdrawPnlEvent, - }, - raydium_clmm::{ - parser::RAYDIUM_CLMM_PROGRAM_ID, RaydiumClmmAmmConfigAccountEvent, - RaydiumClmmClosePositionEvent, RaydiumClmmCreatePoolEvent, - RaydiumClmmDecreaseLiquidityV2Event, RaydiumClmmIncreaseLiquidityV2Event, - RaydiumClmmOpenPositionV2Event, RaydiumClmmOpenPositionWithToken22NftEvent, - RaydiumClmmPoolStateAccountEvent, RaydiumClmmSwapEvent, RaydiumClmmSwapV2Event, - RaydiumClmmTickArrayStateAccountEvent, - }, - raydium_cpmm::{ - parser::RAYDIUM_CPMM_PROGRAM_ID, RaydiumCpmmAmmConfigAccountEvent, - RaydiumCpmmDepositEvent, RaydiumCpmmInitializeEvent, - RaydiumCpmmPoolStateAccountEvent, RaydiumCpmmSwapEvent, - RaydiumCpmmWithdrawEvent, - }, - BlockMetaEvent, - }, - Protocol, UnifiedEvent, - }, - grpc::ClientConfig, - shred::StreamClientConfig, - yellowstone_grpc::{AccountFilter, TransactionFilter}, - ShredStreamGrpc, YellowstoneGrpc, - }, -}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - println!("Starting Solana Streamer..."); - test_grpc().await?; - test_shreds().await?; - Ok(()) -} - -async fn test_grpc() -> Result<(), Box> { - println!("Subscribing to Yellowstone gRPC events..."); - - // 创建低延迟配置 - let mut config = ClientConfig::low_latency(); - // 启用性能监控, 有性能损耗, 默认关闭 - config.enable_metrics = true; - let grpc = YellowstoneGrpc::new_with_config( - "https://solana-yellowstone-grpc.publicnode.com:443".to_string(), - None, - config, - )?; - - println!("GRPC client created successfully"); - - let callback = create_event_callback(); - - // 将会从交易中尝试解析对应的协议事件 - let protocols = vec![ - Protocol::PumpFun, - Protocol::PumpSwap, - Protocol::Bonk, - Protocol::RaydiumCpmm, - Protocol::RaydiumClmm, - Protocol::RaydiumAmmV4, - ]; - - println!("Protocols to monitor: {:?}", protocols); - - // 过滤账号 - let account_include = vec![ - PUMPFUN_PROGRAM_ID.to_string(), // 监听 pumpfun 程序ID - PUMPSWAP_PROGRAM_ID.to_string(), // 监听 pumpswap 程序ID - BONK_PROGRAM_ID.to_string(), // 监听 bonk 程序ID - RAYDIUM_CPMM_PROGRAM_ID.to_string(), // 监听 raydium_cpmm 程序ID - RAYDIUM_CLMM_PROGRAM_ID.to_string(), // 监听 raydium_clmm 程序ID - RAYDIUM_AMM_V4_PROGRAM_ID.to_string(), // 监听 raydium_amm_v4 程序ID - ]; - let account_exclude = vec![]; - let account_required = vec![]; - - // 监听交易数据 - let transaction_filter = TransactionFilter { - account_include: account_include.clone(), - account_exclude, - account_required, - }; - - // 监听属于owner程序的账号数据 -> 账号事件监听 - let account_filter = AccountFilter { account: vec![], owner: account_include.clone() }; - - // 事件过滤 - 可选 - // 不进行事件过滤,包含所有事件 - let event_type_filter = None; - // 只包含PumpSwapBuy事件、PumpSwapSell事件 - // let event_type_filter = Some(EventTypeFilter { include: vec![EventType::PumpSwapBuy, EventType::PumpSwapSell] }); - - println!("Starting to listen for events, press Ctrl+C to stop..."); - println!("Monitoring programs: {:?}", account_include); - - println!("Starting subscription..."); - - grpc.subscribe_events_immediate( - protocols, - None, - transaction_filter, - account_filter, - event_type_filter, - None, - callback, - ) - .await?; - - // 支持 stop 方法,测试代码 - 异步1000秒之后停止 - let grpc_clone = grpc.clone(); - tokio::spawn(async move { - tokio::time::sleep(std::time::Duration::from_secs(1000)).await; - grpc_clone.stop().await; - }); - - println!("Waiting for Ctrl+C to stop..."); - tokio::signal::ctrl_c().await?; - - Ok(()) -} - -async fn test_shreds() -> Result<(), Box> { - println!("Subscribing to ShredStream events..."); - - // 创建低延迟配置 - let mut config = StreamClientConfig::low_latency(); - // 启用性能监控, 有性能损耗, 默认关闭 - config.enable_metrics = true; - let shred_stream = - ShredStreamGrpc::new_with_config("http://127.0.0.1:10800".to_string(), config).await?; - - let callback = create_event_callback(); - let protocols = vec![ - Protocol::PumpFun, - Protocol::PumpSwap, - Protocol::Bonk, - Protocol::RaydiumCpmm, - Protocol::RaydiumClmm, - Protocol::RaydiumAmmV4, - ]; - - // 事件过滤 - // 不进行事件过滤,包含所有事件 - let event_type_filter = None; - // 只包含PumpSwapBuy事件、PumpSwapSell事件 - // let event_type_filter = - // EventTypeFilter { include: vec![EventType::PumpSwapBuy, EventType::PumpSwapSell] }; - - println!("Listening for events, press Ctrl+C to stop..."); - shred_stream.shredstream_subscribe(protocols, None, event_type_filter, callback).await?; - - // 支持 stop 方法,测试代码 - 异步1000秒之后停止 - let shred_clone = shred_stream.clone(); - tokio::spawn(async move { - tokio::time::sleep(std::time::Duration::from_secs(1000)).await; - shred_clone.stop().await; - }); - - println!("Waiting for Ctrl+C to stop..."); - tokio::signal::ctrl_c().await?; - - Ok(()) -} - -fn create_event_callback() -> impl Fn(Box) { - |event: Box| { - println!("🎉 Event received! Type: {:?}, ID: {}", event.event_type(), event.id()); - match_event!(event, { - // -------------------------- block meta ----------------------- - BlockMetaEvent => |e: BlockMetaEvent| { - println!("BlockMetaEvent: {e:?}"); - }, - // -------------------------- bonk ----------------------- - BonkPoolCreateEvent => |e: BonkPoolCreateEvent| { - // 使用grpc的时候,可以从每个事件中获取到block_time - println!("block_time: {:?}, block_time_ms: {:?}", e.metadata.block_time, e.metadata.block_time_ms); - println!("BonkPoolCreateEvent: {:?}", e.base_mint_param.symbol); - }, - BonkTradeEvent => |e: BonkTradeEvent| { - println!("BonkTradeEvent: {e:?}"); - }, - BonkMigrateToAmmEvent => |e: BonkMigrateToAmmEvent| { - println!("BonkMigrateToAmmEvent: {e:?}"); - }, - BonkMigrateToCpswapEvent => |e: BonkMigrateToCpswapEvent| { - println!("BonkMigrateToCpswapEvent: {e:?}"); - }, - // -------------------------- pumpfun ----------------------- - PumpFunTradeEvent => |e: PumpFunTradeEvent| { - println!("PumpFunTradeEvent: {e:?}"); - }, - PumpFunMigrateEvent => |e: PumpFunMigrateEvent| { - println!("PumpFunMigrateEvent: {e:?}"); - }, - PumpFunCreateTokenEvent => |e: PumpFunCreateTokenEvent| { - println!("PumpFunCreateTokenEvent: {e:?}"); - }, - // -------------------------- pumpswap ----------------------- - PumpSwapBuyEvent => |e: PumpSwapBuyEvent| { - println!("Buy event: {e:?}"); - }, - PumpSwapSellEvent => |e: PumpSwapSellEvent| { - println!("Sell event: {e:?}"); - }, - PumpSwapCreatePoolEvent => |e: PumpSwapCreatePoolEvent| { - println!("CreatePool event: {e:?}"); - }, - PumpSwapDepositEvent => |e: PumpSwapDepositEvent| { - println!("Deposit event: {e:?}"); - }, - PumpSwapWithdrawEvent => |e: PumpSwapWithdrawEvent| { - println!("Withdraw event: {e:?}"); - }, - // -------------------------- raydium_cpmm ----------------------- - RaydiumCpmmSwapEvent => |e: RaydiumCpmmSwapEvent| { - println!("RaydiumCpmmSwapEvent: {e:?}"); - }, - RaydiumCpmmDepositEvent => |e: RaydiumCpmmDepositEvent| { - println!("RaydiumCpmmDepositEvent: {e:?}"); - }, - RaydiumCpmmInitializeEvent => |e: RaydiumCpmmInitializeEvent| { - println!("RaydiumCpmmInitializeEvent: {e:?}"); - }, - RaydiumCpmmWithdrawEvent => |e: RaydiumCpmmWithdrawEvent| { - println!("RaydiumCpmmWithdrawEvent: {e:?}"); - }, - // -------------------------- raydium_clmm ----------------------- - RaydiumClmmSwapEvent => |e: RaydiumClmmSwapEvent| { - println!("RaydiumClmmSwapEvent: {e:?}"); - }, - RaydiumClmmSwapV2Event => |e: RaydiumClmmSwapV2Event| { - println!("RaydiumClmmSwapV2Event: {e:?}"); - }, - RaydiumClmmClosePositionEvent => |e: RaydiumClmmClosePositionEvent| { - println!("RaydiumClmmClosePositionEvent: {e:?}"); - }, - RaydiumClmmDecreaseLiquidityV2Event => |e: RaydiumClmmDecreaseLiquidityV2Event| { - println!("RaydiumClmmDecreaseLiquidityV2Event: {e:?}"); - }, - RaydiumClmmCreatePoolEvent => |e: RaydiumClmmCreatePoolEvent| { - println!("RaydiumClmmCreatePoolEvent: {e:?}"); - }, - RaydiumClmmIncreaseLiquidityV2Event => |e: RaydiumClmmIncreaseLiquidityV2Event| { - println!("RaydiumClmmIncreaseLiquidityV2Event: {e:?}"); - }, - RaydiumClmmOpenPositionWithToken22NftEvent => |e: RaydiumClmmOpenPositionWithToken22NftEvent| { - println!("RaydiumClmmOpenPositionWithToken22NftEvent: {e:?}"); - }, - RaydiumClmmOpenPositionV2Event => |e: RaydiumClmmOpenPositionV2Event| { - println!("RaydiumClmmOpenPositionV2Event: {e:?}"); - }, - // -------------------------- raydium_amm_v4 ----------------------- - RaydiumAmmV4SwapEvent => |e: RaydiumAmmV4SwapEvent| { - println!("RaydiumAmmV4SwapEvent: {e:?}"); - }, - RaydiumAmmV4DepositEvent => |e: RaydiumAmmV4DepositEvent| { - println!("RaydiumAmmV4DepositEvent: {e:?}"); - }, - RaydiumAmmV4Initialize2Event => |e: RaydiumAmmV4Initialize2Event| { - println!("RaydiumAmmV4Initialize2Event: {e:?}"); - }, - RaydiumAmmV4WithdrawEvent => |e: RaydiumAmmV4WithdrawEvent| { - println!("RaydiumAmmV4WithdrawEvent: {e:?}"); - }, - RaydiumAmmV4WithdrawPnlEvent => |e: RaydiumAmmV4WithdrawPnlEvent| { - println!("RaydiumAmmV4WithdrawPnlEvent: {e:?}"); - }, - // -------------------------- account ----------------------- - BonkPoolStateAccountEvent => |e: BonkPoolStateAccountEvent| { - println!("BonkPoolStateAccountEvent: {e:?}"); - }, - BonkGlobalConfigAccountEvent => |e: BonkGlobalConfigAccountEvent| { - println!("BonkGlobalConfigAccountEvent: {e:?}"); - }, - BonkPlatformConfigAccountEvent => |e: BonkPlatformConfigAccountEvent| { - println!("BonkPlatformConfigAccountEvent: {e:?}"); - }, - PumpSwapGlobalConfigAccountEvent => |e: PumpSwapGlobalConfigAccountEvent| { - println!("PumpSwapGlobalConfigAccountEvent: {e:?}"); - }, - PumpSwapPoolAccountEvent => |e: PumpSwapPoolAccountEvent| { - println!("PumpSwapPoolAccountEvent: {e:?}"); - }, - PumpFunBondingCurveAccountEvent => |e: PumpFunBondingCurveAccountEvent| { - println!("PumpFunBondingCurveAccountEvent: {e:?}"); - }, - PumpFunGlobalAccountEvent => |e: PumpFunGlobalAccountEvent| { - println!("PumpFunGlobalAccountEvent: {e:?}"); - }, - RaydiumAmmV4AmmInfoAccountEvent => |e: RaydiumAmmV4AmmInfoAccountEvent| { - println!("RaydiumAmmV4AmmInfoAccountEvent: {e:?}"); - }, - RaydiumClmmAmmConfigAccountEvent => |e: RaydiumClmmAmmConfigAccountEvent| { - println!("RaydiumClmmAmmConfigAccountEvent: {e:?}"); - }, - RaydiumClmmPoolStateAccountEvent => |e: RaydiumClmmPoolStateAccountEvent| { - println!("RaydiumClmmPoolStateAccountEvent: {e:?}"); - }, - RaydiumClmmTickArrayStateAccountEvent => |e: RaydiumClmmTickArrayStateAccountEvent| { - println!("RaydiumClmmTickArrayStateAccountEvent: {e:?}"); - }, - RaydiumCpmmAmmConfigAccountEvent => |e: RaydiumCpmmAmmConfigAccountEvent| { - println!("RaydiumCpmmAmmConfigAccountEvent: {e:?}"); - }, - RaydiumCpmmPoolStateAccountEvent => |e: RaydiumCpmmPoolStateAccountEvent| { - println!("RaydiumCpmmPoolStateAccountEvent: {e:?}"); - }, - }); - } -} -``` +| 功能类型 | 示例文件 | 描述 | 运行命令 | 源码路径 | +|---------|---------|------|---------|----------| +| Yellowstone gRPC 流 | `grpc_example.rs` | 使用 Yellowstone gRPC 监控交易事件 | `cargo run --example grpc_example` | [examples/grpc_example.rs](examples/grpc_example.rs) | +| ShredStream 流 | `shred_example.rs` | 使用 ShredStream 监控交易事件 | `cargo run --example shred_example` | [examples/shred_example.rs](examples/shred_example.rs) | +| 解析交易事件 | `parse_tx_events` | 解析 Solana 主网交易数据 | `cargo run --example parse_tx_events` | [examples/parse_tx_events.rs](examples/parse_tx_events.rs) | +| 动态订阅管理 | `dynamic_subscription` | 运行时更新过滤器 | `cargo run --example dynamic_subscription` | [examples/dynamic_subscription.rs](examples/dynamic_subscription.rs) | ### 事件过滤 @@ -529,6 +185,32 @@ let event_type_filter = Some(EventTypeFilter { }); ``` +## 动态订阅管理 + +在运行时更新订阅过滤器而无需重新连接到流。 + +```rust +// 在现有订阅上更新过滤器 +grpc.update_subscription( + TransactionFilter { + account_include: vec!["new_program_id".to_string()], + account_exclude: vec![], + account_required: vec![], + }, + AccountFilter { + account: vec![], + owner: vec![], + }, +).await?; +``` + +- **无需重新连接**: 过滤器变更立即生效,无需关闭流 +- **原子更新**: 交易和账户过滤器同时更新 +- **单一订阅**: 每个客户端实例只有一个活跃订阅 +- **兼容性**: 与立即订阅和高级订阅方法兼容 + +注意:在同一客户端上多次尝试订阅会返回错误。 + ## 支持的协议 - **PumpFun**: 主要迷因币交易平台 @@ -584,8 +266,7 @@ src/ │ ├── shred_stream.rs # ShredStream 客户端 │ ├── yellowstone_grpc.rs # Yellowstone gRPC 客户端 │ └── yellowstone_sub_system.rs # Yellowstone 子系统 -├── lib.rs # 主库文件 -└── main.rs # 示例程序 +└── lib.rs # 主库文件 ``` ## 性能考虑 diff --git a/src/main.rs b/examples/grpc_example.rs old mode 100755 new mode 100644 similarity index 88% rename from src/main.rs rename to examples/grpc_example.rs index c28031d..5a96e51 --- a/src/main.rs +++ b/examples/grpc_example.rs @@ -2,7 +2,7 @@ use solana_streamer_sdk::{ match_event, streaming::{ event_parser::{ - common::{filter::EventTypeFilter, EventType}, + common::EventType, core::account_event_parser::CommonAccountEvent, protocols::{ bonk::{ @@ -44,17 +44,15 @@ use solana_streamer_sdk::{ Protocol, UnifiedEvent, }, grpc::ClientConfig, - shred::StreamClientConfig, yellowstone_grpc::{AccountFilter, TransactionFilter}, - ShredStreamGrpc, YellowstoneGrpc, + YellowstoneGrpc, }, }; #[tokio::main] async fn main() -> Result<(), Box> { - println!("Starting Solana Streamer..."); + println!("Starting Yellowstone gRPC Streamer..."); test_grpc().await?; - test_shreds().await?; Ok(()) } @@ -113,7 +111,7 @@ async fn test_grpc() -> Result<(), Box> { // No event filtering, includes all events let event_type_filter = None; // Only include PumpSwapBuy events and PumpSwapSell events - // let event_type_filter = Some(EventTypeFilter { include: vec![EventType::PumpFunBuy] }); + // let event_type_filter = Some(EventTypeFilter { include: vec![EventType::PumpFunTrade] }); println!("Starting to listen for events, press Ctrl+C to stop..."); println!("Monitoring programs: {:?}", account_include); @@ -144,49 +142,6 @@ async fn test_grpc() -> Result<(), Box> { Ok(()) } -async fn test_shreds() -> Result<(), Box> { - println!("Subscribing to ShredStream events..."); - - // Create low-latency configuration - let mut config = StreamClientConfig::low_latency(); - // Enable performance monitoring, has performance overhead, disabled by default - config.enable_metrics = true; - let shred_stream = - ShredStreamGrpc::new_with_config("http://127.0.0.1:10800".to_string(), config).await?; - - let callback = create_event_callback(); - let protocols = vec![ - Protocol::PumpFun, - Protocol::PumpSwap, - Protocol::Bonk, - Protocol::RaydiumCpmm, - Protocol::RaydiumClmm, - Protocol::RaydiumAmmV4, - ]; - - // Event filtering - // No event filtering, includes all events - let event_type_filter = None; - // Only include PumpSwapBuy events and PumpSwapSell events - // let event_type_filter = - // EventTypeFilter { include: vec![EventType::PumpSwapBuy, EventType::PumpSwapSell] }; - - println!("Listening for events, press Ctrl+C to stop..."); - shred_stream.shredstream_subscribe(protocols, None, event_type_filter, callback).await?; - - // 支持 stop 方法,测试代码 - 异步1000秒之后停止 - let shred_clone = shred_stream.clone(); - tokio::spawn(async move { - tokio::time::sleep(std::time::Duration::from_secs(1000)).await; - shred_clone.stop().await; - }); - - println!("Waiting for Ctrl+C to stop..."); - tokio::signal::ctrl_c().await?; - - Ok(()) -} - fn create_event_callback() -> impl Fn(Box) { |event: Box| { println!( @@ -339,4 +294,4 @@ fn create_event_callback() -> impl Fn(Box) { }, }); } -} +} \ No newline at end of file diff --git a/examples/shred_example.rs b/examples/shred_example.rs new file mode 100644 index 0000000..a1a9e90 --- /dev/null +++ b/examples/shred_example.rs @@ -0,0 +1,253 @@ +use solana_streamer_sdk::{ + match_event, + streaming::{ + event_parser::{ + common::EventType, + core::account_event_parser::CommonAccountEvent, + protocols::{ + bonk::{ + BonkGlobalConfigAccountEvent, BonkMigrateToAmmEvent, + BonkMigrateToCpswapEvent, BonkPlatformConfigAccountEvent, BonkPoolCreateEvent, + BonkPoolStateAccountEvent, BonkTradeEvent, + }, + pumpfun::{ + PumpFunBondingCurveAccountEvent, + PumpFunCreateTokenEvent, PumpFunGlobalAccountEvent, PumpFunMigrateEvent, + PumpFunTradeEvent, + }, + pumpswap::{ + PumpSwapBuyEvent, PumpSwapCreatePoolEvent, + PumpSwapDepositEvent, PumpSwapGlobalConfigAccountEvent, + PumpSwapPoolAccountEvent, PumpSwapSellEvent, PumpSwapWithdrawEvent, + }, + raydium_amm_v4::{ + RaydiumAmmV4AmmInfoAccountEvent, + RaydiumAmmV4DepositEvent, RaydiumAmmV4Initialize2Event, RaydiumAmmV4SwapEvent, + RaydiumAmmV4WithdrawEvent, RaydiumAmmV4WithdrawPnlEvent, + }, + raydium_clmm::{ + RaydiumClmmAmmConfigAccountEvent, + RaydiumClmmClosePositionEvent, RaydiumClmmCreatePoolEvent, + RaydiumClmmDecreaseLiquidityV2Event, RaydiumClmmIncreaseLiquidityV2Event, + RaydiumClmmOpenPositionV2Event, RaydiumClmmOpenPositionWithToken22NftEvent, + RaydiumClmmPoolStateAccountEvent, RaydiumClmmSwapEvent, RaydiumClmmSwapV2Event, + RaydiumClmmTickArrayStateAccountEvent, + }, + raydium_cpmm::{ + RaydiumCpmmAmmConfigAccountEvent, + RaydiumCpmmDepositEvent, RaydiumCpmmInitializeEvent, + RaydiumCpmmPoolStateAccountEvent, RaydiumCpmmSwapEvent, + RaydiumCpmmWithdrawEvent, + }, + BlockMetaEvent, + }, + Protocol, UnifiedEvent, + }, + shred::StreamClientConfig, + ShredStreamGrpc, + }, +}; + +#[tokio::main] +async fn main() -> Result<(), Box> { + println!("Starting ShredStream Streamer..."); + test_shreds().await?; + Ok(()) +} + +async fn test_shreds() -> Result<(), Box> { + println!("Subscribing to ShredStream events..."); + + // Create low-latency configuration + let mut config = StreamClientConfig::low_latency(); + // Enable performance monitoring, has performance overhead, disabled by default + config.enable_metrics = true; + let shred_stream = + ShredStreamGrpc::new_with_config("http://127.0.0.1:10800".to_string(), config).await?; + + let callback = create_event_callback(); + let protocols = vec![ + Protocol::PumpFun, + Protocol::PumpSwap, + Protocol::Bonk, + Protocol::RaydiumCpmm, + Protocol::RaydiumClmm, + Protocol::RaydiumAmmV4, + ]; + + // Event filtering + // No event filtering, includes all events + let event_type_filter = None; + // Only include PumpSwapBuy events and PumpSwapSell events + // let event_type_filter = + // EventTypeFilter { include: vec![EventType::PumpSwapBuy, EventType::PumpSwapSell] }; + + println!("Listening for events, press Ctrl+C to stop..."); + shred_stream.shredstream_subscribe(protocols, None, event_type_filter, callback).await?; + + // 支持 stop 方法,测试代码 - 异步1000秒之后停止 + let shred_clone = shred_stream.clone(); + tokio::spawn(async move { + tokio::time::sleep(std::time::Duration::from_secs(1000)).await; + shred_clone.stop().await; + }); + + println!("Waiting for Ctrl+C to stop..."); + tokio::signal::ctrl_c().await?; + + Ok(()) +} + +fn create_event_callback() -> impl Fn(Box) { + |event: Box| { + println!( + "🎉 Event received! Type: {:?}, transaction_index: {:?}", + event.event_type(), + event.transaction_index() + ); + match_event!(event, { + // -------------------------- block meta ----------------------- + BlockMetaEvent => |e: BlockMetaEvent| { + println!("BlockMetaEvent: {:?}", e.metadata.handle_us); + }, + // -------------------------- bonk ----------------------- + BonkPoolCreateEvent => |e: BonkPoolCreateEvent| { + // When using grpc, you can get block_time from each event + println!("block_time: {:?}, block_time_ms: {:?}", e.metadata.block_time, e.metadata.block_time_ms); + println!("BonkPoolCreateEvent: {:?}", e.base_mint_param.symbol); + }, + BonkTradeEvent => |e: BonkTradeEvent| { + println!("BonkTradeEvent: {e:?}"); + }, + BonkMigrateToAmmEvent => |e: BonkMigrateToAmmEvent| { + println!("BonkMigrateToAmmEvent: {e:?}"); + }, + BonkMigrateToCpswapEvent => |e: BonkMigrateToCpswapEvent| { + println!("BonkMigrateToCpswapEvent: {e:?}"); + }, + // -------------------------- pumpfun ----------------------- + PumpFunTradeEvent => |e: PumpFunTradeEvent| { + println!("PumpFunTradeEvent: {e:?}"); + }, + PumpFunMigrateEvent => |e: PumpFunMigrateEvent| { + println!("PumpFunMigrateEvent: {e:?}"); + }, + PumpFunCreateTokenEvent => |e: PumpFunCreateTokenEvent| { + println!("PumpFunCreateTokenEvent: {e:?}"); + }, + // -------------------------- pumpswap ----------------------- + PumpSwapBuyEvent => |e: PumpSwapBuyEvent| { + println!("Buy event: {e:?}"); + }, + PumpSwapSellEvent => |e: PumpSwapSellEvent| { + println!("Sell event: {e:?}"); + }, + PumpSwapCreatePoolEvent => |e: PumpSwapCreatePoolEvent| { + println!("CreatePool event: {e:?}"); + }, + PumpSwapDepositEvent => |e: PumpSwapDepositEvent| { + println!("Deposit event: {e:?}"); + }, + PumpSwapWithdrawEvent => |e: PumpSwapWithdrawEvent| { + println!("Withdraw event: {e:?}"); + }, + // -------------------------- raydium_cpmm ----------------------- + RaydiumCpmmSwapEvent => |e: RaydiumCpmmSwapEvent| { + println!("RaydiumCpmmSwapEvent: {e:?}"); + }, + RaydiumCpmmDepositEvent => |e: RaydiumCpmmDepositEvent| { + println!("RaydiumCpmmDepositEvent: {e:?}"); + }, + RaydiumCpmmInitializeEvent => |e: RaydiumCpmmInitializeEvent| { + println!("RaydiumCpmmInitializeEvent: {e:?}"); + }, + RaydiumCpmmWithdrawEvent => |e: RaydiumCpmmWithdrawEvent| { + println!("RaydiumCpmmWithdrawEvent: {e:?}"); + }, + // -------------------------- raydium_clmm ----------------------- + RaydiumClmmSwapEvent => |e: RaydiumClmmSwapEvent| { + println!("RaydiumClmmSwapEvent: {e:?}"); + }, + RaydiumClmmSwapV2Event => |e: RaydiumClmmSwapV2Event| { + println!("RaydiumClmmSwapV2Event: {e:?}"); + }, + RaydiumClmmClosePositionEvent => |e: RaydiumClmmClosePositionEvent| { + println!("RaydiumClmmClosePositionEvent: {e:?}"); + }, + RaydiumClmmDecreaseLiquidityV2Event => |e: RaydiumClmmDecreaseLiquidityV2Event| { + println!("RaydiumClmmDecreaseLiquidityV2Event: {e:?}"); + }, + RaydiumClmmCreatePoolEvent => |e: RaydiumClmmCreatePoolEvent| { + println!("RaydiumClmmCreatePoolEvent: {e:?}"); + }, + RaydiumClmmIncreaseLiquidityV2Event => |e: RaydiumClmmIncreaseLiquidityV2Event| { + println!("RaydiumClmmIncreaseLiquidityV2Event: {e:?}"); + }, + RaydiumClmmOpenPositionWithToken22NftEvent => |e: RaydiumClmmOpenPositionWithToken22NftEvent| { + println!("RaydiumClmmOpenPositionWithToken22NftEvent: {e:?}"); + }, + RaydiumClmmOpenPositionV2Event => |e: RaydiumClmmOpenPositionV2Event| { + println!("RaydiumClmmOpenPositionV2Event: {e:?}"); + }, + // -------------------------- raydium_amm_v4 ----------------------- + RaydiumAmmV4SwapEvent => |e: RaydiumAmmV4SwapEvent| { + println!("RaydiumAmmV4SwapEvent: {e:?}"); + }, + RaydiumAmmV4DepositEvent => |e: RaydiumAmmV4DepositEvent| { + println!("RaydiumAmmV4DepositEvent: {e:?}"); + }, + RaydiumAmmV4Initialize2Event => |e: RaydiumAmmV4Initialize2Event| { + println!("RaydiumAmmV4Initialize2Event: {e:?}"); + }, + RaydiumAmmV4WithdrawEvent => |e: RaydiumAmmV4WithdrawEvent| { + println!("RaydiumAmmV4WithdrawEvent: {e:?}"); + }, + RaydiumAmmV4WithdrawPnlEvent => |e: RaydiumAmmV4WithdrawPnlEvent| { + println!("RaydiumAmmV4WithdrawPnlEvent: {e:?}"); + }, + // -------------------------- account ----------------------- + BonkPoolStateAccountEvent => |e: BonkPoolStateAccountEvent| { + println!("BonkPoolStateAccountEvent: {e:?}"); + }, + BonkGlobalConfigAccountEvent => |e: BonkGlobalConfigAccountEvent| { + println!("BonkGlobalConfigAccountEvent: {e:?}"); + }, + BonkPlatformConfigAccountEvent => |e: BonkPlatformConfigAccountEvent| { + println!("BonkPlatformConfigAccountEvent: {e:?}"); + }, + PumpSwapGlobalConfigAccountEvent => |e: PumpSwapGlobalConfigAccountEvent| { + println!("PumpSwapGlobalConfigAccountEvent: {e:?}"); + }, + PumpSwapPoolAccountEvent => |e: PumpSwapPoolAccountEvent| { + println!("PumpSwapPoolAccountEvent: {e:?}"); + }, + PumpFunBondingCurveAccountEvent => |e: PumpFunBondingCurveAccountEvent| { + println!("PumpFunBondingCurveAccountEvent: {e:?}"); + }, + PumpFunGlobalAccountEvent => |e: PumpFunGlobalAccountEvent| { + println!("PumpFunGlobalAccountEvent: {e:?}"); + }, + RaydiumAmmV4AmmInfoAccountEvent => |e: RaydiumAmmV4AmmInfoAccountEvent| { + println!("RaydiumAmmV4AmmInfoAccountEvent: {e:?}"); + }, + RaydiumClmmAmmConfigAccountEvent => |e: RaydiumClmmAmmConfigAccountEvent| { + println!("RaydiumClmmAmmConfigAccountEvent: {e:?}"); + }, + RaydiumClmmPoolStateAccountEvent => |e: RaydiumClmmPoolStateAccountEvent| { + println!("RaydiumClmmPoolStateAccountEvent: {e:?}"); + }, + RaydiumClmmTickArrayStateAccountEvent => |e: RaydiumClmmTickArrayStateAccountEvent| { + println!("RaydiumClmmTickArrayStateAccountEvent: {e:?}"); + }, + RaydiumCpmmAmmConfigAccountEvent => |e: RaydiumCpmmAmmConfigAccountEvent| { + println!("RaydiumCpmmAmmConfigAccountEvent: {e:?}"); + }, + RaydiumCpmmPoolStateAccountEvent => |e: RaydiumCpmmPoolStateAccountEvent| { + println!("RaydiumCpmmPoolStateAccountEvent: {e:?}"); + }, + CommonAccountEvent => |e: CommonAccountEvent| { + println!("CommonAccountEvent: {e:?}"); + }, + }); + } +} \ No newline at end of file