Merge pull request #67 from HelvetiCrypt/feat/shared-infrastructure
Add shared_infrastructure example and update documentation
This commit is contained in:
@@ -17,6 +17,7 @@ readme = "README.md"
|
||||
[workspace]
|
||||
members = [
|
||||
"examples/trading_client",
|
||||
"examples/shared_infrastructure",
|
||||
"examples/middleware_system",
|
||||
"examples/pumpfun_copy_trading",
|
||||
"examples/pumpfun_sniper_trading",
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
8. **Concurrent Trading**: Send transactions using multiple MEV services simultaneously; the fastest succeeds while others fail
|
||||
9. **Unified Trading Interface**: Use unified trading protocol enums for trading operations
|
||||
10. **Middleware System**: Support for custom instruction middleware to modify, add, or remove instructions before transaction execution
|
||||
11. **Shared Infrastructure**: Share expensive RPC and SWQOS clients across multiple wallets for reduced resource usage
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
@@ -105,6 +106,7 @@ sol-trade-sdk = "3.3.6"
|
||||
|
||||
You can refer to [Example: Create TradingClient Instance](examples/trading_client/src/main.rs).
|
||||
|
||||
**Method 1: Simple (single wallet)**
|
||||
```rust
|
||||
// Wallet
|
||||
let payer = Keypair::from_base58_string("use_your_payer_keypair_here");
|
||||
@@ -116,27 +118,29 @@ let swqos_configs: Vec<SwqosConfig> = vec![
|
||||
SwqosConfig::Default(rpc_url.clone()),
|
||||
SwqosConfig::Jito("your uuid".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Bloxroute("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::ZeroSlot("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Temporal("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::FlashBlock("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Node1("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::BlockRazor("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Astralane("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
];
|
||||
// Create TradeConfig instance
|
||||
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
|
||||
|
||||
// Optional: Customize WSOL ATA and Seed optimization settings
|
||||
// let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment)
|
||||
// .with_wsol_ata_config(
|
||||
// true, // create_wsol_ata_on_startup: Check and create WSOL ATA on startup (default: true)
|
||||
// true // use_seed_optimize: Enable seed optimization globally for all ATA operations (default: true)
|
||||
// );
|
||||
|
||||
// Create TradingClient
|
||||
let client = TradingClient::new(Arc::new(payer), trade_config).await;
|
||||
```
|
||||
|
||||
**Method 2: Shared infrastructure (multiple wallets)**
|
||||
|
||||
For multi-wallet scenarios, create the infrastructure once and share it across wallets.
|
||||
See [Example: Shared Infrastructure](examples/shared_infrastructure/src/main.rs).
|
||||
|
||||
```rust
|
||||
// Create infrastructure once (expensive)
|
||||
let infra_config = InfrastructureConfig::new(rpc_url, swqos_configs, commitment);
|
||||
let infrastructure = Arc::new(TradingInfrastructure::new(infra_config).await);
|
||||
|
||||
// Create multiple clients sharing the same infrastructure (fast)
|
||||
let client1 = TradingClient::from_infrastructure(Arc::new(payer1), infrastructure.clone(), true);
|
||||
let client2 = TradingClient::from_infrastructure(Arc::new(payer2), infrastructure.clone(), true);
|
||||
```
|
||||
|
||||
#### 2. Configure Gas Fee Strategy
|
||||
|
||||
For detailed information about Gas Fee Strategy, see the [Gas Fee Strategy Reference](docs/GAS_FEE_STRATEGY.md).
|
||||
@@ -197,6 +201,7 @@ Please ensure that the parameters your trading logic depends on are available in
|
||||
| Description | Run Command | Source Code |
|
||||
|-------------|-------------|-------------|
|
||||
| Create and configure TradingClient instance | `cargo run --package trading_client` | [examples/trading_client](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/trading_client/src/main.rs) |
|
||||
| Share infrastructure across multiple wallets | `cargo run --package shared_infrastructure` | [examples/shared_infrastructure](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/shared_infrastructure/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) |
|
||||
| PumpSwap trading operations | `cargo run --package pumpswap_trading` | [examples/pumpswap_trading](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/pumpswap_trading/src/main.rs) |
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "shared_infrastructure"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
sol-trade-sdk = { path = "../.." }
|
||||
solana-sdk = "3.0.0"
|
||||
solana-commitment-config = { version = "3.0.0", features = ["serde"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
@@ -0,0 +1,72 @@
|
||||
//! Shared Infrastructure Example
|
||||
//!
|
||||
//! This example demonstrates how to share expensive infrastructure (RPC client, SWQOS clients)
|
||||
//! across multiple wallets, significantly reducing resource usage and initialization time.
|
||||
//!
|
||||
//! Use this pattern when:
|
||||
//! - Running a trading service with multiple wallets
|
||||
//! - All wallets use the same RPC endpoint and SWQOS configuration
|
||||
//! - You want to minimize memory usage and connection overhead
|
||||
//!
|
||||
//! Benefits:
|
||||
//! - First wallet: Full async initialization (~200-500ms)
|
||||
//! - Additional wallets: Fast sync initialization (~1-2ms)
|
||||
//! - Shared RPC connection pool and SWQOS clients
|
||||
|
||||
use sol_trade_sdk::{
|
||||
common::InfrastructureConfig,
|
||||
swqos::{SwqosConfig, SwqosRegion},
|
||||
TradingClient, TradingInfrastructure,
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
use solana_sdk::signature::Keypair;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Configuration (same for all wallets)
|
||||
let rpc_url = "https://mainnet.helius-rpc.com/?api-key=xxxxxx".to_string();
|
||||
let commitment = CommitmentConfig::processed();
|
||||
let swqos_configs: Vec<SwqosConfig> = vec![
|
||||
SwqosConfig::Default(rpc_url.clone()),
|
||||
SwqosConfig::Jito("your_uuid".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Bloxroute("your_api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
];
|
||||
|
||||
// Step 1: Create shared infrastructure (expensive, do once)
|
||||
println!("Creating shared infrastructure...");
|
||||
let infra_config = InfrastructureConfig::new(rpc_url, swqos_configs, commitment);
|
||||
let infrastructure = Arc::new(TradingInfrastructure::new(infra_config).await);
|
||||
println!("Infrastructure created with {} SWQOS clients", infrastructure.swqos_clients.len());
|
||||
|
||||
// Step 2: Create multiple TradingClients sharing the same infrastructure (fast)
|
||||
let wallet_keys = vec![
|
||||
"wallet1_base58_private_key_here",
|
||||
"wallet2_base58_private_key_here",
|
||||
"wallet3_base58_private_key_here",
|
||||
];
|
||||
|
||||
let mut clients = Vec::new();
|
||||
for (i, key) in wallet_keys.iter().enumerate() {
|
||||
println!("Creating client for wallet {}...", i + 1);
|
||||
let payer = Arc::new(Keypair::from_base58_string(key));
|
||||
|
||||
// Fast: reuses existing infrastructure
|
||||
let client = TradingClient::from_infrastructure(
|
||||
payer,
|
||||
infrastructure.clone(),
|
||||
true, // use_seed_optimize
|
||||
);
|
||||
clients.push(client);
|
||||
println!(" Client {} created (shares infrastructure)", i + 1);
|
||||
}
|
||||
|
||||
println!("\nCreated {} clients sharing 1 infrastructure instance", clients.len());
|
||||
println!(" - 1 RPC client (shared)");
|
||||
println!(" - {} SWQOS clients (shared)", infrastructure.swqos_clients.len());
|
||||
|
||||
// All clients can now trade concurrently using shared resources
|
||||
// Example: clients[0].buy(buy_params).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,7 +1,16 @@
|
||||
//! TradingClient Creation Example
|
||||
//!
|
||||
//! This example demonstrates two ways to create a TradingClient:
|
||||
//!
|
||||
//! 1. Simple method: `TradingClient::new()` - creates client with its own infrastructure
|
||||
//! 2. Shared method: `TradingClient::from_infrastructure()` - reuses existing infrastructure
|
||||
//!
|
||||
//! For multi-wallet scenarios, see the `shared_infrastructure` example.
|
||||
|
||||
use sol_trade_sdk::{
|
||||
common::{AnyResult, TradeConfig},
|
||||
common::{AnyResult, InfrastructureConfig, TradeConfig},
|
||||
swqos::{SwqosConfig, SwqosRegion},
|
||||
SolanaTrade,
|
||||
TradingClient, TradingInfrastructure,
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
use solana_sdk::signature::Keypair;
|
||||
@@ -9,32 +18,75 @@ use std::sync::Arc;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let _ = create_solana_trade_client().await?;
|
||||
println!("Successfully created SolanaTrade client!");
|
||||
// Method 1: Simple - TradingClient::new() (recommended for single wallet)
|
||||
let client = create_trading_client_simple().await?;
|
||||
println!("Method 1: Created TradingClient with new()");
|
||||
println!(" Wallet: {}", client.get_payer_pubkey());
|
||||
|
||||
// Method 2: From infrastructure (recommended for multiple wallets)
|
||||
let client2 = create_trading_client_from_infrastructure().await?;
|
||||
println!("\nMethod 2: Created TradingClient with from_infrastructure()");
|
||||
println!(" Wallet: {}", client2.get_payer_pubkey());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create SolanaTrade client
|
||||
/// Initializes a new SolanaTrade client with configuration
|
||||
async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
|
||||
println!("Creating SolanaTrade client...");
|
||||
/// Method 1: Create TradingClient using TradeConfig (simple, self-contained)
|
||||
///
|
||||
/// Use this when you have a single wallet or don't need to share infrastructure.
|
||||
async fn create_trading_client_simple() -> AnyResult<TradingClient> {
|
||||
let payer = Keypair::from_base58_string("use_your_payer_keypair_here");
|
||||
let rpc_url = "https://mainnet.helius-rpc.com/?api-key=xxxxxx".to_string();
|
||||
println!("rpc_url: {}", rpc_url);
|
||||
let commitment = CommitmentConfig::processed();
|
||||
|
||||
let swqos_configs: Vec<SwqosConfig> = vec![
|
||||
SwqosConfig::Default(rpc_url.clone()),
|
||||
SwqosConfig::Jito("your uuid".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Bloxroute("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::ZeroSlot("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Temporal("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::FlashBlock("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Node1("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::BlockRazor("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Astralane("your api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Jito("your_uuid".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Bloxroute("your_api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::ZeroSlot("your_api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Temporal("your_api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::FlashBlock("your_api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Node1("your_api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::BlockRazor("your_api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
SwqosConfig::Astralane("your_api_token".to_string(), SwqosRegion::Frankfurt, None),
|
||||
];
|
||||
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
|
||||
let solana_trade_client = SolanaTrade::new(Arc::new(payer), trade_config).await;
|
||||
println!("SolanaTrade client created successfully!");
|
||||
Ok(solana_trade_client)
|
||||
|
||||
// Optional: Customize WSOL ATA and Seed optimization settings
|
||||
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment)
|
||||
.with_wsol_ata_config(
|
||||
true, // create_wsol_ata_on_startup: Check and create WSOL ATA on startup
|
||||
true, // use_seed_optimize: Enable seed optimization for all ATA operations
|
||||
);
|
||||
|
||||
// Creates new infrastructure internally
|
||||
let client = TradingClient::new(Arc::new(payer), trade_config).await;
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
/// Method 2: Create TradingClient from shared infrastructure
|
||||
///
|
||||
/// Use this when you have multiple wallets sharing the same configuration.
|
||||
/// The infrastructure (RPC client, SWQOS clients) is created once and shared.
|
||||
async fn create_trading_client_from_infrastructure() -> AnyResult<TradingClient> {
|
||||
let payer = Keypair::from_base58_string("use_your_payer_keypair_here");
|
||||
let rpc_url = "https://mainnet.helius-rpc.com/?api-key=xxxxxx".to_string();
|
||||
let commitment = CommitmentConfig::processed();
|
||||
|
||||
let swqos_configs: Vec<SwqosConfig> = vec![
|
||||
SwqosConfig::Default(rpc_url.clone()),
|
||||
SwqosConfig::Jito("your_uuid".to_string(), SwqosRegion::Frankfurt, None),
|
||||
];
|
||||
|
||||
// Create infrastructure separately (can be shared across multiple wallets)
|
||||
let infra_config = InfrastructureConfig::new(rpc_url, swqos_configs, commitment);
|
||||
let infrastructure = Arc::new(TradingInfrastructure::new(infra_config).await);
|
||||
|
||||
// Create client from existing infrastructure (fast, no async needed)
|
||||
let client = TradingClient::from_infrastructure(
|
||||
Arc::new(payer),
|
||||
infrastructure,
|
||||
true, // use_seed_optimize
|
||||
);
|
||||
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user