diff --git a/Cargo.toml b/Cargo.toml index 0871b04..6f35cd7 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sol-trade-sdk" -version = "1.2.3" +version = "2.0.0" edition = "2021" authors = [ "William ", @@ -17,7 +17,6 @@ readme = "README.md" [workspace] members = [ "examples/trading_client", - "examples/event_subscription", "examples/middleware_system", "examples/pumpfun_copy_trading", "examples/pumpfun_sniper_trading", @@ -39,22 +38,24 @@ members = [ crate-type = ["cdylib", "rlib"] [dependencies] -solana-streamer-sdk = "0.4.13" -solana-sdk = "2.3.0" -solana-client = "2.3.6" -solana-program = "2.3.0" -solana-rpc-client = "2.3.6" -solana-rpc-client-api = "2.3.6" -solana-transaction-status = "2.3.6" -solana-account-decoder = "2.3.6" -solana-hash = "2.3.0" -solana-entry = "2.3.6" -solana-rpc-client-nonce-utils = "2.3.6" -solana-perf = "2.3.6" -solana-metrics = "2.3.6" -spl-token = "8.0.0" -spl-token-2022 = { version = "8.0.0", features = ["no-entrypoint"] } -spl-associated-token-account = "7.0.0" +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-client = "3.0.0" +solana-program = "3.0.0" +solana-rpc-client = "3.0.0" +solana-rpc-client-api = "3.0.0" +solana-transaction-status = "3.0.0" +solana-account-decoder = "3.0.0" +solana-hash = "3.0.0" +solana-entry = "3.0.0" +solana-rpc-client-nonce-utils = "3.0.0" +solana-perf = "3.0.0" +solana-metrics = "3.0.0" +solana-nonce = "3.0.0" +solana-address-lookup-table-interface = "3.0.0" +solana-compute-budget-interface = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } + borsh = { version = "1.5.3", features = ["derive"] } isahc = "1.7.2" serde = { version = "1.0.215", features = ["derive"] } @@ -66,11 +67,11 @@ bs58 = "0.5.1" rand = "0.9.0" bincode = "1.3.3" anyhow = "1.0.90" -yellowstone-grpc-client = { version = "8.0.0" } -yellowstone-grpc-proto = { version = "8.0.0" } +yellowstone-grpc-client = { version = "9.0.0" } +yellowstone-grpc-proto = { version = "9.0.0" } reqwest = { version = "0.12.12", features = ["json", "multipart"] } tokio = { version = "1.42.0" , features = ["full", "rt-multi-thread"]} -tonic = { version = "0.12.3", features = ["tls", "tls-roots", "tls-webpki-roots"] } +tonic = { version = "0.14.2", features = ["transport"] } rustls = { version = "0.23.23", features = ["ring"] } rustls-native-certs = "0.8.1" tokio-rustls = "0.26.1" @@ -83,8 +84,8 @@ thiserror = "2.0.11" async-trait = "0.1.86" lazy_static = "1.5.0" once_cell = "1.20.3" -prost = "0.13.5" -prost-types = "0.13.5" +prost = "0.14.1" +prost-types = "0.14.1" num_enum = "0.7.3" num-derive = "0.4.2" num-traits = "0.2.19" @@ -93,11 +94,12 @@ bytemuck = { version = "1.4.0" } arrayref = "0.3.6" borsh-derive = "1.5.5" indicatif = "0.18.0" -solana-system-interface = { version = "1.0.0", features = ["bincode"] } +solana-system-interface = { version = "2.0.0", features = ["bincode"] } fnv = "1.0.7" dashmap = "6.1.0" clru = "0.6" smallvec = "1.15.1" parking_lot = "0.12" arc-swap = "1.7" -sha2 = "0.10" \ No newline at end of file +sha2 = "0.10" +tonic-prost = "0.14.2" diff --git a/README.md b/README.md index da99f50..2b83e69 100644 --- a/README.md +++ b/README.md @@ -87,14 +87,14 @@ Add the dependency to your `Cargo.toml`: ```toml # Add to your Cargo.toml -sol-trade-sdk = { path = "./sol-trade-sdk", version = "1.2.3" } +sol-trade-sdk = { path = "./sol-trade-sdk", version = "2.0.0" } ``` ### Use crates.io ```toml # Add to your Cargo.toml -sol-trade-sdk = "1.2.3" +sol-trade-sdk = "2.0.0" ``` ## 🛠️ Usage Examples @@ -179,7 +179,6 @@ Please ensure that the parameters your trading logic depends on are available in | Description | Run Command | Source Code | |-------------|-------------|-------------| -| Monitor token trading events | `cargo run --package event_subscription` | [examples/event_subscription](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/event_subscription/src/main.rs) | | Create and configure SolanaTrade instance | `cargo run --package trading_client` | [examples/trading_client](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/trading_client/src/main.rs) | | PumpFun token sniping trading | `cargo run --package pumpfun_sniper_trading` | [examples/pumpfun_sniper_trading](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/pumpfun_sniper_trading/src/main.rs) | | PumpFun token copy trading | `cargo run --package pumpfun_copy_trading` | [examples/pumpfun_copy_trading](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/pumpfun_copy_trading/src/main.rs) | @@ -272,7 +271,6 @@ src/ ├── constants/ # Constant definitions ├── instruction/ # Instruction building │ └── utils/ # Instruction utilities -├── protos/ # gRPC protocol definitions ├── swqos/ # MEV service clients ├── trading/ # Unified trading engine │ ├── common/ # Common trading tools diff --git a/README_CN.md b/README_CN.md index dbe48ce..7eff7aa 100755 --- a/README_CN.md +++ b/README_CN.md @@ -87,14 +87,14 @@ git clone https://github.com/0xfnzero/sol-trade-sdk ```toml # 添加到您的 Cargo.toml -sol-trade-sdk = { path = "./sol-trade-sdk", version = "1.2.3" } +sol-trade-sdk = { path = "./sol-trade-sdk", version = "2.0.0" } ``` ### 使用 crates.io ```toml # 添加到您的 Cargo.toml -sol-trade-sdk = "1.2.3" +sol-trade-sdk = "2.0.0" ``` ## 🛠️ 使用示例 @@ -180,7 +180,6 @@ client.buy(buy_params).await?; | 描述 | 运行命令 | 源码路径 | |------|---------|----------| -| 监听代币交易事件 | `cargo run --package event_subscription` | [examples/event_subscription](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/event_subscription/src/main.rs) | | 创建和配置 SolanaTrade 实例 | `cargo run --package trading_client` | [examples/trading_client](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/trading_client/src/main.rs) | | PumpFun 代币狙击交易 | `cargo run --package pumpfun_sniper_trading` | [examples/pumpfun_sniper_trading](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/pumpfun_sniper_trading/src/main.rs) | | PumpFun 代币跟单交易 | `cargo run --package pumpfun_copy_trading` | [examples/pumpfun_copy_trading](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/pumpfun_copy_trading/src/main.rs) | @@ -273,7 +272,6 @@ src/ ├── constants/ # 常量定义 ├── instruction/ # 指令构建 │ └── utils/ # 指令工具函数 -├── protos/ # gRPC 协议定义 ├── swqos/ # MEV 服务客户端 ├── trading/ # 统一交易引擎 │ ├── common/ # 通用交易工具 diff --git a/examples/address_lookup/Cargo.toml b/examples/address_lookup/Cargo.toml index dbc8aef..61c2097 100644 --- a/examples/address_lookup/Cargo.toml +++ b/examples/address_lookup/Cargo.toml @@ -5,7 +5,9 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" -spl-associated-token-account = "7.0.0" +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-address-lookup-table-interface = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } tokio = { version = "1", features = ["full"] } anyhow = "1.0.94" diff --git a/examples/address_lookup/src/main.rs b/examples/address_lookup/src/main.rs index ab5dd01..0cfc806 100644 --- a/examples/address_lookup/src/main.rs +++ b/examples/address_lookup/src/main.rs @@ -1,3 +1,23 @@ +use sol_trade_sdk::common::address_lookup_cache::AddressLookupTableCache; +use sol_trade_sdk::common::SolanaRpcClient; +use sol_trade_sdk::common::TradeConfig; +use sol_trade_sdk::{ + common::AnyResult, + swqos::SwqosConfig, + trading::{core::params::PumpFunParams, factory::DexType}, + SolanaTrade, +}; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::pubkey::Pubkey; +use solana_sdk::signature::Keypair; +use solana_streamer_sdk::match_event; +use solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; +use solana_streamer_sdk::streaming::event_parser::common::EventType; +use solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::parser::PUMPFUN_PROGRAM_ID; +use solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; +use solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; +use solana_streamer_sdk::streaming::yellowstone_grpc::{AccountFilter, TransactionFilter}; +use solana_streamer_sdk::streaming::YellowstoneGrpc; use std::{ str::FromStr, sync::{ @@ -6,31 +26,6 @@ use std::{ }, }; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::parser::PUMPFUN_PROGRAM_ID; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; -use sol_trade_sdk::solana_streamer_sdk::streaming::yellowstone_grpc::{ - AccountFilter, TransactionFilter, -}; -use sol_trade_sdk::solana_streamer_sdk::streaming::YellowstoneGrpc; -use sol_trade_sdk::{ - common::address_lookup_cache::AddressLookupTableCache, - solana_streamer_sdk::streaming::event_parser::common::EventType, -}; -use sol_trade_sdk::{ - common::AnyResult, - swqos::SwqosConfig, - trading::{core::params::PumpFunParams, factory::DexType}, - SolanaTrade, -}; -use sol_trade_sdk::{ - common::SolanaRpcClient, - solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter, -}; -use sol_trade_sdk::{common::TradeConfig, solana_streamer_sdk::match_event}; -use solana_sdk::pubkey::Pubkey; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; - // Global static flag to ensure transaction is executed only once static ALREADY_EXECUTED: AtomicBool = AtomicBool::new(false); diff --git a/examples/bonk_copy_trading/Cargo.toml b/examples/bonk_copy_trading/Cargo.toml index c61c9b1..f75fab6 100644 --- a/examples/bonk_copy_trading/Cargo.toml +++ b/examples/bonk_copy_trading/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" -spl-associated-token-account = "7.0.0" +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } tokio = { version = "1", features = ["full"] } diff --git a/examples/bonk_copy_trading/src/main.rs b/examples/bonk_copy_trading/src/main.rs index 58c284d..021f9b6 100644 --- a/examples/bonk_copy_trading/src/main.rs +++ b/examples/bonk_copy_trading/src/main.rs @@ -3,25 +3,25 @@ use std::sync::{ Arc, }; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::common::EventType; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::protocols::bonk::parser::BONK_PROGRAM_ID; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::protocols::bonk::BonkTradeEvent; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; -use sol_trade_sdk::solana_streamer_sdk::streaming::yellowstone_grpc::{ - AccountFilter, TransactionFilter, -}; -use sol_trade_sdk::solana_streamer_sdk::streaming::YellowstoneGrpc; +use sol_trade_sdk::common::spl_associated_token_account::get_associated_token_address; +use sol_trade_sdk::common::TradeConfig; use sol_trade_sdk::{ common::AnyResult, swqos::SwqosConfig, trading::{core::params::BonkParams, factory::DexType}, SolanaTrade, }; -use sol_trade_sdk::{common::TradeConfig, solana_streamer_sdk::match_event}; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::signature::Keypair; use solana_sdk::signer::Signer; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; -use spl_associated_token_account::get_associated_token_address; +use solana_streamer_sdk::match_event; +use solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; +use solana_streamer_sdk::streaming::event_parser::common::EventType; +use solana_streamer_sdk::streaming::event_parser::protocols::bonk::parser::BONK_PROGRAM_ID; +use solana_streamer_sdk::streaming::event_parser::protocols::bonk::BonkTradeEvent; +use solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; +use solana_streamer_sdk::streaming::yellowstone_grpc::{AccountFilter, TransactionFilter}; +use solana_streamer_sdk::streaming::YellowstoneGrpc; // Global static flag to ensure transaction is executed only once static ALREADY_EXECUTED: AtomicBool = AtomicBool::new(false); diff --git a/examples/bonk_sniper_trading/Cargo.toml b/examples/bonk_sniper_trading/Cargo.toml index b317b98..62da9b4 100644 --- a/examples/bonk_sniper_trading/Cargo.toml +++ b/examples/bonk_sniper_trading/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" -spl-associated-token-account = "7.0.0" +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } tokio = { version = "1", features = ["full"] } diff --git a/examples/bonk_sniper_trading/src/main.rs b/examples/bonk_sniper_trading/src/main.rs index a590151..7f71897 100644 --- a/examples/bonk_sniper_trading/src/main.rs +++ b/examples/bonk_sniper_trading/src/main.rs @@ -1,18 +1,19 @@ +use sol_trade_sdk::common::spl_associated_token_account::get_associated_token_address; use sol_trade_sdk::common::TradeConfig; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::common::EventType; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::protocols::bonk::BonkTradeEvent; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; -use sol_trade_sdk::solana_streamer_sdk::{match_event, streaming::ShredStreamGrpc}; +use solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; +use solana_streamer_sdk::streaming::event_parser::common::EventType; +use solana_streamer_sdk::streaming::event_parser::protocols::bonk::BonkTradeEvent; +use solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; +use solana_streamer_sdk::{match_event, streaming::ShredStreamGrpc}; use sol_trade_sdk::{ common::AnyResult, swqos::SwqosConfig, trading::{core::params::BonkParams, factory::DexType}, SolanaTrade, }; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::signature::Keypair; use solana_sdk::signer::Signer; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; -use spl_associated_token_account::get_associated_token_address; use std::sync::{ atomic::{AtomicBool, Ordering}, Arc, diff --git a/examples/cli_trading/Cargo.toml b/examples/cli_trading/Cargo.toml index 073101c..2413f79 100644 --- a/examples/cli_trading/Cargo.toml +++ b/examples/cli_trading/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } +solana-system-interface = "2.0.0" tokio = { version = "1", features = ["full"] } clap = { version = "4.0", features = ["derive"] } -spl-token = "8.0.0" -spl-associated-token-account = "7.0.0" \ No newline at end of file diff --git a/examples/cli_trading/src/main.rs b/examples/cli_trading/src/main.rs index d7827b0..cd0e7f7 100644 --- a/examples/cli_trading/src/main.rs +++ b/examples/cli_trading/src/main.rs @@ -1,8 +1,14 @@ use clap::Parser; use sol_trade_sdk::{ common::{ - fast_fn::get_associated_token_address_with_program_id_fast_use_seed, AnyResult, TradeConfig, + fast_fn::get_associated_token_address_with_program_id_fast_use_seed, + spl_associated_token_account::{ + create_associated_token_account_idempotent, get_associated_token_address, + }, + spl_token::{self, close_account}, + AnyResult, TradeConfig, }, + constants::WSOL_TOKEN_ACCOUNT, swqos::SwqosConfig, trading::{ core::params::{ @@ -12,10 +18,15 @@ use sol_trade_sdk::{ }, SolanaTrade, TradeBuyParams, TradeSellParams, TradeTokenType, }; +use solana_commitment_config::CommitmentConfig; use solana_sdk::{ - commitment_config::CommitmentConfig, native_token::sol_str_to_lamports, pubkey::Pubkey, - signature::Keypair, signer::Signer, + message::{AccountMeta, Instruction}, + native_token::sol_str_to_lamports, + pubkey::Pubkey, + signature::Keypair, + signer::Signer, }; +use solana_system_interface::instruction::transfer; use std::sync::{Arc, LazyLock}; use std::{ io::{self, Write}, @@ -1238,7 +1249,7 @@ async fn handle_close_wsol() -> Result<(), Box> { match initialize_real_client().await { Ok(client) => { // Check WSOL balance first - let wsol_mint = spl_token::native_mint::id(); + let wsol_mint = WSOL_TOKEN_ACCOUNT; match client.get_payer_token_balance(&wsol_mint).await { Ok(wsol_balance) => { if wsol_balance == 0 { @@ -1332,29 +1343,27 @@ async fn wrap_sol_real( let wsol_mint = "So11111111111111111111111111111111111111112".parse().unwrap(); let instructions = vec![ // Create associated token account for WSOL - spl_associated_token_account::instruction::create_associated_token_account_idempotent( + create_associated_token_account_idempotent( &client.get_payer_pubkey(), &client.get_payer_pubkey(), &wsol_mint, &spl_token::ID, ), // Transfer SOL to WSOL account - solana_sdk::system_instruction::transfer( + transfer( &client.get_payer_pubkey(), - &spl_associated_token_account::get_associated_token_address( - &client.get_payer_pubkey(), - &wsol_mint, - ), + &get_associated_token_address(&client.get_payer_pubkey(), &wsol_mint), amount_lamports, ), // Sync native (convert SOL to WSOL tokens) - spl_token::instruction::sync_native( - &spl_token::ID, - &spl_associated_token_account::get_associated_token_address( - &client.get_payer_pubkey(), - &wsol_mint, - ), - )?, + Instruction { + program_id: sol_trade_sdk::constants::TOKEN_PROGRAM, + accounts: vec![AccountMeta::new( + get_associated_token_address(&client.get_payer_pubkey(), &wsol_mint), + false, + )], + data: vec![17], + }, ]; // Build and send transaction @@ -1375,10 +1384,7 @@ async fn close_wsol_real(client: &SolanaTrade) -> Result<(), Box Result<(), Box Result<(), Box> { - println!("This example demonstrates how to subscribe to events using Yellowstone gRPC and ShredStream."); - println!("You can choose which example to run by uncommenting the relevant function call."); - - // Uncomment one of these to run the example: - test_grpc().await?; // Use public Yellowstone gRPC endpoint - // test_shreds().await?; // Use local ShredStream endpoint - - Ok(()) -} - -/// Subscribe to events using Yellowstone gRPC -async fn test_grpc() -> Result<(), Box> { - println!("Subscribing to GRPC events..."); - - // Initialize gRPC client with public endpoint - let grpc = YellowstoneGrpc::new( - "https://solana-yellowstone-grpc.publicnode.com:443".to_string(), - None, // No auth token needed - )?; - - let callback = create_event_callback(); - - // Define protocols to monitor - let protocols = - vec![Protocol::PumpFun, Protocol::PumpSwap, Protocol::Bonk, Protocol::RaydiumCpmm]; - - // Define program IDs to monitor - 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![]; - - // Configure transaction filter - let transaction_filter = TransactionFilter { - account_include: account_include.clone(), - account_exclude, - account_required, - }; - - // Configure account filter for program-owned accounts - let account_filter = - AccountFilter { account: vec![], owner: account_include.clone(), filters: vec![] }; - - // Configure event type filter (all events) - let event_type_filter = None; - // For specific events only: - // let event_type_filter = - // EventTypeFilter { include: vec![EventType::PumpSwapBuy, EventType::PumpSwapSell] }; - - println!("Starting to listen for events, press Ctrl+C to stop..."); - - // Start subscription - grpc.subscribe_events_immediate( - protocols, - None, - vec![transaction_filter], - vec![account_filter], - event_type_filter, - None, - callback, - ) - .await?; - - // Wait for termination signal - tokio::signal::ctrl_c().await?; - - Ok(()) -} - -/// Subscribe to events using ShredStream -async fn test_shreds() -> Result<(), Box> { - println!("Subscribing to ShredStream events..."); - - // Initialize ShredStream client with local endpoint - let shred_stream = ShredStreamGrpc::new("http://127.0.0.1:10800".to_string()).await?; - - let callback = create_event_callback(); - - // Define protocols to monitor - let protocols = vec![Protocol::PumpFun, Protocol::PumpSwap, Protocol::Bonk]; - - // Configure event type filter (all events) - let event_type_filter = None; - // For specific events only: - // let event_type_filter = - // EventTypeFilter { include: vec![EventType::PumpSwapBuy, EventType::PumpSwapSell] }; - - println!("Starting to listen for events, press Ctrl+C to stop..."); - - // Start subscription - shred_stream - .shredstream_subscribe( - protocols, - None, // No slot range specified - event_type_filter, - callback, - ) - .await?; - - // Wait for termination signal - tokio::signal::ctrl_c().await?; - - Ok(()) -} - -/// Create an event callback function that handles different types of events -fn create_event_callback() -> impl Fn(Box) { - |event: Box| { - // Process events using match_event! macro - match_event!(event, { - // Bonk protocol events - BonkPoolCreateEvent => |e: BonkPoolCreateEvent| { - println!("BonkPoolCreateEvent: {:?}", e.base_mint_param.symbol); - }, - BonkTradeEvent => |e: BonkTradeEvent| { - println!("BonkTradeEvent: {:?}", e); - }, - - // PumpFun protocol events - PumpFunTradeEvent => |e: PumpFunTradeEvent| { - println!("PumpFunTradeEvent: {:?}", e); - }, - PumpFunCreateTokenEvent => |e: PumpFunCreateTokenEvent| { - println!("PumpFunCreateTokenEvent: {:?}", e); - }, - - // PumpSwap protocol events - 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 protocol events - RaydiumCpmmSwapEvent => |e: RaydiumCpmmSwapEvent| { - println!("RaydiumCpmmSwapEvent: {:?}", e); - }, - // For more events and documentation, please refer to https://github.com/0xfnzero/solana-streamer - }); - } -} diff --git a/examples/middleware_system/Cargo.toml b/examples/middleware_system/Cargo.toml index d270db3..42670e8 100644 --- a/examples/middleware_system/Cargo.toml +++ b/examples/middleware_system/Cargo.toml @@ -5,6 +5,8 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } tokio = { version = "1", features = ["full"] } anyhow = "1.0.79" \ No newline at end of file diff --git a/examples/middleware_system/src/main.rs b/examples/middleware_system/src/main.rs index 1147274..3e0efb5 100644 --- a/examples/middleware_system/src/main.rs +++ b/examples/middleware_system/src/main.rs @@ -8,10 +8,8 @@ use sol_trade_sdk::{ }, SolanaTrade, TradeTokenType, }; -use solana_sdk::{ - commitment_config::CommitmentConfig, instruction::Instruction, pubkey::Pubkey, - signature::Keypair, -}; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::{instruction::Instruction, pubkey::Pubkey, signature::Keypair}; use std::{str::FromStr, sync::Arc}; #[tokio::main] diff --git a/examples/nonce_cache/Cargo.toml b/examples/nonce_cache/Cargo.toml index 214411b..dff0001 100644 --- a/examples/nonce_cache/Cargo.toml +++ b/examples/nonce_cache/Cargo.toml @@ -5,7 +5,9 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } spl-associated-token-account = "7.0.0" tokio = { version = "1", features = ["full"] } anyhow = "1.0.94" diff --git a/examples/nonce_cache/src/main.rs b/examples/nonce_cache/src/main.rs index b7cb12c..9b0224b 100644 --- a/examples/nonce_cache/src/main.rs +++ b/examples/nonce_cache/src/main.rs @@ -3,28 +3,25 @@ use std::sync::{ Arc, }; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::common::EventType; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; -use sol_trade_sdk::solana_streamer_sdk::streaming::yellowstone_grpc::{ - AccountFilter, TransactionFilter, -}; -use sol_trade_sdk::solana_streamer_sdk::streaming::YellowstoneGrpc; -use sol_trade_sdk::{ - common::nonce_cache::NonceCache, - solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::parser::PUMPFUN_PROGRAM_ID, -}; +use sol_trade_sdk::common::nonce_cache::NonceCache; +use sol_trade_sdk::common::TradeConfig; +use sol_trade_sdk::TradeTokenType; use sol_trade_sdk::{ common::AnyResult, swqos::SwqosConfig, trading::{core::params::PumpFunParams, factory::DexType}, SolanaTrade, }; -use sol_trade_sdk::{common::TradeConfig, solana_streamer_sdk::match_event}; -use sol_trade_sdk::{ - solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter, TradeTokenType, -}; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::signature::Keypair; +use solana_streamer_sdk::match_event; +use solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; +use solana_streamer_sdk::streaming::event_parser::common::EventType; +use solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::parser::PUMPFUN_PROGRAM_ID; +use solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; +use solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; +use solana_streamer_sdk::streaming::yellowstone_grpc::{AccountFilter, TransactionFilter}; +use solana_streamer_sdk::streaming::YellowstoneGrpc; // Global static flag to ensure transaction is executed only once static ALREADY_EXECUTED: AtomicBool = AtomicBool::new(false); diff --git a/examples/pumpfun_copy_trading/Cargo.toml b/examples/pumpfun_copy_trading/Cargo.toml index e1a431c..9ced16a 100644 --- a/examples/pumpfun_copy_trading/Cargo.toml +++ b/examples/pumpfun_copy_trading/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" -spl-associated-token-account = "7.0.0" +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } tokio = { version = "1", features = ["full"] } diff --git a/examples/pumpfun_copy_trading/src/main.rs b/examples/pumpfun_copy_trading/src/main.rs index 7cd6264..d1a3431 100644 --- a/examples/pumpfun_copy_trading/src/main.rs +++ b/examples/pumpfun_copy_trading/src/main.rs @@ -3,27 +3,27 @@ use std::sync::{ Arc, }; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::common::EventType; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::parser::PUMPFUN_PROGRAM_ID; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; -use sol_trade_sdk::solana_streamer_sdk::streaming::yellowstone_grpc::{ - AccountFilter, TransactionFilter, +use sol_trade_sdk::common::{ + spl_associated_token_account::get_associated_token_address, TradeConfig, }; -use sol_trade_sdk::solana_streamer_sdk::streaming::YellowstoneGrpc; +use sol_trade_sdk::TradeTokenType; use sol_trade_sdk::{ common::AnyResult, swqos::SwqosConfig, trading::{core::params::PumpFunParams, factory::DexType}, SolanaTrade, }; -use sol_trade_sdk::{common::TradeConfig, solana_streamer_sdk::match_event}; -use sol_trade_sdk::{ - solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter, TradeTokenType, -}; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::signature::Keypair; use solana_sdk::signer::Signer; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; -use spl_associated_token_account::get_associated_token_address; +use solana_streamer_sdk::match_event; +use solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; +use solana_streamer_sdk::streaming::event_parser::common::EventType; +use solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::parser::PUMPFUN_PROGRAM_ID; +use solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; +use solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; +use solana_streamer_sdk::streaming::yellowstone_grpc::{AccountFilter, TransactionFilter}; +use solana_streamer_sdk::streaming::YellowstoneGrpc; // Global static flag to ensure transaction is executed only once static ALREADY_EXECUTED: AtomicBool = AtomicBool::new(false); diff --git a/examples/pumpfun_sniper_trading/Cargo.toml b/examples/pumpfun_sniper_trading/Cargo.toml index 48db355..0dbb2c4 100644 --- a/examples/pumpfun_sniper_trading/Cargo.toml +++ b/examples/pumpfun_sniper_trading/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" -spl-associated-token-account = "7.0.0" +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } tokio = { version = "1", features = ["full"] } diff --git a/examples/pumpfun_sniper_trading/src/main.rs b/examples/pumpfun_sniper_trading/src/main.rs index c8abb5c..77a62f0 100644 --- a/examples/pumpfun_sniper_trading/src/main.rs +++ b/examples/pumpfun_sniper_trading/src/main.rs @@ -1,9 +1,5 @@ +use sol_trade_sdk::common::spl_associated_token_account::get_associated_token_address; use sol_trade_sdk::common::TradeConfig; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::common::EventType; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; -use sol_trade_sdk::solana_streamer_sdk::{match_event, streaming::ShredStreamGrpc}; use sol_trade_sdk::TradeTokenType; use sol_trade_sdk::{ common::AnyResult, @@ -11,10 +7,14 @@ use sol_trade_sdk::{ trading::{core::params::PumpFunParams, factory::DexType}, SolanaTrade, }; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::signature::Keypair; use solana_sdk::signer::Signer; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; -use spl_associated_token_account::get_associated_token_address; -use std::mem::take; +use solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; +use solana_streamer_sdk::streaming::event_parser::common::EventType; +use solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; +use solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; +use solana_streamer_sdk::{match_event, streaming::ShredStreamGrpc}; use std::sync::{ atomic::{AtomicBool, Ordering}, Arc, diff --git a/examples/pumpswap_direct_trading/Cargo.toml b/examples/pumpswap_direct_trading/Cargo.toml index 21deed4..e4d855b 100644 --- a/examples/pumpswap_direct_trading/Cargo.toml +++ b/examples/pumpswap_direct_trading/Cargo.toml @@ -5,8 +5,7 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" -spl-associated-token-account = "7.0.0" +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } tokio = { version = "1", features = ["full"] } -spl-token= "8.0.0" -spl-token-2022 = { version = "8.0.0", features = ["no-entrypoint"] } \ No newline at end of file diff --git a/examples/pumpswap_direct_trading/src/main.rs b/examples/pumpswap_direct_trading/src/main.rs index aaf814f..cd15476 100644 --- a/examples/pumpswap_direct_trading/src/main.rs +++ b/examples/pumpswap_direct_trading/src/main.rs @@ -1,12 +1,15 @@ use sol_trade_sdk::{ - common::{AnyResult, TradeConfig}, + common::{ + spl_associated_token_account::get_associated_token_address_with_program_id, AnyResult, + TradeConfig, + }, swqos::SwqosConfig, trading::{core::params::PumpSwapParams, factory::DexType}, SolanaTrade, TradeTokenType, }; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::signature::Keypair; use solana_sdk::{pubkey::Pubkey, signer::Signer}; -use spl_associated_token_account::get_associated_token_address_with_program_id; use std::{str::FromStr, sync::Arc}; #[tokio::main] @@ -47,7 +50,7 @@ async fn main() -> Result<(), Box> { let rpc = client.rpc.clone(); let payer = client.payer.pubkey(); - let program_id = spl_token_2022::ID; + let program_id = sol_trade_sdk::constants::TOKEN_PROGRAM_2022; let account = get_associated_token_address_with_program_id(&payer, &mint_pubkey, &program_id); let balance = rpc.get_token_account_balance(&account).await?; let amount_token = balance.amount.parse::().unwrap(); diff --git a/examples/pumpswap_trading/Cargo.toml b/examples/pumpswap_trading/Cargo.toml index 3ee9cfe..ad1faf5 100644 --- a/examples/pumpswap_trading/Cargo.toml +++ b/examples/pumpswap_trading/Cargo.toml @@ -5,7 +5,8 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" -spl-associated-token-account = "7.0.0" +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } tokio = { version = "1", features = ["full"] } spl-token-2022 = { version = "8.0.0", features = ["no-entrypoint"] } \ No newline at end of file diff --git a/examples/pumpswap_trading/src/main.rs b/examples/pumpswap_trading/src/main.rs index 867d509..ab7530b 100644 --- a/examples/pumpswap_trading/src/main.rs +++ b/examples/pumpswap_trading/src/main.rs @@ -1,40 +1,31 @@ -use std::sync::{ - atomic::{AtomicBool, Ordering}, - Arc, -}; - -use sol_trade_sdk::solana_streamer_sdk::streaming::yellowstone_grpc::{ - AccountFilter, TransactionFilter, -}; -use sol_trade_sdk::solana_streamer_sdk::streaming::YellowstoneGrpc; -use sol_trade_sdk::solana_streamer_sdk::{ - match_event, streaming::event_parser::protocols::pumpswap::parser::PUMPSWAP_PROGRAM_ID, -}; +use sol_trade_sdk::common::spl_associated_token_account::get_associated_token_address_with_program_id; +use sol_trade_sdk::common::TradeConfig; +use sol_trade_sdk::TradeTokenType; use sol_trade_sdk::{ common::AnyResult, swqos::SwqosConfig, trading::{core::params::PumpSwapParams, factory::DexType}, SolanaTrade, }; -use sol_trade_sdk::{ - common::TradeConfig, - solana_streamer_sdk::streaming::event_parser::{ - common::EventType, protocols::pumpswap::PumpSwapSellEvent, - }, -}; -use sol_trade_sdk::{ - instruction::utils::pumpswap::accounts, - solana_streamer_sdk::streaming::event_parser::{ - common::filter::EventTypeFilter, protocols::pumpswap::PumpSwapBuyEvent, - }, -}; -use sol_trade_sdk::{ - solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}, - TradeTokenType, -}; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::signature::Keypair; use solana_sdk::{pubkey::Pubkey, signer::Signer}; -use spl_associated_token_account::get_associated_token_address_with_program_id; +use solana_streamer_sdk::streaming::event_parser::{ + common::filter::EventTypeFilter, protocols::pumpswap::PumpSwapBuyEvent, +}; +use solana_streamer_sdk::streaming::event_parser::{ + common::EventType, protocols::pumpswap::PumpSwapSellEvent, +}; +use solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; +use solana_streamer_sdk::streaming::yellowstone_grpc::{AccountFilter, TransactionFilter}; +use solana_streamer_sdk::streaming::YellowstoneGrpc; +use solana_streamer_sdk::{ + match_event, streaming::event_parser::protocols::pumpswap::parser::PUMPSWAP_PROGRAM_ID, +}; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; // Global static flag to ensure transaction is executed only once static ALREADY_EXECUTED: AtomicBool = AtomicBool::new(false); diff --git a/examples/raydium_amm_v4_trading/Cargo.toml b/examples/raydium_amm_v4_trading/Cargo.toml index c1f9ecf..202d6ef 100644 --- a/examples/raydium_amm_v4_trading/Cargo.toml +++ b/examples/raydium_amm_v4_trading/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" -spl-associated-token-account = "7.0.0" +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } tokio = { version = "1", features = ["full"] } diff --git a/examples/raydium_amm_v4_trading/src/main.rs b/examples/raydium_amm_v4_trading/src/main.rs index 4383b20..d0f5232 100644 --- a/examples/raydium_amm_v4_trading/src/main.rs +++ b/examples/raydium_amm_v4_trading/src/main.rs @@ -1,26 +1,29 @@ -use std::sync::{ - atomic::{AtomicBool, Ordering}, - Arc, -}; - -use sol_trade_sdk::{common::TradeConfig, instruction::utils::raydium_amm_v4::{accounts, fetch_amm_info}, solana_streamer_sdk::{match_event, streaming::event_parser::protocols::raydium_amm_v4::RaydiumAmmV4SwapEvent}, trading::common::get_multi_token_balances, TradeTokenType}; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::common::EventType; -use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::protocols::raydium_amm_v4::parser::RAYDIUM_AMM_V4_PROGRAM_ID; -use sol_trade_sdk::{solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}}; -use sol_trade_sdk::solana_streamer_sdk::streaming::yellowstone_grpc::{ - AccountFilter, TransactionFilter, -}; -use sol_trade_sdk::solana_streamer_sdk::streaming::YellowstoneGrpc; use sol_trade_sdk::{ - common::AnyResult, + common::TradeConfig, instruction::utils::raydium_amm_v4::fetch_amm_info, + trading::common::get_multi_token_balances, TradeTokenType, +}; +use sol_trade_sdk::{ + common::{spl_associated_token_account::get_associated_token_address, AnyResult}, swqos::SwqosConfig, trading::{core::params::RaydiumAmmV4Params, factory::DexType}, SolanaTrade, }; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::signature::Keypair; use solana_sdk::signer::Signer; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; -use spl_associated_token_account::get_associated_token_address; +use solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; +use solana_streamer_sdk::streaming::event_parser::common::EventType; +use solana_streamer_sdk::streaming::event_parser::protocols::raydium_amm_v4::parser::RAYDIUM_AMM_V4_PROGRAM_ID; +use solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; +use solana_streamer_sdk::streaming::yellowstone_grpc::{AccountFilter, TransactionFilter}; +use solana_streamer_sdk::streaming::YellowstoneGrpc; +use solana_streamer_sdk::{ + match_event, streaming::event_parser::protocols::raydium_amm_v4::RaydiumAmmV4SwapEvent, +}; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; // Global static flag to ensure transaction is executed only once static ALREADY_EXECUTED: AtomicBool = AtomicBool::new(false); diff --git a/examples/raydium_cpmm_trading/Cargo.toml b/examples/raydium_cpmm_trading/Cargo.toml index e372de3..3604b47 100644 --- a/examples/raydium_cpmm_trading/Cargo.toml +++ b/examples/raydium_cpmm_trading/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" -spl-associated-token-account = "7.0.0" +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } tokio = { version = "1", features = ["full"] } diff --git a/examples/raydium_cpmm_trading/src/main.rs b/examples/raydium_cpmm_trading/src/main.rs index cea1581..bac0464 100644 --- a/examples/raydium_cpmm_trading/src/main.rs +++ b/examples/raydium_cpmm_trading/src/main.rs @@ -1,37 +1,27 @@ +use sol_trade_sdk::common::spl_associated_token_account::get_associated_token_address; +use sol_trade_sdk::common::TradeConfig; +use sol_trade_sdk::constants::WSOL_TOKEN_ACCOUNT; +use sol_trade_sdk::trading::core::params::RaydiumCpmmParams; +use sol_trade_sdk::trading::factory::DexType; +use sol_trade_sdk::TradeTokenType; +use sol_trade_sdk::{common::AnyResult, swqos::SwqosConfig, SolanaTrade}; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::signature::Keypair; +use solana_sdk::signer::Signer; +use solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; +use solana_streamer_sdk::streaming::event_parser::common::EventType; +use solana_streamer_sdk::streaming::event_parser::protocols::raydium_cpmm::parser::RAYDIUM_CPMM_PROGRAM_ID; +use solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}; +use solana_streamer_sdk::streaming::yellowstone_grpc::{AccountFilter, TransactionFilter}; +use solana_streamer_sdk::streaming::YellowstoneGrpc; +use solana_streamer_sdk::{ + match_event, streaming::event_parser::protocols::raydium_cpmm::RaydiumCpmmSwapEvent, +}; use std::sync::{ atomic::{AtomicBool, Ordering}, Arc, }; -use sol_trade_sdk::solana_streamer_sdk::{ - match_event, streaming::event_parser::protocols::raydium_cpmm::RaydiumCpmmSwapEvent, -}; -use sol_trade_sdk::{common::AnyResult, swqos::SwqosConfig, SolanaTrade}; -use sol_trade_sdk::{ - common::TradeConfig, - solana_streamer_sdk::streaming::yellowstone_grpc::{AccountFilter, TransactionFilter}, -}; -use sol_trade_sdk::{ - constants::WSOL_TOKEN_ACCOUNT, - solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent}, -}; -use sol_trade_sdk::{ - instruction::utils::raydium_cpmm::accounts, - solana_streamer_sdk::streaming::event_parser::protocols::raydium_cpmm::parser::RAYDIUM_CPMM_PROGRAM_ID, -}; -use sol_trade_sdk::{ - solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter, - trading::factory::DexType, -}; -use sol_trade_sdk::{ - solana_streamer_sdk::streaming::event_parser::common::EventType, - trading::core::params::RaydiumCpmmParams, -}; -use sol_trade_sdk::{solana_streamer_sdk::streaming::YellowstoneGrpc, TradeTokenType}; -use solana_sdk::signer::Signer; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; -use spl_associated_token_account::get_associated_token_address; - // Global static flag to ensure transaction is executed only once static ALREADY_EXECUTED: AtomicBool = AtomicBool::new(false); diff --git a/examples/seed_trading/Cargo.toml b/examples/seed_trading/Cargo.toml index 1fe9a6e..6de3112 100644 --- a/examples/seed_trading/Cargo.toml +++ b/examples/seed_trading/Cargo.toml @@ -5,8 +5,7 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" -spl-associated-token-account = "7.0.0" -tokio = { version = "1", features = ["full"] } -spl-token= "8.0.0" -spl-token-2022 = { version = "8.0.0", features = ["no-entrypoint"] } \ No newline at end of file +solana-streamer-sdk = "0.5.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } +tokio = { version = "1", features = ["full"] } \ No newline at end of file diff --git a/examples/seed_trading/src/main.rs b/examples/seed_trading/src/main.rs index f4f577c..f3eabb5 100644 --- a/examples/seed_trading/src/main.rs +++ b/examples/seed_trading/src/main.rs @@ -6,7 +6,8 @@ use sol_trade_sdk::{ trading::{core::params::PumpSwapParams, factory::DexType}, SolanaTrade, TradeTokenType, }; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::signature::Keypair; use solana_sdk::{pubkey::Pubkey, signer::Signer}; use std::{str::FromStr, sync::Arc}; @@ -50,7 +51,7 @@ async fn main() -> Result<(), Box> { let rpc = client.rpc.clone(); let payer = client.payer.pubkey(); - let program_id = spl_token::ID; + let program_id = sol_trade_sdk::constants::TOKEN_PROGRAM; // ❗️❗️❗️❗️ Must use the 'use seed' method to get the ATA account, otherwise the transaction will fail let account = get_associated_token_address_with_program_id_fast_use_seed( &payer, diff --git a/examples/trading_client/Cargo.toml b/examples/trading_client/Cargo.toml index d8df48e..82d9400 100644 --- a/examples/trading_client/Cargo.toml +++ b/examples/trading_client/Cargo.toml @@ -5,5 +5,6 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } tokio = { version = "1", features = ["full"] } diff --git a/examples/trading_client/src/main.rs b/examples/trading_client/src/main.rs index 46f651f..01747e3 100644 --- a/examples/trading_client/src/main.rs +++ b/examples/trading_client/src/main.rs @@ -3,7 +3,8 @@ use sol_trade_sdk::{ swqos::{SwqosConfig, SwqosRegion}, SolanaTrade, }; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::signature::Keypair; use std::sync::Arc; #[tokio::main] diff --git a/examples/wsol_wrapper/Cargo.toml b/examples/wsol_wrapper/Cargo.toml index b33d376..fd9370f 100644 --- a/examples/wsol_wrapper/Cargo.toml +++ b/examples/wsol_wrapper/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] sol-trade-sdk = { path = "../.." } -solana-sdk = "2.3.0" +solana-sdk = "3.0.0" +solana-commitment-config = { version = "3.0.0", features = ["serde"] } tokio = { version = "1", features = ["full"] } anyhow = "1.0" \ No newline at end of file diff --git a/examples/wsol_wrapper/src/main.rs b/examples/wsol_wrapper/src/main.rs index ea58e60..c7d13ab 100644 --- a/examples/wsol_wrapper/src/main.rs +++ b/examples/wsol_wrapper/src/main.rs @@ -1,5 +1,6 @@ use sol_trade_sdk::{common::TradeConfig, swqos::SwqosConfig, SolanaTrade}; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair}; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::signature::Keypair; use std::sync::Arc; #[tokio::main] diff --git a/src/common/address_lookup_cache.rs b/src/common/address_lookup_cache.rs index 91e8209..fd72478 100755 --- a/src/common/address_lookup_cache.rs +++ b/src/common/address_lookup_cache.rs @@ -1,8 +1,6 @@ use dashmap::DashMap; -use solana_sdk::{ - address_lookup_table::state::AddressLookupTable, message::AddressLookupTableAccount, - pubkey::Pubkey, -}; +use solana_address_lookup_table_interface::state::AddressLookupTable; +use solana_sdk::{message::AddressLookupTableAccount, pubkey::Pubkey}; use std::{ error::Error, sync::{Arc, OnceLock}, diff --git a/src/common/bonding_curve.rs b/src/common/bonding_curve.rs index 657cb86..4e3f056 100755 --- a/src/common/bonding_curve.rs +++ b/src/common/bonding_curve.rs @@ -33,7 +33,7 @@ use crate::instruction::utils::pumpfun::global_constants::{ TOKEN_TOTAL_SUPPLY, }; use crate::instruction::utils::pumpfun::{get_bonding_curve_pda, get_creator_vault_pda}; -use crate::solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; +use solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; /// Represents the global configuration account for token pricing and fees #[derive(Debug, Clone, Serialize, Deserialize, Default)] diff --git a/src/common/fast_fn.rs b/src/common/fast_fn.rs index 94ba969..b2ccb35 100644 --- a/src/common/fast_fn.rs +++ b/src/common/fast_fn.rs @@ -5,11 +5,10 @@ use solana_sdk::{ instruction::{AccountMeta, Instruction}, pubkey::Pubkey, }; -use spl_associated_token_account::{ - get_associated_token_address_with_program_id, ID as ASSOCIATED_TOKEN_PROGRAM_ID, -}; use std::num::NonZeroUsize; +use crate::common::{spl_associated_token_account::get_associated_token_address_with_program_id, spl_token::close_account}; + const MAX_PDA_CACHE_SIZE: usize = 10000; const MAX_ATA_CACHE_SIZE: usize = 10000; const MAX_INSTRUCTION_CACHE_SIZE: usize = 10000; @@ -104,7 +103,7 @@ pub fn _create_associated_token_account_idempotent_fast( if use_seed && !mint.eq(&crate::constants::WSOL_TOKEN_ACCOUNT) && !mint.eq(&crate::constants::SOL_TOKEN_ACCOUNT) - && token_program.eq(&spl_token::ID) + && token_program.eq(&crate::constants::TOKEN_PROGRAM) { // Use cache to get instruction get_cached_instructions(cache_key, || { @@ -120,7 +119,7 @@ pub fn _create_associated_token_account_idempotent_fast( // Create Associated Token Account instruction // Reference implementation of spl_associated_token_account::instruction::create_associated_token_account vec![Instruction { - program_id: ASSOCIATED_TOKEN_PROGRAM_ID, + program_id: crate::constants::ASSOCIATED_TOKEN_PROGRAM_ID, accounts: vec![ AccountMeta::new(*payer, true), // Payer (signer, writable) AccountMeta::new(associated_token_address, false), // ATA address (writable, non-signer) @@ -247,7 +246,7 @@ fn _get_associated_token_address_with_program_id_fast( let ata = if use_seed && !token_mint_address.eq(&crate::constants::WSOL_TOKEN_ACCOUNT) && !token_mint_address.eq(&crate::constants::SOL_TOKEN_ACCOUNT) - && token_program_id.eq(&spl_token::ID) + && token_program_id.eq(&crate::constants::TOKEN_PROGRAM) { super::seed::get_associated_token_address_with_program_id_use_seed( wallet_address, @@ -292,7 +291,7 @@ pub fn fast_init(payer: &Pubkey) { wsol_token_account, }, || { - vec![spl_token::instruction::close_account( + vec![close_account( &crate::constants::TOKEN_PROGRAM, &wsol_token_account, &payer, diff --git a/src/common/mod.rs b/src/common/mod.rs index 24739dc..2918d23 100755 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,12 +1,15 @@ pub mod address_lookup_cache; pub mod bonding_curve; pub mod fast_fn; +pub mod gas_fee_strategy; pub mod global; pub mod nonce_cache; pub mod seed; +pub mod spl_associated_token_account; +pub mod spl_token; +pub mod spl_token_2022; pub mod subscription_handle; pub mod types; -pub mod gas_fee_strategy; +pub use gas_fee_strategy::*; pub use types::*; -pub use gas_fee_strategy::*; \ No newline at end of file diff --git a/src/common/nonce_cache.rs b/src/common/nonce_cache.rs index e7e4299..8826529 100755 --- a/src/common/nonce_cache.rs +++ b/src/common/nonce_cache.rs @@ -1,8 +1,8 @@ use parking_lot::Mutex; use solana_hash::Hash; +use solana_nonce::state::State; +use solana_nonce::versions::Versions; use solana_sdk::account_utils::StateMut; -use solana_sdk::nonce::state::Versions; -use solana_sdk::nonce::State; use solana_sdk::pubkey::Pubkey; use solana_streamer_sdk::common::SolanaRpcClient; use std::str::FromStr; @@ -59,8 +59,8 @@ impl NonceCache { self.update_nonce_info_partial(nonce_account, None, Some(false)); } - /// Get a copy of NonceInfo - pub fn get_nonce_info(&self) -> NonceInfo { + /// Get a copy of NonceInfo + pub fn get_nonce_info(&self) -> NonceInfo { let nonce_info = self.nonce_info.lock(); NonceInfo { nonce_account: nonce_info.nonce_account, @@ -72,15 +72,13 @@ impl NonceCache { pub fn get_durable_nonce_info() -> DurableNonceInfo { let nonce_info = Self::get_instance().get_nonce_info(); let nonce_account = nonce_info.nonce_account; - let current_nonce = if nonce_account.is_some() && nonce_info.current_nonce != Hash::default() { - Some(nonce_info.current_nonce) - } else { - None - }; - DurableNonceInfo { - nonce_account, - current_nonce, - } + let current_nonce = + if nonce_account.is_some() && nonce_info.current_nonce != Hash::default() { + Some(nonce_info.current_nonce) + } else { + None + }; + DurableNonceInfo { nonce_account, current_nonce } } /// Partially update NonceInfo, only update the passed fields diff --git a/src/common/seed.rs b/src/common/seed.rs index be37b64..3c7d8ac 100644 --- a/src/common/seed.rs +++ b/src/common/seed.rs @@ -1,7 +1,7 @@ use crate::common::SolanaRpcClient; use anyhow::anyhow; use fnv::FnvHasher; -use solana_sdk::{instruction::Instruction, program_pack::Pack, pubkey::Pubkey}; +use solana_sdk::{instruction::Instruction, pubkey::Pubkey}; use solana_system_interface::instruction::create_account_with_seed; use std::hash::Hasher; use std::sync::Arc; @@ -34,15 +34,9 @@ pub fn start_rent_updater(client: Arc) { async fn fetch_rent_for_token_account( client: &SolanaRpcClient, - is_2022_token: bool, + _is_2022_token: bool, ) -> Result { - Ok(client - .get_minimum_balance_for_rent_exemption(if is_2022_token { - spl_token_2022::state::Account::LEN as usize - } else { - spl_token::state::Account::LEN as usize - }) - .await?) + Ok(client.get_minimum_balance_for_rent_exemption(165).await?) } pub fn create_associated_token_account_use_seed( @@ -51,7 +45,7 @@ pub fn create_associated_token_account_use_seed( mint: &Pubkey, token_program: &Pubkey, ) -> Result, anyhow::Error> { - let is_2022_token = token_program == &spl_token_2022::id(); + let is_2022_token = token_program == &crate::constants::TOKEN_PROGRAM_2022; let rent = if is_2022_token { unsafe { SPL_TOKEN_2022_RENT } } else { unsafe { SPL_TOKEN_RENT } }; if rent.is_none() { @@ -72,18 +66,14 @@ pub fn create_associated_token_account_use_seed( let seed = unsafe { std::str::from_utf8_unchecked(&buf) }; let ata_like = Pubkey::create_with_seed(payer, seed, token_program)?; - let len = if is_2022_token { - spl_token_2022::state::Account::LEN as u64 - } else { - spl_token::state::Account::LEN as u64 - }; + let len = 165; let create_acc = create_account_with_seed(payer, &ata_like, owner, seed, rent.unwrap(), len, token_program); let init_acc = if is_2022_token { - spl_token_2022::instruction::initialize_account3(&token_program, &ata_like, mint, owner)? + crate::common::spl_token_2022::initialize_account3(&token_program, &ata_like, mint, owner)? } else { - spl_token::instruction::initialize_account3(&token_program, &ata_like, mint, owner)? + crate::common::spl_token::initialize_account3(&token_program, &ata_like, mint, owner)? }; Ok(vec![create_acc, init_acc]) @@ -106,9 +96,13 @@ pub fn get_associated_token_address_with_program_id_use_seed( _ => b'a' + (nibble - 10), }; } - let is_2022_token = token_program_id == &spl_token_2022::id(); + let is_2022_token = token_program_id == &crate::constants::TOKEN_PROGRAM_2022; let seed = unsafe { std::str::from_utf8_unchecked(&buf) }; - let token_program = if is_2022_token { &spl_token_2022::id() } else { &spl_token::id() }; + let token_program = if is_2022_token { + &crate::constants::TOKEN_PROGRAM_2022 + } else { + &crate::constants::TOKEN_PROGRAM + }; let ata_like = Pubkey::create_with_seed(wallet_address, seed, token_program)?; Ok(ata_like) } diff --git a/src/common/spl_associated_token_account.rs b/src/common/spl_associated_token_account.rs new file mode 100644 index 0000000..f1e6ce7 --- /dev/null +++ b/src/common/spl_associated_token_account.rs @@ -0,0 +1,55 @@ +use solana_sdk::{ + message::{AccountMeta, Instruction}, + pubkey::Pubkey, +}; + +use crate::constants::{ASSOCIATED_TOKEN_PROGRAM_ID, SYSTEM_PROGRAM}; + +pub fn get_associated_token_address_with_program_id( + wallet_address: &Pubkey, + token_mint_address: &Pubkey, + token_program_id: &Pubkey, +) -> Pubkey { + Pubkey::find_program_address( + &[&wallet_address.to_bytes(), &token_program_id.to_bytes(), &token_mint_address.to_bytes()], + &crate::constants::ASSOCIATED_TOKEN_PROGRAM_ID, + ) + .0 +} + +pub fn get_associated_token_address( + wallet_address: &Pubkey, + token_mint_address: &Pubkey, +) -> Pubkey { + get_associated_token_address_with_program_id( + wallet_address, + token_mint_address, + &crate::constants::TOKEN_PROGRAM, + ) +} + +pub fn create_associated_token_account_idempotent( + funding_address: &Pubkey, + wallet_address: &Pubkey, + token_mint_address: &Pubkey, + token_program_id: &Pubkey, +) -> Instruction { + let instruction = 1; + let associated_account_address = get_associated_token_address_with_program_id( + wallet_address, + token_mint_address, + token_program_id, + ); + Instruction { + program_id: ASSOCIATED_TOKEN_PROGRAM_ID, + accounts: vec![ + AccountMeta::new(*funding_address, true), + AccountMeta::new(associated_account_address, false), + AccountMeta::new_readonly(*wallet_address, false), + AccountMeta::new_readonly(*token_mint_address, false), + AccountMeta::new_readonly(SYSTEM_PROGRAM, false), + AccountMeta::new_readonly(*token_program_id, false), + ], + data: vec![instruction], + } +} diff --git a/src/common/spl_token.rs b/src/common/spl_token.rs new file mode 100644 index 0000000..823dbe6 --- /dev/null +++ b/src/common/spl_token.rs @@ -0,0 +1,48 @@ +use solana_program::pubkey; +use solana_sdk::{ + message::{AccountMeta, Instruction}, + program_error::ProgramError, + pubkey::Pubkey, +}; + +pub const ID: Pubkey = pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); + +pub fn close_account( + token_program_id: &Pubkey, + account_pubkey: &Pubkey, + destination_pubkey: &Pubkey, + owner_pubkey: &Pubkey, + signer_pubkeys: &[&Pubkey], +) -> Result { + // CloseAccount + let mut data = Vec::with_capacity(1); + data.push(9); + let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len()); + accounts.push(solana_sdk::message::AccountMeta::new(*account_pubkey, false)); + accounts.push(solana_sdk::message::AccountMeta::new(*destination_pubkey, false)); + accounts.push(solana_sdk::message::AccountMeta::new_readonly( + *owner_pubkey, + signer_pubkeys.is_empty(), + )); + for signer_pubkey in signer_pubkeys.iter() { + accounts.push(solana_sdk::message::AccountMeta::new_readonly(**signer_pubkey, true)); + } + Ok(Instruction { program_id: *token_program_id, accounts, data }) +} + +pub fn initialize_account3( + token_program_id: &Pubkey, + account_pubkey: &Pubkey, + mint_pubkey: &Pubkey, + owner_pubkey: &Pubkey, +) -> Result { + // InitializeAccount3 + let mut data = Vec::with_capacity(33); + data.push(18); + data.extend_from_slice(owner_pubkey.as_ref()); + let accounts = vec![ + AccountMeta::new(*account_pubkey, false), + AccountMeta::new_readonly(*mint_pubkey, false), + ]; + Ok(Instruction { program_id: *token_program_id, accounts, data }) +} diff --git a/src/common/spl_token_2022.rs b/src/common/spl_token_2022.rs new file mode 100644 index 0000000..d19230f --- /dev/null +++ b/src/common/spl_token_2022.rs @@ -0,0 +1,25 @@ +use solana_program::pubkey; +use solana_sdk::{ + message::{AccountMeta, Instruction}, + program_error::ProgramError, + pubkey::Pubkey, +}; + +pub const ID: Pubkey = pubkey!("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"); + +pub fn initialize_account3( + token_program_id: &Pubkey, + account_pubkey: &Pubkey, + mint_pubkey: &Pubkey, + owner_pubkey: &Pubkey, +) -> Result { + // InitializeAccount3 + let mut data = Vec::with_capacity(33); + data.push(18); + data.extend_from_slice(owner_pubkey.as_ref()); + let accounts = vec![ + AccountMeta::new(*account_pubkey, false), + AccountMeta::new_readonly(*mint_pubkey, false), + ]; + Ok(Instruction { program_id: *token_program_id, accounts, data }) +} diff --git a/src/common/types.rs b/src/common/types.rs index 5c692f9..d36dea2 100755 --- a/src/common/types.rs +++ b/src/common/types.rs @@ -1,5 +1,5 @@ use crate::swqos::SwqosConfig; -use solana_sdk::commitment_config::CommitmentConfig; +use solana_commitment_config::CommitmentConfig; #[derive(Debug, Clone)] pub struct TradeConfig { diff --git a/src/constants/accounts.rs b/src/constants/accounts.rs index 0e11b83..3a7e879 100644 --- a/src/constants/accounts.rs +++ b/src/constants/accounts.rs @@ -1,6 +1,6 @@ use solana_sdk::{pubkey, pubkey::Pubkey}; -pub const SYSTEM_PROGRAM: Pubkey = solana_sdk::system_program::ID; +pub const SYSTEM_PROGRAM: Pubkey = pubkey!("11111111111111111111111111111111"); pub const SYSTEM_PROGRAM_META: solana_sdk::instruction::AccountMeta = solana_sdk::instruction::AccountMeta { pubkey: SYSTEM_PROGRAM, @@ -8,7 +8,7 @@ pub const SYSTEM_PROGRAM_META: solana_sdk::instruction::AccountMeta = is_writable: false, }; -pub const TOKEN_PROGRAM: Pubkey = spl_token::ID; +pub const TOKEN_PROGRAM: Pubkey = pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); pub const TOKEN_PROGRAM_META: solana_sdk::instruction::AccountMeta = solana_sdk::instruction::AccountMeta { pubkey: TOKEN_PROGRAM, @@ -16,7 +16,7 @@ pub const TOKEN_PROGRAM_META: solana_sdk::instruction::AccountMeta = is_writable: false, }; -pub const TOKEN_PROGRAM_2022: Pubkey = spl_token_2022::ID; +pub const TOKEN_PROGRAM_2022: Pubkey = pubkey!("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"); pub const TOKEN_PROGRAM_2022_META: solana_sdk::instruction::AccountMeta = solana_sdk::instruction::AccountMeta { pubkey: TOKEN_PROGRAM_2022, @@ -45,3 +45,6 @@ pub const USD1_TOKEN_ACCOUNT_META: solana_sdk::instruction::AccountMeta = pub const RENT: Pubkey = solana_sdk::sysvar::rent::id(); pub const RENT_META: solana_sdk::instruction::AccountMeta = solana_sdk::instruction::AccountMeta { pubkey: RENT, is_signer: false, is_writable: false }; + +pub const ASSOCIATED_TOKEN_PROGRAM_ID: Pubkey = + pubkey!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"); diff --git a/src/instruction/pumpfun.rs b/src/instruction/pumpfun.rs index 66e8640..0dfd3f2 100755 --- a/src/instruction/pumpfun.rs +++ b/src/instruction/pumpfun.rs @@ -1,9 +1,8 @@ use crate::{ - constants::trade::trade::DEFAULT_SLIPPAGE, - trading::core::{ + common::spl_token::close_account, constants::trade::trade::DEFAULT_SLIPPAGE, trading::core::{ params::{PumpFunParams, SwapParams}, traits::InstructionBuilder, - }, + } }; use crate::{ instruction::utils::pumpfun::{ @@ -18,7 +17,6 @@ use crate::{ use anyhow::{anyhow, Result}; use solana_sdk::instruction::AccountMeta; use solana_sdk::{instruction::Instruction, pubkey::Pubkey, signer::Signer}; -use spl_token::instruction::close_account; /// Instruction builder for PumpFun protocol pub struct PumpFunInstructionBuilder; diff --git a/src/instruction/utils/pumpfun.rs b/src/instruction/utils/pumpfun.rs index 4716be1..71e8448 100644 --- a/src/instruction/utils/pumpfun.rs +++ b/src/instruction/utils/pumpfun.rs @@ -1,7 +1,7 @@ use crate::common::{global::GlobalAccount, SolanaRpcClient}; -use crate::solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; use anyhow::anyhow; use solana_sdk::pubkey::Pubkey; +use solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; use std::{collections::HashMap, sync::Arc}; use tokio::sync::RwLock; @@ -216,7 +216,13 @@ pub fn get_user_volume_accumulator_pda(user: &Pubkey) -> Option { pub async fn fetch_bonding_curve_account( rpc: &SolanaRpcClient, mint: &Pubkey, -) -> Result<(Arc, Pubkey), anyhow::Error>{ +) -> Result< + ( + Arc, + Pubkey, + ), + anyhow::Error, +> { let bonding_curve_pda: Pubkey = get_bonding_curve_pda(mint).ok_or(anyhow!("Bonding curve not found"))?; @@ -225,8 +231,10 @@ pub async fn fetch_bonding_curve_account( return Err(anyhow!("Bonding curve not found")); } - let bonding_curve = solana_sdk::borsh1::try_from_slice_unchecked::(&account.data[8..]) - .map_err(|e| anyhow::anyhow!("Failed to deserialize bonding curve account: {}", e))?; + let bonding_curve = solana_sdk::borsh1::try_from_slice_unchecked::< + solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::types::BondingCurve, + >(&account.data[8..]) + .map_err(|e| anyhow::anyhow!("Failed to deserialize bonding curve account: {}", e))?; Ok((Arc::new(bonding_curve), bonding_curve_pda)) } diff --git a/src/instruction/utils/pumpswap.rs b/src/instruction/utils/pumpswap.rs index 8e00e3f..a262855 100644 --- a/src/instruction/utils/pumpswap.rs +++ b/src/instruction/utils/pumpswap.rs @@ -1,4 +1,9 @@ -use crate::{common::SolanaRpcClient, constants::TOKEN_PROGRAM}; +use crate::{ + common::{ + spl_associated_token_account::get_associated_token_address_with_program_id, SolanaRpcClient, + }, + constants::TOKEN_PROGRAM, +}; use anyhow::anyhow; use solana_account_decoder::UiAccountEncoding; use solana_sdk::pubkey::Pubkey; @@ -138,12 +143,11 @@ pub(crate) fn coin_creator_vault_authority(coin_creator: Pubkey) -> Pubkey { pub(crate) fn coin_creator_vault_ata(coin_creator: Pubkey, quote_mint: Pubkey) -> Pubkey { let creator_vault_authority = coin_creator_vault_authority(coin_creator); - let associated_token_creator_vault_authority = - spl_associated_token_account::get_associated_token_address_with_program_id( - &creator_vault_authority, - "e_mint, - &TOKEN_PROGRAM, - ); + let associated_token_creator_vault_authority = get_associated_token_address_with_program_id( + &creator_vault_authority, + "e_mint, + &TOKEN_PROGRAM, + ); associated_token_creator_vault_authority } diff --git a/src/lib.rs b/src/lib.rs index 18b0c8e..d790339 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ pub mod common; pub mod constants; pub mod instruction; -pub mod protos; pub mod swqos; pub mod trading; pub mod utils; @@ -30,7 +29,6 @@ use rustls::crypto::{ring::default_provider, CryptoProvider}; use solana_sdk::hash::Hash; use solana_sdk::signer::Signer; use solana_sdk::{pubkey::Pubkey, signature::Keypair, signature::Signature}; -pub use solana_streamer_sdk; use std::sync::Arc; /// Type of the token to buy diff --git a/src/protos/auth.rs b/src/protos/auth.rs deleted file mode 100755 index 127047c..0000000 --- a/src/protos/auth.rs +++ /dev/null @@ -1,260 +0,0 @@ -// This file is @generated by prost-build. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GenerateAuthChallengeRequest { - /// / Role the client is attempting to generate tokens for. - #[prost(enumeration = "Role", tag = "1")] - pub role: i32, - /// / Client's 32 byte pubkey. - #[prost(bytes = "vec", tag = "2")] - pub pubkey: ::prost::alloc::vec::Vec, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GenerateAuthChallengeResponse { - #[prost(string, tag = "1")] - pub challenge: ::prost::alloc::string::String, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GenerateAuthTokensRequest { - /// / The pre-signed challenge. - #[prost(string, tag = "1")] - pub challenge: ::prost::alloc::string::String, - /// / The signing keypair's corresponding 32 byte pubkey. - #[prost(bytes = "vec", tag = "2")] - pub client_pubkey: ::prost::alloc::vec::Vec, - /// / The 64 byte signature of the challenge signed by the client's private key. The private key must correspond to - /// the pubkey passed in the \[GenerateAuthChallenge\] method. The client is expected to sign the challenge token - /// prepended with their pubkey. For example sign(pubkey, challenge). - #[prost(bytes = "vec", tag = "3")] - pub signed_challenge: ::prost::alloc::vec::Vec, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Token { - /// / The token. - #[prost(string, tag = "1")] - pub value: ::prost::alloc::string::String, - /// / When the token will expire. - #[prost(message, optional, tag = "2")] - pub expires_at_utc: ::core::option::Option<::prost_types::Timestamp>, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GenerateAuthTokensResponse { - /// / The token granting access to resources. - #[prost(message, optional, tag = "1")] - pub access_token: ::core::option::Option, - /// / The token used to refresh the access_token. This has a longer TTL than the access_token. - #[prost(message, optional, tag = "2")] - pub refresh_token: ::core::option::Option, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RefreshAccessTokenRequest { - /// / Non-expired refresh token obtained from the \[GenerateAuthTokens\] method. - #[prost(string, tag = "1")] - pub refresh_token: ::prost::alloc::string::String, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RefreshAccessTokenResponse { - /// / Fresh access_token. - #[prost(message, optional, tag = "1")] - pub access_token: ::core::option::Option, -} -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum Role { - Relayer = 0, - Searcher = 1, - Validator = 2, - ShredstreamSubscriber = 3, -} -impl Role { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Self::Relayer => "RELAYER", - Self::Searcher => "SEARCHER", - Self::Validator => "VALIDATOR", - Self::ShredstreamSubscriber => "SHREDSTREAM_SUBSCRIBER", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "RELAYER" => Some(Self::Relayer), - "SEARCHER" => Some(Self::Searcher), - "VALIDATOR" => Some(Self::Validator), - "SHREDSTREAM_SUBSCRIBER" => Some(Self::ShredstreamSubscriber), - _ => None, - } - } -} -/// Generated client implementations. -pub mod auth_service_client { - #![allow( - unused_variables, - dead_code, - missing_docs, - clippy::wildcard_imports, - clippy::let_unit_value, - )] - use tonic::codegen::*; - use tonic::codegen::http::Uri; - /// / This service is responsible for issuing auth tokens to clients for API access. - #[derive(Debug, Clone)] - pub struct AuthServiceClient { - inner: tonic::client::Grpc, - } - impl AuthServiceClient { - /// Attempt to create a new client by connecting to a given endpoint. - pub async fn connect(dst: D) -> Result - where - D: TryInto, - D::Error: Into, - { - let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; - Ok(Self::new(conn)) - } - } - impl AuthServiceClient - where - T: tonic::client::GrpcService, - T::Error: Into, - T::ResponseBody: Body + std::marker::Send + 'static, - ::Error: Into + std::marker::Send, - { - pub fn new(inner: T) -> Self { - let inner = tonic::client::Grpc::new(inner); - Self { inner } - } - pub fn with_origin(inner: T, origin: Uri) -> Self { - let inner = tonic::client::Grpc::with_origin(inner, origin); - Self { inner } - } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> AuthServiceClient> - where - F: tonic::service::Interceptor, - T::ResponseBody: Default, - T: tonic::codegen::Service< - http::Request, - Response = http::Response< - >::ResponseBody, - >, - >, - , - >>::Error: Into + std::marker::Send + std::marker::Sync, - { - AuthServiceClient::new(InterceptedService::new(inner, interceptor)) - } - /// Compress requests with the given encoding. - /// - /// This requires the server to support it otherwise it might respond with an - /// error. - #[must_use] - pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.send_compressed(encoding); - self - } - /// Enable decompressing responses. - #[must_use] - pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.accept_compressed(encoding); - self - } - /// Limits the maximum size of a decoded message. - /// - /// Default: `4MB` - #[must_use] - pub fn max_decoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_decoding_message_size(limit); - self - } - /// Limits the maximum size of an encoded message. - /// - /// Default: `usize::MAX` - #[must_use] - pub fn max_encoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_encoding_message_size(limit); - self - } - /// / Returns a challenge, client is expected to sign this challenge with an appropriate keypair in order to obtain access tokens. - pub async fn generate_auth_challenge( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/auth.AuthService/GenerateAuthChallenge", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("auth.AuthService", "GenerateAuthChallenge")); - self.inner.unary(req, path, codec).await - } - /// / Provides the client with the initial pair of auth tokens for API access. - pub async fn generate_auth_tokens( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/auth.AuthService/GenerateAuthTokens", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("auth.AuthService", "GenerateAuthTokens")); - self.inner.unary(req, path, codec).await - } - /// / Call this method with a non-expired refresh token to obtain a new access token. - pub async fn refresh_access_token( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/auth.AuthService/RefreshAccessToken", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("auth.AuthService", "RefreshAccessToken")); - self.inner.unary(req, path, codec).await - } - } -} diff --git a/src/protos/block.rs b/src/protos/block.rs deleted file mode 100755 index 0fc0434..0000000 --- a/src/protos/block.rs +++ /dev/null @@ -1,19 +0,0 @@ -// This file is @generated by prost-build. -/// Condensed block helpful for getting data around efficiently internal to our system. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct CondensedBlock { - #[prost(message, optional, tag = "1")] - pub header: ::core::option::Option, - #[prost(string, tag = "2")] - pub previous_blockhash: ::prost::alloc::string::String, - #[prost(string, tag = "3")] - pub blockhash: ::prost::alloc::string::String, - #[prost(uint64, tag = "4")] - pub parent_slot: u64, - #[prost(bytes = "vec", repeated, tag = "5")] - pub versioned_transactions: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, - #[prost(uint64, tag = "6")] - pub slot: u64, - #[prost(string, tag = "7")] - pub commitment: ::prost::alloc::string::String, -} diff --git a/src/protos/block_engine.rs b/src/protos/block_engine.rs deleted file mode 100755 index 69c22eb..0000000 --- a/src/protos/block_engine.rs +++ /dev/null @@ -1,462 +0,0 @@ -// This file is @generated by prost-build. -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct SubscribePacketsRequest {} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SubscribePacketsResponse { - #[prost(message, optional, tag = "1")] - pub header: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub batch: ::core::option::Option, -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct SubscribeBundlesRequest {} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SubscribeBundlesResponse { - #[prost(message, repeated, tag = "1")] - pub bundles: ::prost::alloc::vec::Vec, -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct BlockBuilderFeeInfoRequest {} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BlockBuilderFeeInfoResponse { - #[prost(string, tag = "1")] - pub pubkey: ::prost::alloc::string::String, - /// commission (0-100) - #[prost(uint64, tag = "2")] - pub commission: u64, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct AccountsOfInterest { - /// use * for all accounts - #[prost(string, repeated, tag = "1")] - pub accounts: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct AccountsOfInterestRequest {} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct AccountsOfInterestUpdate { - #[prost(string, repeated, tag = "1")] - pub accounts: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct ProgramsOfInterestRequest {} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ProgramsOfInterestUpdate { - #[prost(string, repeated, tag = "1")] - pub programs: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, -} -/// A series of packets with an expiration attached to them. -/// The header contains a timestamp for when this packet was generated. -/// The expiry is how long the packet batches have before they expire and are forwarded to the validator. -/// This provides a more censorship resistant method to MEV than block engines receiving packets directly. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ExpiringPacketBatch { - #[prost(message, optional, tag = "1")] - pub header: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub batch: ::core::option::Option, - #[prost(uint32, tag = "3")] - pub expiry_ms: u32, -} -/// Packets and heartbeats are sent over the same stream. -/// ExpiringPacketBatches have an expiration attached to them so the block engine can track -/// how long it has until the relayer forwards the packets to the validator. -/// Heartbeats contain a timestamp from the system and is used as a simple and naive time-sync mechanism -/// so the block engine has some idea on how far their clocks are apart. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PacketBatchUpdate { - #[prost(oneof = "packet_batch_update::Msg", tags = "1, 2")] - pub msg: ::core::option::Option, -} -/// Nested message and enum types in `PacketBatchUpdate`. -pub mod packet_batch_update { - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Msg { - #[prost(message, tag = "1")] - Batches(super::ExpiringPacketBatch), - #[prost(message, tag = "2")] - Heartbeat(super::super::shared::Heartbeat), - } -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct StartExpiringPacketStreamResponse { - #[prost(message, optional, tag = "1")] - pub heartbeat: ::core::option::Option, -} -/// Generated client implementations. -pub mod block_engine_validator_client { - #![allow( - unused_variables, - dead_code, - missing_docs, - clippy::wildcard_imports, - clippy::let_unit_value, - )] - use tonic::codegen::*; - use tonic::codegen::http::Uri; - /// / Validators can connect to Block Engines to receive packets and bundles. - #[derive(Debug, Clone)] - pub struct BlockEngineValidatorClient { - inner: tonic::client::Grpc, - } - impl BlockEngineValidatorClient { - /// Attempt to create a new client by connecting to a given endpoint. - pub async fn connect(dst: D) -> Result - where - D: TryInto, - D::Error: Into, - { - let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; - Ok(Self::new(conn)) - } - } - impl BlockEngineValidatorClient - where - T: tonic::client::GrpcService, - T::Error: Into, - T::ResponseBody: Body + std::marker::Send + 'static, - ::Error: Into + std::marker::Send, - { - pub fn new(inner: T) -> Self { - let inner = tonic::client::Grpc::new(inner); - Self { inner } - } - pub fn with_origin(inner: T, origin: Uri) -> Self { - let inner = tonic::client::Grpc::with_origin(inner, origin); - Self { inner } - } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> BlockEngineValidatorClient> - where - F: tonic::service::Interceptor, - T::ResponseBody: Default, - T: tonic::codegen::Service< - http::Request, - Response = http::Response< - >::ResponseBody, - >, - >, - , - >>::Error: Into + std::marker::Send + std::marker::Sync, - { - BlockEngineValidatorClient::new(InterceptedService::new(inner, interceptor)) - } - /// Compress requests with the given encoding. - /// - /// This requires the server to support it otherwise it might respond with an - /// error. - #[must_use] - pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.send_compressed(encoding); - self - } - /// Enable decompressing responses. - #[must_use] - pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.accept_compressed(encoding); - self - } - /// Limits the maximum size of a decoded message. - /// - /// Default: `4MB` - #[must_use] - pub fn max_decoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_decoding_message_size(limit); - self - } - /// Limits the maximum size of an encoded message. - /// - /// Default: `usize::MAX` - #[must_use] - pub fn max_encoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_encoding_message_size(limit); - self - } - /// / Validators can subscribe to the block engine to receive a stream of packets - pub async fn subscribe_packets( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response>, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/block_engine.BlockEngineValidator/SubscribePackets", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "block_engine.BlockEngineValidator", - "SubscribePackets", - ), - ); - self.inner.server_streaming(req, path, codec).await - } - /// / Validators can subscribe to the block engine to receive a stream of simulated and profitable bundles - pub async fn subscribe_bundles( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response>, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/block_engine.BlockEngineValidator/SubscribeBundles", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "block_engine.BlockEngineValidator", - "SubscribeBundles", - ), - ); - self.inner.server_streaming(req, path, codec).await - } - /// Block builders can optionally collect fees. This returns fee information if a block builder wants to - /// collect one. - pub async fn get_block_builder_fee_info( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/block_engine.BlockEngineValidator/GetBlockBuilderFeeInfo", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "block_engine.BlockEngineValidator", - "GetBlockBuilderFeeInfo", - ), - ); - self.inner.unary(req, path, codec).await - } - } -} -/// Generated client implementations. -pub mod block_engine_relayer_client { - #![allow( - unused_variables, - dead_code, - missing_docs, - clippy::wildcard_imports, - clippy::let_unit_value, - )] - use tonic::codegen::*; - use tonic::codegen::http::Uri; - /// / Relayers can forward packets to Block Engines. - /// / Block Engines provide an AccountsOfInterest field to only send transactions that are of interest. - #[derive(Debug, Clone)] - pub struct BlockEngineRelayerClient { - inner: tonic::client::Grpc, - } - impl BlockEngineRelayerClient { - /// Attempt to create a new client by connecting to a given endpoint. - pub async fn connect(dst: D) -> Result - where - D: TryInto, - D::Error: Into, - { - let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; - Ok(Self::new(conn)) - } - } - impl BlockEngineRelayerClient - where - T: tonic::client::GrpcService, - T::Error: Into, - T::ResponseBody: Body + std::marker::Send + 'static, - ::Error: Into + std::marker::Send, - { - pub fn new(inner: T) -> Self { - let inner = tonic::client::Grpc::new(inner); - Self { inner } - } - pub fn with_origin(inner: T, origin: Uri) -> Self { - let inner = tonic::client::Grpc::with_origin(inner, origin); - Self { inner } - } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> BlockEngineRelayerClient> - where - F: tonic::service::Interceptor, - T::ResponseBody: Default, - T: tonic::codegen::Service< - http::Request, - Response = http::Response< - >::ResponseBody, - >, - >, - , - >>::Error: Into + std::marker::Send + std::marker::Sync, - { - BlockEngineRelayerClient::new(InterceptedService::new(inner, interceptor)) - } - /// Compress requests with the given encoding. - /// - /// This requires the server to support it otherwise it might respond with an - /// error. - #[must_use] - pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.send_compressed(encoding); - self - } - /// Enable decompressing responses. - #[must_use] - pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.accept_compressed(encoding); - self - } - /// Limits the maximum size of a decoded message. - /// - /// Default: `4MB` - #[must_use] - pub fn max_decoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_decoding_message_size(limit); - self - } - /// Limits the maximum size of an encoded message. - /// - /// Default: `usize::MAX` - #[must_use] - pub fn max_encoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_encoding_message_size(limit); - self - } - /// / The block engine feeds accounts of interest (AOI) updates to the relayer periodically. - /// / For all transactions the relayer receives, it forwards transactions to the block engine which write-lock - /// / any of the accounts in the AOI. - pub async fn subscribe_accounts_of_interest( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response>, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/block_engine.BlockEngineRelayer/SubscribeAccountsOfInterest", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "block_engine.BlockEngineRelayer", - "SubscribeAccountsOfInterest", - ), - ); - self.inner.server_streaming(req, path, codec).await - } - pub async fn subscribe_programs_of_interest( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response>, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/block_engine.BlockEngineRelayer/SubscribeProgramsOfInterest", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "block_engine.BlockEngineRelayer", - "SubscribeProgramsOfInterest", - ), - ); - self.inner.server_streaming(req, path, codec).await - } - /// Validators can subscribe to packets from the relayer and receive a multiplexed signal that contains a mixture - /// of packets and heartbeats. - /// NOTE: This is a bi-directional stream due to a bug with how Envoy handles half closed client-side streams. - /// The issue is being tracked here: https://github.com/envoyproxy/envoy/issues/22748. In the meantime, the - /// server will stream heartbeats to clients at some reasonable cadence. - pub async fn start_expiring_packet_stream( - &mut self, - request: impl tonic::IntoStreamingRequest, - ) -> std::result::Result< - tonic::Response< - tonic::codec::Streaming, - >, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/block_engine.BlockEngineRelayer/StartExpiringPacketStream", - ); - let mut req = request.into_streaming_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "block_engine.BlockEngineRelayer", - "StartExpiringPacketStream", - ), - ); - self.inner.streaming(req, path, codec).await - } - } -} diff --git a/src/protos/bundle.rs b/src/protos/bundle.rs deleted file mode 100755 index 5409c92..0000000 --- a/src/protos/bundle.rs +++ /dev/null @@ -1,171 +0,0 @@ -// This file is @generated by prost-build. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Bundle { - #[prost(message, optional, tag = "2")] - pub header: ::core::option::Option, - #[prost(message, repeated, tag = "3")] - pub packets: ::prost::alloc::vec::Vec, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BundleUuid { - #[prost(message, optional, tag = "1")] - pub bundle: ::core::option::Option, - #[prost(string, tag = "2")] - pub uuid: ::prost::alloc::string::String, -} -/// Indicates the bundle was accepted and forwarded to a validator. -/// NOTE: A single bundle may have multiple events emitted if forwarded to many validators. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Accepted { - /// Slot at which bundle was forwarded. - #[prost(uint64, tag = "1")] - pub slot: u64, - /// Validator identity bundle was forwarded to. - #[prost(string, tag = "2")] - pub validator_identity: ::prost::alloc::string::String, -} -/// Indicates the bundle was dropped and therefore not forwarded to any validator. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Rejected { - #[prost(oneof = "rejected::Reason", tags = "1, 2, 3, 4, 5")] - pub reason: ::core::option::Option, -} -/// Nested message and enum types in `Rejected`. -pub mod rejected { - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Reason { - #[prost(message, tag = "1")] - StateAuctionBidRejected(super::StateAuctionBidRejected), - #[prost(message, tag = "2")] - WinningBatchBidRejected(super::WinningBatchBidRejected), - #[prost(message, tag = "3")] - SimulationFailure(super::SimulationFailure), - #[prost(message, tag = "4")] - InternalError(super::InternalError), - #[prost(message, tag = "5")] - DroppedBundle(super::DroppedBundle), - } -} -/// Indicates the bundle's bid was high enough to win its state auction. -/// However, not high enough relative to other state auction winners and therefore excluded from being forwarded. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct WinningBatchBidRejected { - /// Auction's unique identifier. - #[prost(string, tag = "1")] - pub auction_id: ::prost::alloc::string::String, - /// Bundle's simulated bid. - #[prost(uint64, tag = "2")] - pub simulated_bid_lamports: u64, - #[prost(string, optional, tag = "3")] - pub msg: ::core::option::Option<::prost::alloc::string::String>, -} -/// Indicates the bundle's bid was __not__ high enough to be included in its state auction's set of winners. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct StateAuctionBidRejected { - /// Auction's unique identifier. - #[prost(string, tag = "1")] - pub auction_id: ::prost::alloc::string::String, - /// Bundle's simulated bid. - #[prost(uint64, tag = "2")] - pub simulated_bid_lamports: u64, - #[prost(string, optional, tag = "3")] - pub msg: ::core::option::Option<::prost::alloc::string::String>, -} -/// Bundle dropped due to simulation failure. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SimulationFailure { - /// Signature of the offending transaction. - #[prost(string, tag = "1")] - pub tx_signature: ::prost::alloc::string::String, - #[prost(string, optional, tag = "2")] - pub msg: ::core::option::Option<::prost::alloc::string::String>, -} -/// Bundle dropped due to an internal error. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct InternalError { - #[prost(string, tag = "1")] - pub msg: ::prost::alloc::string::String, -} -/// Bundle dropped (e.g. because no leader upcoming) -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct DroppedBundle { - #[prost(string, tag = "1")] - pub msg: ::prost::alloc::string::String, -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct Finalized {} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Processed { - #[prost(string, tag = "1")] - pub validator_identity: ::prost::alloc::string::String, - #[prost(uint64, tag = "2")] - pub slot: u64, - /// / Index within the block. - #[prost(uint64, tag = "3")] - pub bundle_index: u64, -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct Dropped { - #[prost(enumeration = "DroppedReason", tag = "1")] - pub reason: i32, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BundleResult { - /// Bundle's Uuid. - #[prost(string, tag = "1")] - pub bundle_id: ::prost::alloc::string::String, - #[prost(oneof = "bundle_result::Result", tags = "2, 3, 4, 5, 6")] - pub result: ::core::option::Option, -} -/// Nested message and enum types in `BundleResult`. -pub mod bundle_result { - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Result { - /// Indicated accepted by the block-engine and forwarded to a jito-solana validator. - #[prost(message, tag = "2")] - Accepted(super::Accepted), - /// Rejected by the block-engine. - #[prost(message, tag = "3")] - Rejected(super::Rejected), - /// Reached finalized commitment level. - #[prost(message, tag = "4")] - Finalized(super::Finalized), - /// Reached a processed commitment level. - #[prost(message, tag = "5")] - Processed(super::Processed), - /// Was accepted and forwarded by the block-engine but never landed on-chain. - #[prost(message, tag = "6")] - Dropped(super::Dropped), - } -} -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum DroppedReason { - BlockhashExpired = 0, - /// One or more transactions in the bundle landed on-chain, invalidating the bundle. - PartiallyProcessed = 1, - /// This indicates bundle was processed but not finalized. This could occur during forks. - NotFinalized = 2, -} -impl DroppedReason { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Self::BlockhashExpired => "BlockhashExpired", - Self::PartiallyProcessed => "PartiallyProcessed", - Self::NotFinalized => "NotFinalized", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "BlockhashExpired" => Some(Self::BlockhashExpired), - "PartiallyProcessed" => Some(Self::PartiallyProcessed), - "NotFinalized" => Some(Self::NotFinalized), - _ => None, - } - } -} diff --git a/src/protos/convert.rs b/src/protos/convert.rs deleted file mode 100755 index e975ee6..0000000 --- a/src/protos/convert.rs +++ /dev/null @@ -1,158 +0,0 @@ -use std::{ - cmp::min, - net::{AddrParseError, IpAddr, Ipv4Addr, SocketAddr}, - str::FromStr, -}; - -use bincode::serialize; -use solana_perf::packet::{Packet, PacketBatch, PACKET_DATA_SIZE}; -use solana_sdk::{ - packet::{Meta, PacketFlags}, - transaction::VersionedTransaction, -}; - -use crate::protos::{ - packet::{ - Meta as ProtoMeta, Packet as ProtoPacket, PacketBatch as ProtoPacketBatch, - PacketFlags as ProtoPacketFlags, - }, - shared::Socket, -}; - -/// Converts a Solana packet to a protobuf packet -/// NOTE: the packet.data() function will filter packets marked for discard -pub fn packet_to_proto_packet(p: &solana_perf::packet::PacketRef<'_>) -> Option { - Some(ProtoPacket { - data: p.data(..)?.to_vec(), - meta: Some(ProtoMeta { - size: p.meta().size as u64, - addr: p.meta().addr.to_string(), - port: p.meta().port as u32, - flags: Some(ProtoPacketFlags { - discard: p.meta().discard(), - forwarded: p.meta().forwarded(), - repair: p.meta().repair(), - simple_vote_tx: p.meta().is_simple_vote_tx(), - tracer_packet: p.meta().is_perf_track_packet(), - from_staked_node: p.meta().is_from_staked_node(), - }), - sender_stake: 0, - }), - }) -} - -pub fn packet_batches_to_proto_packets( - batches: &[PacketBatch], -) -> impl Iterator + '_ { - batches - .iter() - .flat_map(|b| b.iter().filter_map(|p| packet_to_proto_packet(&p))) - } - -/// converts from a protobuf packet to packet -pub fn proto_packet_to_packet(p: &ProtoPacket) -> Packet { - let mut data = [0u8; PACKET_DATA_SIZE]; - let copy_len = min(data.len(), p.data.len()); - data[..copy_len].copy_from_slice(&p.data[..copy_len]); - let mut packet = Packet::new(data, Meta::default()); - if let Some(meta) = &p.meta { - packet.meta_mut().size = meta.size as usize; - packet.meta_mut().addr = meta - .addr - .parse() - .unwrap_or(IpAddr::V4(Ipv4Addr::UNSPECIFIED)); - packet.meta_mut().port = meta.port as u16; - if let Some(flags) = &meta.flags { - if flags.simple_vote_tx { - packet.meta_mut().flags.insert(PacketFlags::SIMPLE_VOTE_TX); - } - if flags.forwarded { - packet.meta_mut().flags.insert(PacketFlags::FORWARDED); - } - if flags.tracer_packet { - packet.meta_mut().flags.insert(PacketFlags::PERF_TRACK_PACKET); - } - if flags.repair { - packet.meta_mut().flags.insert(PacketFlags::REPAIR); - } - if flags.discard { - packet.meta_mut().flags.insert(PacketFlags::DISCARD); - } - } - } - packet -} - -pub fn proto_packet_batch_to_packets( - packet_batch: ProtoPacketBatch, -) -> impl Iterator { - packet_batch - .packets - .into_iter() - .map(|proto_packet| proto_packet_to_packet(&proto_packet)) -} - -/// Converts a protobuf packet to a VersionedTransaction -pub fn versioned_tx_from_packet(p: &ProtoPacket) -> Option { - let mut data = [0; PACKET_DATA_SIZE]; - let copy_len = min(data.len(), p.data.len()); - data[..copy_len].copy_from_slice(&p.data[..copy_len]); - let mut packet = Packet::new(data, Default::default()); - if let Some(meta) = &p.meta { - packet.meta_mut().size = meta.size as usize; - } - packet.deserialize_slice(..).ok() -} - -/// Coverts a VersionedTransaction to packet -pub fn packet_from_versioned_tx(tx: VersionedTransaction) -> Packet { - let tx_data = serialize(&tx).expect("serializes"); - let mut data = [0; PACKET_DATA_SIZE]; - let copy_len = min(tx_data.len(), data.len()); - data[..copy_len].copy_from_slice(&tx_data[..copy_len]); - let mut packet = Packet::new(data, Default::default()); - packet.meta_mut().size = copy_len; - packet -} - -/// Converts a VersionedTransaction to a protobuf packet -pub fn proto_packet_from_versioned_tx(tx: &VersionedTransaction) -> ProtoPacket { - let data = serialize(tx).expect("serializes"); - let size = data.len() as u64; - ProtoPacket { - data, - meta: Some(ProtoMeta { - size, - addr: "".to_string(), - port: 0, - flags: None, - sender_stake: 0, - }), - } -} - -/// Converts a GRPC Socket to stdlib SocketAddr -impl TryFrom<&Socket> for SocketAddr { - type Error = AddrParseError; - - fn try_from(value: &Socket) -> Result { - IpAddr::from_str(&value.ip).map(|ip| SocketAddr::new(ip, value.port as u16)) - } -} - -// #[cfg(test)] -// mod tests { -// use solana_perf::test_tx::test_tx; -// use solana_sdk::transaction::VersionedTransaction; - -// use crate::convert::{proto_packet_from_versioned_tx, versioned_tx_from_packet}; - -// #[test] -// fn test_proto_to_packet() { -// let tx_before = VersionedTransaction::from(test_tx()); -// let tx_after = versioned_tx_from_packet(&proto_packet_from_versioned_tx(&tx_before)) -// .expect("tx_after"); - -// assert_eq!(tx_before, tx_after); -// } -// } diff --git a/src/protos/mod.rs b/src/protos/mod.rs deleted file mode 100755 index 0bf6c4d..0000000 --- a/src/protos/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -pub mod auth; -pub mod block; -pub mod block_engine; -pub mod bundle; -pub mod packet; -pub mod relayer; -pub mod searcher; -pub mod shared; -pub mod trace_shred; -pub mod convert; -pub mod nextblock_grpc; -pub mod searcher_client; -pub mod token_authenticator; diff --git a/src/protos/nextblock_grpc.rs b/src/protos/nextblock_grpc.rs deleted file mode 100755 index a69e66d..0000000 --- a/src/protos/nextblock_grpc.rs +++ /dev/null @@ -1,462 +0,0 @@ -// This file is @generated by prost-build. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PostSubmitRequest { - #[prost(message, optional, tag = "1")] - pub transaction: ::core::option::Option, - #[prost(bool, tag = "2")] - pub skip_pre_flight: bool, - #[prost(bool, optional, tag = "3")] - pub front_running_protection: ::core::option::Option, - #[prost(bool, optional, tag = "8")] - pub experimental_front_running_protection: ::core::option::Option, - #[prost(bool, optional, tag = "9")] - pub snipe_transaction: ::core::option::Option, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PostSubmitRequestEntry { - #[prost(message, optional, tag = "1")] - pub transaction: ::core::option::Option, - #[prost(bool, tag = "2")] - pub skip_pre_flight: bool, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PostSubmitBatchRequest { - #[prost(message, repeated, tag = "1")] - pub entries: ::prost::alloc::vec::Vec, - #[prost(enumeration = "SubmitStrategy", tag = "2")] - pub submit_strategy: i32, - #[prost(bool, optional, tag = "3")] - pub use_bundle: ::core::option::Option, - #[prost(bool, optional, tag = "4")] - pub front_running_protection: ::core::option::Option, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PostSubmitBatchResponseEntry { - #[prost(string, tag = "1")] - pub signature: ::prost::alloc::string::String, - #[prost(string, tag = "2")] - pub error: ::prost::alloc::string::String, - #[prost(bool, tag = "3")] - pub submitted: bool, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PostSubmitBatchResponse { - #[prost(message, repeated, tag = "1")] - pub transactions: ::prost::alloc::vec::Vec, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PostSubmitResponse { - #[prost(string, tag = "1")] - pub signature: ::prost::alloc::string::String, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TransactionMessage { - #[prost(string, tag = "1")] - pub content: ::prost::alloc::string::String, - #[prost(bool, tag = "2")] - pub is_cleanup: bool, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TransactionMessageV2 { - #[prost(string, tag = "1")] - pub content: ::prost::alloc::string::String, -} -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum SubmitStrategy { - PUknown = 0, - PSubmitAll = 1, - PAbortOnFirstError = 2, - PWaitForConfirmation = 3, -} -impl SubmitStrategy { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Self::PUknown => "P_UKNOWN", - Self::PSubmitAll => "P_SUBMIT_ALL", - Self::PAbortOnFirstError => "P_ABORT_ON_FIRST_ERROR", - Self::PWaitForConfirmation => "P_WAIT_FOR_CONFIRMATION", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "P_UKNOWN" => Some(Self::PUknown), - "P_SUBMIT_ALL" => Some(Self::PSubmitAll), - "P_ABORT_ON_FIRST_ERROR" => Some(Self::PAbortOnFirstError), - "P_WAIT_FOR_CONFIRMATION" => Some(Self::PWaitForConfirmation), - _ => None, - } - } -} -/// Generated client implementations. -pub mod api_client { - #![allow( - unused_variables, - dead_code, - missing_docs, - clippy::wildcard_imports, - clippy::let_unit_value, - )] - use tonic::codegen::*; - use tonic::codegen::http::Uri; - #[derive(Debug, Clone)] - pub struct ApiClient { - inner: tonic::client::Grpc, - } - impl ApiClient { - /// Attempt to create a new client by connecting to a given endpoint. - pub async fn connect(dst: D) -> Result - where - D: std::convert::TryInto, - D::Error: Into, - { - let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; - Ok(Self::new(conn)) - } - } - impl ApiClient - where - T: tonic::client::GrpcService, - T::Error: Into, - T::ResponseBody: Body + std::marker::Send + 'static, - ::Error: Into + std::marker::Send, - { - pub fn new(inner: T) -> Self { - let inner = tonic::client::Grpc::new(inner); - Self { inner } - } - pub fn with_origin(inner: T, origin: Uri) -> Self { - let inner = tonic::client::Grpc::with_origin(inner, origin); - Self { inner } - } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> ApiClient> - where - F: tonic::service::Interceptor, - T::ResponseBody: Default, - T: tonic::codegen::Service< - http::Request, - Response = http::Response< - >::ResponseBody, - >, - >, - , - >>::Error: Into + std::marker::Send + std::marker::Sync, - { - ApiClient::new(InterceptedService::new(inner, interceptor)) - } - /// Compress requests with the given encoding. - /// - /// This requires the server to support it otherwise it might respond with an - /// error. - #[must_use] - pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.send_compressed(encoding); - self - } - /// Enable decompressing responses. - #[must_use] - pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.accept_compressed(encoding); - self - } - /// Limits the maximum size of a decoded message. - /// - /// Default: `4MB` - #[must_use] - pub fn max_decoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_decoding_message_size(limit); - self - } - /// Limits the maximum size of an encoded message. - /// - /// Default: `usize::MAX` - #[must_use] - pub fn max_encoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_encoding_message_size(limit); - self - } - pub async fn post_submit_v2( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static("/api.Api/PostSubmitV2"); - let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new("api.Api", "PostSubmitV2")); - self.inner.unary(req, path, codec).await - } - pub async fn post_submit_batch_v2( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/api.Api/PostSubmitBatchV2", - ); - let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new("api.Api", "PostSubmitBatchV2")); - self.inner.unary(req, path, codec).await - } - } -} -/// Generated server implementations. -pub mod api_server { - #![allow( - unused_variables, - dead_code, - missing_docs, - clippy::wildcard_imports, - clippy::let_unit_value, - )] - use tonic::codegen::*; - /// Generated trait containing gRPC methods that should be implemented for use with ApiServer. - #[async_trait] - pub trait Api: std::marker::Send + std::marker::Sync + 'static { - async fn post_submit_v2( - &self, - request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; - async fn post_submit_batch_v2( - &self, - request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; - } - #[derive(Debug)] - pub struct ApiServer { - inner: Arc, - accept_compression_encodings: EnabledCompressionEncodings, - send_compression_encodings: EnabledCompressionEncodings, - max_decoding_message_size: Option, - max_encoding_message_size: Option, - } - impl ApiServer { - pub fn new(inner: T) -> Self { - Self::from_arc(Arc::new(inner)) - } - pub fn from_arc(inner: Arc) -> Self { - Self { - inner, - accept_compression_encodings: Default::default(), - send_compression_encodings: Default::default(), - max_decoding_message_size: None, - max_encoding_message_size: None, - } - } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> InterceptedService - where - F: tonic::service::Interceptor, - { - InterceptedService::new(Self::new(inner), interceptor) - } - /// Enable decompressing requests with the given encoding. - #[must_use] - pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.accept_compression_encodings.enable(encoding); - self - } - /// Compress responses with the given encoding, if the client supports it. - #[must_use] - pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.send_compression_encodings.enable(encoding); - self - } - /// Limits the maximum size of a decoded message. - /// - /// Default: `4MB` - #[must_use] - pub fn max_decoding_message_size(mut self, limit: usize) -> Self { - self.max_decoding_message_size = Some(limit); - self - } - /// Limits the maximum size of an encoded message. - /// - /// Default: `usize::MAX` - #[must_use] - pub fn max_encoding_message_size(mut self, limit: usize) -> Self { - self.max_encoding_message_size = Some(limit); - self - } - } - impl tonic::codegen::Service> for ApiServer - where - T: Api, - B: Body + std::marker::Send + 'static, - B::Error: Into + std::marker::Send + 'static, - { - type Response = http::Response; - type Error = std::convert::Infallible; - type Future = BoxFuture; - fn poll_ready( - &mut self, - _cx: &mut Context<'_>, - ) -> Poll> { - Poll::Ready(Ok(())) - } - fn call(&mut self, req: http::Request) -> Self::Future { - match req.uri().path() { - "/api.Api/PostSubmitV2" => { - #[allow(non_camel_case_types)] - struct PostSubmitV2Svc(pub Arc); - impl tonic::server::UnaryService - for PostSubmitV2Svc { - type Response = super::PostSubmitResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; - fn call( - &mut self, - request: tonic::Request, - ) -> Self::Future { - let inner = Arc::clone(&self.0); - let fut = async move { - ::post_submit_v2(&inner, request).await - }; - Box::pin(fut) - } - } - let accept_compression_encodings = self.accept_compression_encodings; - let send_compression_encodings = self.send_compression_encodings; - let max_decoding_message_size = self.max_decoding_message_size; - let max_encoding_message_size = self.max_encoding_message_size; - let inner = self.inner.clone(); - let fut = async move { - let method = PostSubmitV2Svc(inner); - let codec = tonic::codec::ProstCodec::default(); - let mut grpc = tonic::server::Grpc::new(codec) - .apply_compression_config( - accept_compression_encodings, - send_compression_encodings, - ) - .apply_max_message_size_config( - max_decoding_message_size, - max_encoding_message_size, - ); - let res = grpc.unary(method, req).await; - Ok(res) - }; - Box::pin(fut) - } - "/api.Api/PostSubmitBatchV2" => { - #[allow(non_camel_case_types)] - struct PostSubmitBatchV2Svc(pub Arc); - impl< - T: Api, - > tonic::server::UnaryService - for PostSubmitBatchV2Svc { - type Response = super::PostSubmitBatchResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; - fn call( - &mut self, - request: tonic::Request, - ) -> Self::Future { - let inner = Arc::clone(&self.0); - let fut = async move { - ::post_submit_batch_v2(&inner, request).await - }; - Box::pin(fut) - } - } - let accept_compression_encodings = self.accept_compression_encodings; - let send_compression_encodings = self.send_compression_encodings; - let max_decoding_message_size = self.max_decoding_message_size; - let max_encoding_message_size = self.max_encoding_message_size; - let inner = self.inner.clone(); - let fut = async move { - let method = PostSubmitBatchV2Svc(inner); - let codec = tonic::codec::ProstCodec::default(); - let mut grpc = tonic::server::Grpc::new(codec) - .apply_compression_config( - accept_compression_encodings, - send_compression_encodings, - ) - .apply_max_message_size_config( - max_decoding_message_size, - max_encoding_message_size, - ); - let res = grpc.unary(method, req).await; - Ok(res) - }; - Box::pin(fut) - } - _ => { - Box::pin(async move { - let mut response = http::Response::new(empty_body()); - let headers = response.headers_mut(); - headers - .insert( - tonic::Status::GRPC_STATUS, - (tonic::Code::Unimplemented as i32).into(), - ); - headers - .insert( - http::header::CONTENT_TYPE, - tonic::metadata::GRPC_CONTENT_TYPE, - ); - Ok(response) - }) - } - } - } - } - impl Clone for ApiServer { - fn clone(&self) -> Self { - let inner = self.inner.clone(); - Self { - inner, - accept_compression_encodings: self.accept_compression_encodings, - send_compression_encodings: self.send_compression_encodings, - max_decoding_message_size: self.max_decoding_message_size, - max_encoding_message_size: self.max_encoding_message_size, - } - } - } - /// Generated gRPC service name - pub const SERVICE_NAME: &str = "api.Api"; - impl tonic::server::NamedService for ApiServer { - const NAME: &'static str = SERVICE_NAME; - } -} \ No newline at end of file diff --git a/src/protos/packet.rs b/src/protos/packet.rs deleted file mode 100755 index fd20158..0000000 --- a/src/protos/packet.rs +++ /dev/null @@ -1,41 +0,0 @@ -// This file is @generated by prost-build. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PacketBatch { - #[prost(message, repeated, tag = "1")] - pub packets: ::prost::alloc::vec::Vec, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Packet { - #[prost(bytes = "vec", tag = "1")] - pub data: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag = "2")] - pub meta: ::core::option::Option, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Meta { - #[prost(uint64, tag = "1")] - pub size: u64, - #[prost(string, tag = "2")] - pub addr: ::prost::alloc::string::String, - #[prost(uint32, tag = "3")] - pub port: u32, - #[prost(message, optional, tag = "4")] - pub flags: ::core::option::Option, - #[prost(uint64, tag = "5")] - pub sender_stake: u64, -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct PacketFlags { - #[prost(bool, tag = "1")] - pub discard: bool, - #[prost(bool, tag = "2")] - pub forwarded: bool, - #[prost(bool, tag = "3")] - pub repair: bool, - #[prost(bool, tag = "4")] - pub simple_vote_tx: bool, - #[prost(bool, tag = "5")] - pub tracer_packet: bool, - #[prost(bool, tag = "6")] - pub from_staked_node: bool, -} diff --git a/src/protos/relayer.rs b/src/protos/relayer.rs deleted file mode 100755 index c771fc5..0000000 --- a/src/protos/relayer.rs +++ /dev/null @@ -1,178 +0,0 @@ -// This file is @generated by prost-build. -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct GetTpuConfigsRequest {} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GetTpuConfigsResponse { - #[prost(message, optional, tag = "1")] - pub tpu: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub tpu_forward: ::core::option::Option, -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct SubscribePacketsRequest {} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SubscribePacketsResponse { - #[prost(message, optional, tag = "1")] - pub header: ::core::option::Option, - #[prost(oneof = "subscribe_packets_response::Msg", tags = "2, 3")] - pub msg: ::core::option::Option, -} -/// Nested message and enum types in `SubscribePacketsResponse`. -pub mod subscribe_packets_response { - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Msg { - #[prost(message, tag = "2")] - Heartbeat(super::super::shared::Heartbeat), - #[prost(message, tag = "3")] - Batch(super::super::packet::PacketBatch), - } -} -/// Generated client implementations. -pub mod relayer_client { - #![allow( - unused_variables, - dead_code, - missing_docs, - clippy::wildcard_imports, - clippy::let_unit_value, - )] - use tonic::codegen::*; - use tonic::codegen::http::Uri; - /// / Relayers offer a TPU and TPU forward proxy for Solana validators. - /// / Validators can connect and fetch the TPU configuration for the relayer and start to advertise the - /// / relayer's information in gossip. - /// / They can also subscribe to packets which arrived on the TPU ports at the relayer - #[derive(Debug, Clone)] - pub struct RelayerClient { - inner: tonic::client::Grpc, - } - impl RelayerClient { - /// Attempt to create a new client by connecting to a given endpoint. - pub async fn connect(dst: D) -> Result - where - D: TryInto, - D::Error: Into, - { - let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; - Ok(Self::new(conn)) - } - } - impl RelayerClient - where - T: tonic::client::GrpcService, - T::Error: Into, - T::ResponseBody: Body + std::marker::Send + 'static, - ::Error: Into + std::marker::Send, - { - pub fn new(inner: T) -> Self { - let inner = tonic::client::Grpc::new(inner); - Self { inner } - } - pub fn with_origin(inner: T, origin: Uri) -> Self { - let inner = tonic::client::Grpc::with_origin(inner, origin); - Self { inner } - } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> RelayerClient> - where - F: tonic::service::Interceptor, - T::ResponseBody: Default, - T: tonic::codegen::Service< - http::Request, - Response = http::Response< - >::ResponseBody, - >, - >, - , - >>::Error: Into + std::marker::Send + std::marker::Sync, - { - RelayerClient::new(InterceptedService::new(inner, interceptor)) - } - /// Compress requests with the given encoding. - /// - /// This requires the server to support it otherwise it might respond with an - /// error. - #[must_use] - pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.send_compressed(encoding); - self - } - /// Enable decompressing responses. - #[must_use] - pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.accept_compressed(encoding); - self - } - /// Limits the maximum size of a decoded message. - /// - /// Default: `4MB` - #[must_use] - pub fn max_decoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_decoding_message_size(limit); - self - } - /// Limits the maximum size of an encoded message. - /// - /// Default: `usize::MAX` - #[must_use] - pub fn max_encoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_encoding_message_size(limit); - self - } - /// The relayer has TPU and TPU forward sockets that validators can leverage. - /// A validator can fetch this config and change its TPU and TPU forward port in gossip. - pub async fn get_tpu_configs( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/relayer.Relayer/GetTpuConfigs", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("relayer.Relayer", "GetTpuConfigs")); - self.inner.unary(req, path, codec).await - } - /// Validators can subscribe to packets from the relayer and receive a multiplexed signal that contains a mixture - /// of packets and heartbeats - pub async fn subscribe_packets( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response>, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/relayer.Relayer/SubscribePackets", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("relayer.Relayer", "SubscribePackets")); - self.inner.server_streaming(req, path, codec).await - } - } -} diff --git a/src/protos/searcher.rs b/src/protos/searcher.rs deleted file mode 100755 index ad922df..0000000 --- a/src/protos/searcher.rs +++ /dev/null @@ -1,363 +0,0 @@ -// This file is @generated by prost-build. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SlotList { - #[prost(uint64, repeated, tag = "1")] - pub slots: ::prost::alloc::vec::Vec, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ConnectedLeadersResponse { - /// Mapping of validator pubkey to leader slots for the current epoch. - #[prost(map = "string, message", tag = "1")] - pub connected_validators: ::std::collections::HashMap< - ::prost::alloc::string::String, - SlotList, - >, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SendBundleRequest { - #[prost(message, optional, tag = "1")] - pub bundle: ::core::option::Option, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SendBundleResponse { - /// server uuid for the bundle - #[prost(string, tag = "1")] - pub uuid: ::prost::alloc::string::String, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct NextScheduledLeaderRequest { - /// Defaults to the currently connected region if no region provided. - #[prost(string, repeated, tag = "1")] - pub regions: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct NextScheduledLeaderResponse { - /// the current slot the backend is on - #[prost(uint64, tag = "1")] - pub current_slot: u64, - /// the slot of the next leader - #[prost(uint64, tag = "2")] - pub next_leader_slot: u64, - /// the identity pubkey (base58) of the next leader - #[prost(string, tag = "3")] - pub next_leader_identity: ::prost::alloc::string::String, - /// the block engine region of the next leader - #[prost(string, tag = "4")] - pub next_leader_region: ::prost::alloc::string::String, -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct ConnectedLeadersRequest {} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ConnectedLeadersRegionedRequest { - /// Defaults to the currently connected region if no region provided. - #[prost(string, repeated, tag = "1")] - pub regions: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ConnectedLeadersRegionedResponse { - #[prost(map = "string, message", tag = "1")] - pub connected_validators: ::std::collections::HashMap< - ::prost::alloc::string::String, - ConnectedLeadersResponse, - >, -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct GetTipAccountsRequest {} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GetTipAccountsResponse { - #[prost(string, repeated, tag = "1")] - pub accounts: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct SubscribeBundleResultsRequest {} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct GetRegionsRequest {} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GetRegionsResponse { - /// The region the client is currently connected to - #[prost(string, tag = "1")] - pub current_region: ::prost::alloc::string::String, - /// Regions that are online and ready for connections - /// All regions: - #[prost(string, repeated, tag = "2")] - pub available_regions: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, -} -/// Generated client implementations. -pub mod searcher_service_client { - #![allow( - unused_variables, - dead_code, - missing_docs, - clippy::wildcard_imports, - clippy::let_unit_value, - )] - use tonic::codegen::*; - use tonic::codegen::http::Uri; - #[derive(Debug, Clone)] - pub struct SearcherServiceClient { - inner: tonic::client::Grpc, - } - impl SearcherServiceClient { - /// Attempt to create a new client by connecting to a given endpoint. - pub async fn connect(dst: D) -> Result - where - D: TryInto, - D::Error: Into, - { - let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; - Ok(Self::new(conn)) - } - } - impl SearcherServiceClient - where - T: tonic::client::GrpcService, - T::Error: Into, - T::ResponseBody: Body + std::marker::Send + 'static, - ::Error: Into + std::marker::Send, - { - pub fn new(inner: T) -> Self { - let inner = tonic::client::Grpc::new(inner); - Self { inner } - } - pub fn with_origin(inner: T, origin: Uri) -> Self { - let inner = tonic::client::Grpc::with_origin(inner, origin); - Self { inner } - } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> SearcherServiceClient> - where - F: tonic::service::Interceptor, - T::ResponseBody: Default, - T: tonic::codegen::Service< - http::Request, - Response = http::Response< - >::ResponseBody, - >, - >, - , - >>::Error: Into + std::marker::Send + std::marker::Sync, - { - SearcherServiceClient::new(InterceptedService::new(inner, interceptor)) - } - /// Compress requests with the given encoding. - /// - /// This requires the server to support it otherwise it might respond with an - /// error. - #[must_use] - pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.send_compressed(encoding); - self - } - /// Enable decompressing responses. - #[must_use] - pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.accept_compressed(encoding); - self - } - /// Limits the maximum size of a decoded message. - /// - /// Default: `4MB` - #[must_use] - pub fn max_decoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_decoding_message_size(limit); - self - } - /// Limits the maximum size of an encoded message. - /// - /// Default: `usize::MAX` - #[must_use] - pub fn max_encoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_encoding_message_size(limit); - self - } - /// Searchers can invoke this endpoint to subscribe to their respective bundle results. - /// A success result would indicate the bundle won its state auction and was submitted to the validator. - pub async fn subscribe_bundle_results( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response>, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/searcher.SearcherService/SubscribeBundleResults", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("searcher.SearcherService", "SubscribeBundleResults"), - ); - self.inner.server_streaming(req, path, codec).await - } - pub async fn send_bundle( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/searcher.SearcherService/SendBundle", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("searcher.SearcherService", "SendBundle")); - self.inner.unary(req, path, codec).await - } - /// Returns the next scheduled leader connected to the block engine. - pub async fn get_next_scheduled_leader( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/searcher.SearcherService/GetNextScheduledLeader", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("searcher.SearcherService", "GetNextScheduledLeader"), - ); - self.inner.unary(req, path, codec).await - } - /// Returns leader slots for connected jito validators during the current epoch. Only returns data for this region. - pub async fn get_connected_leaders( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/searcher.SearcherService/GetConnectedLeaders", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("searcher.SearcherService", "GetConnectedLeaders"), - ); - self.inner.unary(req, path, codec).await - } - /// Returns leader slots for connected jito validators during the current epoch. - pub async fn get_connected_leaders_regioned( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/searcher.SearcherService/GetConnectedLeadersRegioned", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "searcher.SearcherService", - "GetConnectedLeadersRegioned", - ), - ); - self.inner.unary(req, path, codec).await - } - /// Returns the tip accounts searchers shall transfer funds to for the leader to claim. - pub async fn get_tip_accounts( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/searcher.SearcherService/GetTipAccounts", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("searcher.SearcherService", "GetTipAccounts")); - self.inner.unary(req, path, codec).await - } - /// Returns region the client is directly connected to, along with all available regions - pub async fn get_regions( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/searcher.SearcherService/GetRegions", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("searcher.SearcherService", "GetRegions")); - self.inner.unary(req, path, codec).await - } - } -} diff --git a/src/protos/searcher_client.rs b/src/protos/searcher_client.rs deleted file mode 100755 index bdeeac6..0000000 --- a/src/protos/searcher_client.rs +++ /dev/null @@ -1,131 +0,0 @@ -use std::{ - sync::Arc, - time::{Duration, Instant}, -}; - -use crate::protos::{ - bundle::{ - Bundle, BundleResult, - }, - convert::proto_packet_from_versioned_tx, - searcher::{ - searcher_service_client::SearcherServiceClient, SendBundleRequest, SubscribeBundleResultsRequest, - }, -}; -use solana_sdk::{ - signature::Signature, - transaction::VersionedTransaction, -}; -use thiserror::Error; -use tokio::sync::Mutex; -use tonic::{ - transport::{self, Channel, Endpoint}, Status -}; -use yellowstone_grpc_client::ClientTlsConfig; - -use crate::swqos::common::poll_transaction_confirmation; -use crate::common::SolanaRpcClient; -use crate::swqos::TradeType; - -#[derive(Debug, Error)] -pub enum BlockEngineConnectionError { - #[error("transport error {0}")] - TransportError(#[from] transport::Error), - #[error("client error {0}")] - ClientError(#[from] Status), -} - -#[derive(Debug, Error)] -pub enum BundleRejectionError { - #[error("bundle lost state auction, auction: {0}, tip {1} lamports")] - StateAuctionBidRejected(String, u64), - #[error("bundle won state auction but failed global auction, auction {0}, tip {1} lamports")] - WinningBatchBidRejected(String, u64), - #[error("bundle simulation failure on tx {0}, message: {1:?}")] - SimulationFailure(String, Option), - #[error("internal error {0}")] - InternalError(String), -} - -pub type BlockEngineConnectionResult = Result; - -pub async fn get_searcher_client_no_auth( - block_engine_url: &str, -) -> BlockEngineConnectionResult> { - let searcher_channel = create_grpc_channel(block_engine_url).await?; - let searcher_client = SearcherServiceClient::new(searcher_channel); - Ok(searcher_client) -} - -pub async fn create_grpc_channel(url: &str) -> BlockEngineConnectionResult { - let mut endpoint = Endpoint::from_shared(url.to_string()).expect("invalid url"); - if url.starts_with("https") { - endpoint = endpoint.tls_config(ClientTlsConfig::new().with_native_roots())?; - } - - endpoint = endpoint.tcp_nodelay(true); - endpoint = endpoint.tcp_keepalive(Some(Duration::from_secs(10))); - endpoint = endpoint.connect_timeout(Duration::from_secs(20)); - endpoint = endpoint.http2_keep_alive_interval(Duration::from_secs(10)); - - Ok(endpoint.connect().await?) -} - -pub async fn subscribe_bundle_results( - searcher_client: Arc>>, - request: impl tonic::IntoRequest, -) -> std::result::Result< - tonic::Response>, - tonic::Status, -> { - let mut searcher = searcher_client.lock().await; - searcher.subscribe_bundle_results(request).await -} - -pub async fn send_bundle_with_confirmation( - rpc: Arc, - trade_type: TradeType, - transactions: &Vec, - searcher_client: Arc>>, -) -> Result, anyhow::Error> { - let start_time = Instant::now(); - let signatures = send_bundle_no_wait(transactions, searcher_client).await?; - println!(" Jito{}提交: {:?}", trade_type, start_time.elapsed()); - - let start_time: Instant = Instant::now(); - for signature in signatures.clone() { - match poll_transaction_confirmation(&rpc, signature).await { - Ok(_) => continue, - Err(_) => continue, - } - } - - println!(" Jito{}确认: {:?}", trade_type, start_time.elapsed()); - - Ok(signatures) -} - -pub async fn send_bundle_no_wait( - transactions: &Vec, - searcher_client: Arc>>, -) -> Result, anyhow::Error> { - let mut packets = vec![]; - let mut signatures = vec![]; - for transaction in transactions { - let packet = proto_packet_from_versioned_tx(transaction); - packets.push(packet); - signatures.push(transaction.signatures[0]); - } - - let mut searcher = searcher_client.lock().await; - searcher - .send_bundle(SendBundleRequest { - bundle: Some(Bundle { - header: None, - packets, - }), - }) - .await?; - - Ok(signatures) -} diff --git a/src/protos/shared.rs b/src/protos/shared.rs deleted file mode 100755 index b2b0680..0000000 --- a/src/protos/shared.rs +++ /dev/null @@ -1,18 +0,0 @@ -// This file is @generated by prost-build. -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct Header { - #[prost(message, optional, tag = "1")] - pub ts: ::core::option::Option<::prost_types::Timestamp>, -} -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct Heartbeat { - #[prost(uint64, tag = "1")] - pub count: u64, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Socket { - #[prost(string, tag = "1")] - pub ip: ::prost::alloc::string::String, - #[prost(int64, tag = "2")] - pub port: i64, -} diff --git a/src/protos/token_authenticator.rs b/src/protos/token_authenticator.rs deleted file mode 100755 index debb4ca..0000000 --- a/src/protos/token_authenticator.rs +++ /dev/null @@ -1,167 +0,0 @@ -use std::{ - sync::{Arc, RwLock}, - time::{Duration, SystemTime}, -}; - -use crate::protos::auth::{ - auth_service_client::AuthServiceClient, GenerateAuthChallengeRequest, - GenerateAuthTokensRequest, RefreshAccessTokenRequest, Role, Token, -}; -use prost_types::Timestamp; -use solana_metrics::datapoint_info; -use solana_sdk::signature::{Keypair, Signer}; -use tokio::{task::JoinHandle, time::sleep}; -use tonic::{service::Interceptor, transport::Channel, Request, Status}; - -use super::searcher_client::BlockEngineConnectionResult; - -const AUTHORIZATION_HEADER: &str = "authorization"; -const BEARER: &str = "Bearer "; - -/// Adds the token to each requests' authorization header. -/// Manages refreshing the token in a separate thread. -#[derive(Clone)] -pub struct ClientInterceptor { - /// The token added to each request header. - bearer_token: Arc>, -} - -impl ClientInterceptor { - pub async fn new( - mut auth_service_client: AuthServiceClient, - keypair: &Arc, - role: Role, - ) -> BlockEngineConnectionResult { - let (access_token, refresh_token) = - Self::auth(&mut auth_service_client, keypair, role).await?; - - let bearer_token = Arc::new(RwLock::new(access_token.value.clone())); - - let _refresh_token_thread = Self::spawn_token_refresh_thread( - auth_service_client, - bearer_token.clone(), - refresh_token, - access_token.expires_at_utc.unwrap(), - keypair.clone(), - role, - ); - - Ok(Self { bearer_token }) - } - - async fn auth( - auth_service_client: &mut AuthServiceClient, - keypair: &Keypair, - role: Role, - ) -> BlockEngineConnectionResult<(Token, Token)> { - let challenge_resp = auth_service_client - .generate_auth_challenge(GenerateAuthChallengeRequest { - role: role as i32, - pubkey: keypair.pubkey().as_ref().to_vec(), - }) - .await? - .into_inner(); - let challenge = format!("{}-{}", keypair.pubkey(), challenge_resp.challenge); - let signed_challenge = keypair.sign_message(challenge.as_bytes()).as_ref().to_vec(); - - let tokens = auth_service_client - .generate_auth_tokens(GenerateAuthTokensRequest { - challenge, - client_pubkey: keypair.pubkey().as_ref().to_vec(), - signed_challenge, - }) - .await? - .into_inner(); - - Ok((tokens.access_token.unwrap(), tokens.refresh_token.unwrap())) - } - - fn spawn_token_refresh_thread( - mut auth_service_client: AuthServiceClient, - bearer_token: Arc>, - refresh_token: Token, - access_token_expiration: Timestamp, - keypair: Arc, - role: Role, - ) -> JoinHandle> { - tokio::spawn(async move { - let mut refresh_token = refresh_token; - let mut access_token_expiration = access_token_expiration; - - loop { - let access_token_ttl = SystemTime::try_from(access_token_expiration.clone()) - .unwrap() - .duration_since(SystemTime::now()) - .unwrap_or_else(|_| Duration::from_secs(0)); - let refresh_token_ttl = - SystemTime::try_from(refresh_token.expires_at_utc.as_ref().unwrap().clone()) - .unwrap() - .duration_since(SystemTime::now()) - .unwrap_or_else(|_| Duration::from_secs(0)); - - let does_access_token_expire_soon = access_token_ttl < Duration::from_secs(5 * 60); - let does_refresh_token_expire_soon = - refresh_token_ttl < Duration::from_secs(5 * 60); - - match ( - does_refresh_token_expire_soon, - does_access_token_expire_soon, - ) { - // re-run entire auth workflow is refresh token expiring soon - (true, _) => { - let is_error = { - if let Ok((new_access_token, new_refresh_token)) = - Self::auth(&mut auth_service_client, &keypair, role).await - { - *bearer_token.write().unwrap() = new_access_token.value.clone(); - access_token_expiration = new_access_token.expires_at_utc.unwrap(); - refresh_token = new_refresh_token; - false - } else { - true - } - }; - datapoint_info!("searcher-full-auth", ("is_error", is_error, bool)); - } - // re-up the access token if it expires soon - (_, true) => { - let is_error = { - if let Ok(refresh_resp) = auth_service_client - .refresh_access_token(RefreshAccessTokenRequest { - refresh_token: refresh_token.value.clone(), - }) - .await - { - let access_token = refresh_resp.into_inner().access_token.unwrap(); - *bearer_token.write().unwrap() = access_token.value.clone(); - access_token_expiration = access_token.expires_at_utc.unwrap(); - false - } else { - true - } - }; - - datapoint_info!("searcher-refresh-auth", ("is_error", is_error, bool)); - } - _ => { - sleep(Duration::from_secs(60)).await; - } - } - } - }) - } -} - -impl Interceptor for ClientInterceptor { - fn call(&mut self, mut request: Request<()>) -> Result, Status> { - let l_token = self.bearer_token.read().unwrap(); - if !l_token.is_empty() { - request.metadata_mut().insert( - AUTHORIZATION_HEADER, - format!("{BEARER}{l_token}").parse().unwrap(), - ); - } - - Ok(request) - } -} diff --git a/src/protos/trace_shred.rs b/src/protos/trace_shred.rs deleted file mode 100755 index 35c5558..0000000 --- a/src/protos/trace_shred.rs +++ /dev/null @@ -1,13 +0,0 @@ -// This file is @generated by prost-build. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TraceShred { - /// source region, one of: - #[prost(string, tag = "1")] - pub region: ::prost::alloc::string::String, - /// timestamp of creation - #[prost(message, optional, tag = "2")] - pub created_at: ::core::option::Option<::prost_types::Timestamp>, - /// monotonically increases, resets upon service restart - #[prost(uint32, tag = "3")] - pub seq_num: u32, -} diff --git a/src/swqos/mod.rs b/src/swqos/mod.rs index 1239af0..41c0239 100755 --- a/src/swqos/mod.rs +++ b/src/swqos/mod.rs @@ -12,7 +12,8 @@ pub mod astralane; use std::sync::Arc; -use solana_sdk::{commitment_config::CommitmentConfig, transaction::VersionedTransaction}; +use solana_commitment_config::CommitmentConfig; +use solana_sdk::transaction::VersionedTransaction; use tokio::sync::RwLock; use anyhow::Result; diff --git a/src/swqos/solana_rpc.rs b/src/swqos/solana_rpc.rs index 59368c9..56212a6 100755 --- a/src/swqos/solana_rpc.rs +++ b/src/swqos/solana_rpc.rs @@ -1,7 +1,8 @@ use std::{sync::Arc, time::Instant}; use solana_client::rpc_config::RpcSendTransactionConfig; -use solana_sdk::{commitment_config::CommitmentLevel, transaction::VersionedTransaction}; +use solana_commitment_config::CommitmentLevel; +use solana_sdk::transaction::VersionedTransaction; use solana_transaction_status::UiTransactionEncoding; use crate::swqos::SwqosClientTrait; diff --git a/src/trading/common/compute_budget_manager.rs b/src/trading/common/compute_budget_manager.rs index 4491607..2cd8325 100755 --- a/src/trading/common/compute_budget_manager.rs +++ b/src/trading/common/compute_budget_manager.rs @@ -1,7 +1,8 @@ use dashmap::DashMap; use once_cell::sync::Lazy; use smallvec::SmallVec; -use solana_sdk::{compute_budget::ComputeBudgetInstruction, instruction::Instruction}; +use solana_sdk::instruction::Instruction; +use solana_compute_budget_interface::ComputeBudgetInstruction; /// Cache key containing all parameters for compute budget instructions #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/trading/common/utils.rs b/src/trading/common/utils.rs index b884a35..68399c1 100644 --- a/src/trading/common/utils.rs +++ b/src/trading/common/utils.rs @@ -1,9 +1,10 @@ use solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer, transaction::Transaction}; use solana_system_interface::instruction::transfer; -use spl_associated_token_account::get_associated_token_address; -use spl_token::instruction::close_account; -use crate::common::SolanaRpcClient; +use crate::common::{ + fast_fn::get_associated_token_address_with_program_id_fast, spl_token::close_account, + SolanaRpcClient, +}; use anyhow::anyhow; /// Get the balances of two tokens in the pool @@ -35,7 +36,11 @@ pub async fn get_token_balance( payer: &Pubkey, mint: &Pubkey, ) -> Result { - let ata = get_associated_token_address(payer, mint); + let ata = crate::common::fast_fn::get_associated_token_address_with_program_id_fast( + payer, + mint, + &crate::constants::TOKEN_PROGRAM, + ); let balance = rpc.get_token_account_balance(&ata).await?; let balance_u64 = balance.amount.parse::().map_err(|_| anyhow!("Failed to parse token balance"))?; @@ -102,7 +107,11 @@ pub async fn close_token_account( mint: &Pubkey, ) -> Result<(), anyhow::Error> { // Get associated token account address - let ata = get_associated_token_address(&payer.pubkey(), mint); + let ata = get_associated_token_address_with_program_id_fast( + &payer.pubkey(), + mint, + &crate::constants::TOKEN_PROGRAM, + ); // Check if account exists let account_exists = rpc.get_account(&ata).await.is_ok(); diff --git a/src/trading/common/wsol_manager.rs b/src/trading/common/wsol_manager.rs index 40f71ab..9b0d869 100644 --- a/src/trading/common/wsol_manager.rs +++ b/src/trading/common/wsol_manager.rs @@ -1,8 +1,9 @@ -use crate::common::fast_fn::create_associated_token_account_idempotent_fast; +use crate::common::{ + fast_fn::create_associated_token_account_idempotent_fast, spl_token::close_account, +}; use smallvec::SmallVec; -use solana_sdk::{instruction::Instruction, pubkey::Pubkey}; +use solana_sdk::{instruction::Instruction, message::AccountMeta, pubkey::Pubkey}; use solana_system_interface::instruction::transfer; -use spl_token::instruction::close_account; #[inline] pub fn handle_wsol(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 3]> { @@ -22,8 +23,12 @@ pub fn handle_wsol(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 3]> )); insts.extend([ transfer(&payer, &wsol_token_account, amount_in), - spl_token::instruction::sync_native(&crate::constants::TOKEN_PROGRAM, &wsol_token_account) - .unwrap(), + // sync_native + Instruction { + program_id: crate::constants::TOKEN_PROGRAM, + accounts: vec![AccountMeta::new(wsol_token_account, false)], + data: vec![17], + }, ]); insts diff --git a/src/trading/core/params.rs b/src/trading/core/params.rs index d28dea1..db2082e 100755 --- a/src/trading/core/params.rs +++ b/src/trading/core/params.rs @@ -1,9 +1,10 @@ use super::traits::ProtocolParams; use crate::common::bonding_curve::BondingCurveAccount; use crate::common::nonce_cache::DurableNonceInfo; +use crate::common::spl_associated_token_account::get_associated_token_address_with_program_id; use crate::common::SolanaRpcClient; -use crate::solana_streamer_sdk::streaming::event_parser::common::EventType; -use crate::solana_streamer_sdk::streaming::event_parser::protocols::bonk::BonkTradeEvent; +use solana_streamer_sdk::streaming::event_parser::common::EventType; +use solana_streamer_sdk::streaming::event_parser::protocols::bonk::BonkTradeEvent; use crate::swqos::{SwqosClient, TradeType}; use crate::trading::common::get_multi_token_balances; use crate::trading::MiddlewareManager; @@ -15,7 +16,6 @@ use solana_streamer_sdk::streaming::event_parser::protocols::pumpswap::{ }; use solana_streamer_sdk::streaming::event_parser::protocols::raydium_amm_v4::types::AmmInfo; use solana_streamer_sdk::streaming::event_parser::protocols::raydium_cpmm::RaydiumCpmmSwapEvent; -use spl_associated_token_account::get_associated_token_address; use std::sync::Arc; /// Swap parameters @@ -121,7 +121,11 @@ impl PumpFunParams { complete: account.0.complete, creator: account.0.creator, }; - let associated_bonding_curve = get_associated_token_address(&bonding_curve.account, mint); + let associated_bonding_curve = get_associated_token_address_with_program_id( + &bonding_curve.account, + mint, + &crate::constants::TOKEN_PROGRAM, + ); let creator_vault = crate::instruction::utils::pumpfun::get_creator_vault_pda(&bonding_curve.creator); Ok(Self { @@ -244,18 +248,16 @@ impl PumpSwapParams { let coin_creator_vault_authority = crate::instruction::utils::pumpswap::coin_creator_vault_authority(creator); - let base_token_program_ata = - spl_associated_token_account::get_associated_token_address_with_program_id( - &pool_address, - &pool_data.base_mint, - &crate::constants::TOKEN_PROGRAM, - ); - let quote_token_program_ata = - spl_associated_token_account::get_associated_token_address_with_program_id( - &pool_address, - &pool_data.quote_mint, - &crate::constants::TOKEN_PROGRAM, - ); + let base_token_program_ata = get_associated_token_address_with_program_id( + &pool_address, + &pool_data.base_mint, + &crate::constants::TOKEN_PROGRAM, + ); + let quote_token_program_ata = get_associated_token_address_with_program_id( + &pool_address, + &pool_data.quote_mint, + &crate::constants::TOKEN_PROGRAM, + ); Ok(Self { pool: pool_address.clone(), @@ -303,7 +305,6 @@ pub struct BonkParams { pub base_vault: Pubkey, pub quote_vault: Pubkey, /// Token program ID - /// Specifies the program used by the token, usually spl_token::ID or spl_token_2022::ID pub mint_token_program: Pubkey, pub platform_config: Pubkey, pub platform_associated_account: Pubkey, @@ -473,9 +474,9 @@ pub struct RaydiumCpmmParams { pub base_vault: Pubkey, /// Quote token vault address pub quote_vault: Pubkey, - /// Base token program ID (usually spl_token::ID or spl_token_2022::ID) + /// Base token program ID pub base_token_program: Pubkey, - /// Quote token program ID (usually spl_token::ID or spl_token_2022::ID) + /// Quote token program ID pub quote_token_program: Pubkey, /// Observation state account pub observation_state: Pubkey,