diff --git a/README.md b/README.md index 961e1a9..7d9f67c 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,32 @@ When configuring SWQOS services, note the different parameter requirements for e - **Temporal**: The first parameter is API Token - **FlashBlock**: The first parameter is API Token, Add community TG admin [xyz_0xfnzero](https://t.me/xyz_0xfnzero) to get a free key and instantly speed up your trading (with tip refunds available)! - **BlockRazor**: The first parameter is API Token, Add official TG support to get a free key and instantly accelerate your trades! -- **Node1**: The first parameter is API Token, Add the official TG support at https://t.me/node1_me to get a free key and instantly accelerate your trades! +- **Node1**: The first parameter is API Token, Add the official TG support at https://t.me/node1_me to get a free key and instantly accelerate your trades! + +#### Custom URL Support + +Each SWQOS service now supports an optional custom URL parameter: + +```rust +// Using custom URL (third parameter) +let jito_config = SwqosConfig::Jito( + "your_uuid".to_string(), + SwqosRegion::Frankfurt, // This parameter is still required but will be ignored + Some("https://custom-jito-endpoint.com".to_string()) // Custom URL +); + +// Using default regional endpoint (third parameter is None) +let nextblock_config = SwqosConfig::NextBlock( + "your_api_token".to_string(), + SwqosRegion::NewYork, // Will use the default endpoint for this region + None // No custom URL, uses SwqosRegion +); +``` + +**URL Priority Logic**: +- If a custom URL is provided (`Some(url)`), it will be used instead of the regional endpoint +- If no custom URL is provided (`None`), the system will use the default endpoint for the specified `SwqosRegion` +- This allows for maximum flexibility while maintaining backward compatibility When using multiple MEV services, you need to use `Durable Nonce`. You need to initialize a `NonceCache` class (or write your own nonce management class), get the latest `nonce` value, and use it as the `blockhash` when trading. diff --git a/README_CN.md b/README_CN.md index 634a792..2542a39 100755 --- a/README_CN.md +++ b/README_CN.md @@ -120,6 +120,31 @@ sol-trade-sdk = "0.5.7" - **BlockRazor**: 第一个参数是 API Token, 添加tg官方客服获取免费key立即加速你的交易! - **Node1**: 第一个参数是 API Token, 添加tg官方客服https://t.me/node1_me 获取免费key立即加速你的交易! +#### 自定义 URL 支持 + +每个 SWQOS 服务现在都支持可选的自定义 URL 参数: + +```rust +// 使用自定义 URL(第三个参数) +let jito_config = SwqosConfig::Jito( + "your_uuid".to_string(), + SwqosRegion::Frankfurt, // 这个参数仍然需要,但会被忽略 + Some("https://custom-jito-endpoint.com".to_string()) // 自定义 URL +); + +// 使用默认区域端点(第三个参数为 None) +let nextblock_config = SwqosConfig::NextBlock( + "your_api_token".to_string(), + SwqosRegion::NewYork, // 将使用该区域的默认端点 + None // 没有自定义 URL,使用 SwqosRegion +); +``` + +**URL 优先级逻辑**: +- 如果提供了自定义 URL(`Some(url)`),将使用自定义 URL 而不是区域端点 +- 如果没有提供自定义 URL(`None`),系统将使用指定 `SwqosRegion` 的默认端点 +- 这提供了最大的灵活性,同时保持向后兼容性 + 当使用多个MEV服务时,需要使用`Durable Nonce`。你需要初始化`NonceCache`类(或者自行写一个管理nonce的类),获取最新的`nonce`值,并在交易的时候作为`blockhash`使用。 ### 中间件系统说明 diff --git a/examples/trading_client/src/main.rs b/examples/trading_client/src/main.rs index 75bcba1..695a3a8 100644 --- a/examples/trading_client/src/main.rs +++ b/examples/trading_client/src/main.rs @@ -35,16 +35,16 @@ async fn test_create_solana_trade_client() -> AnyResult { fn create_swqos_configs(rpc_url: &str) -> Vec { vec![ // First parameter is UUID, pass empty string if no UUID - SwqosConfig::Jito("your uuid".to_string(), SwqosRegion::Frankfurt), - SwqosConfig::NextBlock("your api_token".to_string(), SwqosRegion::Frankfurt), - SwqosConfig::Bloxroute("your api_token".to_string(), SwqosRegion::Frankfurt), - SwqosConfig::ZeroSlot("your api_token".to_string(), SwqosRegion::Frankfurt), - SwqosConfig::Temporal("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Jito("your uuid".to_string(), SwqosRegion::Frankfurt, None), + SwqosConfig::NextBlock("your api_token".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), // Add tg official customer https://t.me/FlashBlock_Official to get free FlashBlock key - SwqosConfig::FlashBlock("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::FlashBlock("your api_token".to_string(), SwqosRegion::Frankfurt, None), // Add tg official customer https://t.me/node1_me to get free Node1 key - SwqosConfig::Node1("your api_token".to_string(), SwqosRegion::Frankfurt), - SwqosConfig::BlockRazor("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Node1("your api_token".to_string(), SwqosRegion::Frankfurt, None), + SwqosConfig::BlockRazor("your api_token".to_string(), SwqosRegion::Frankfurt, None), SwqosConfig::Default(rpc_url.to_string()), ] } diff --git a/src/main.rs b/src/main.rs index 524cc70..a042ba5 100755 --- a/src/main.rs +++ b/src/main.rs @@ -75,14 +75,14 @@ async fn test_create_solana_trade_client() -> AnyResult { fn create_swqos_configs(rpc_url: &str) -> Vec { vec![ - SwqosConfig::Jito("your api_token".to_string(), SwqosRegion::Frankfurt), - SwqosConfig::NextBlock("your api_token".to_string(), SwqosRegion::Frankfurt), - SwqosConfig::Bloxroute("your api_token".to_string(), SwqosRegion::Frankfurt), - SwqosConfig::ZeroSlot("your api_token".to_string(), SwqosRegion::Frankfurt), - SwqosConfig::Temporal("your api_token".to_string(), SwqosRegion::Frankfurt), - SwqosConfig::Node1("your api_token".to_string(), SwqosRegion::Frankfurt), - SwqosConfig::FlashBlock("your api_token".to_string(), SwqosRegion::Frankfurt), - SwqosConfig::BlockRazor("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Jito("your api_token".to_string(), SwqosRegion::Frankfurt, None), + SwqosConfig::NextBlock("your api_token".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::Node1("your api_token".to_string(), SwqosRegion::Frankfurt, None), + SwqosConfig::FlashBlock("your api_token".to_string(), SwqosRegion::Frankfurt, None), + SwqosConfig::BlockRazor("your api_token".to_string(), SwqosRegion::Frankfurt, None), SwqosConfig::Default(rpc_url.to_string()), ] } diff --git a/src/swqos/mod.rs b/src/swqos/mod.rs index 22382e8..38787e8 100755 --- a/src/swqos/mod.rs +++ b/src/swqos/mod.rs @@ -103,18 +103,22 @@ pub enum SwqosRegion { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum SwqosConfig { Default(String), - Jito(String, SwqosRegion), - NextBlock(String, SwqosRegion), - Bloxroute(String, SwqosRegion), - Temporal(String, SwqosRegion), - ZeroSlot(String, SwqosRegion), - Node1(String, SwqosRegion), - FlashBlock(String, SwqosRegion), - BlockRazor(String, SwqosRegion), + Jito(String, SwqosRegion, Option), + NextBlock(String, SwqosRegion, Option), + Bloxroute(String, SwqosRegion, Option), + Temporal(String, SwqosRegion, Option), + ZeroSlot(String, SwqosRegion, Option), + Node1(String, SwqosRegion, Option), + FlashBlock(String, SwqosRegion, Option), + BlockRazor(String, SwqosRegion, Option), } impl SwqosConfig { - pub fn get_endpoint(swqos_type: SwqosType, region: SwqosRegion) -> String { + pub fn get_endpoint(swqos_type: SwqosType, region: SwqosRegion, url: Option) -> String { + if let Some(custom_url) = url { + return custom_url; + } + match swqos_type { SwqosType::Jito => SWQOS_ENDPOINTS_JITO[region as usize].to_string(), SwqosType::NextBlock => SWQOS_ENDPOINTS_NEXTBLOCK[region as usize].to_string(), @@ -130,8 +134,8 @@ impl SwqosConfig { pub fn get_swqos_client(rpc_url: String, commitment: CommitmentConfig, swqos_config: SwqosConfig) -> Arc { match swqos_config { - SwqosConfig::Jito(auth_token, region) => { - let endpoint = SwqosConfig::get_endpoint(SwqosType::Jito, region); + SwqosConfig::Jito(auth_token, region, url) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::Jito, region, url); let jito_client = JitoClient::new( rpc_url.clone(), endpoint, @@ -139,8 +143,8 @@ impl SwqosConfig { ); Arc::new(jito_client) } - SwqosConfig::NextBlock(auth_token, region) => { - let endpoint = SwqosConfig::get_endpoint(SwqosType::NextBlock, region); + SwqosConfig::NextBlock(auth_token, region, url) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::NextBlock, region, url); let nextblock_client = NextBlockClient::new( rpc_url.clone(), endpoint.to_string(), @@ -148,8 +152,8 @@ impl SwqosConfig { ); Arc::new(nextblock_client) }, - SwqosConfig::ZeroSlot(auth_token, region) => { - let endpoint = SwqosConfig::get_endpoint(SwqosType::ZeroSlot, region); + SwqosConfig::ZeroSlot(auth_token, region, url) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::ZeroSlot, region, url); let zeroslot_client = ZeroSlotClient::new( rpc_url.clone(), endpoint.to_string(), @@ -157,8 +161,8 @@ impl SwqosConfig { ); Arc::new(zeroslot_client) }, - SwqosConfig::Temporal(auth_token, region) => { - let endpoint = SwqosConfig::get_endpoint(SwqosType::Temporal, region); + SwqosConfig::Temporal(auth_token, region, url) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::Temporal, region, url); let temporal_client = TemporalClient::new( rpc_url.clone(), endpoint.to_string(), @@ -166,8 +170,8 @@ impl SwqosConfig { ); Arc::new(temporal_client) }, - SwqosConfig::Bloxroute(auth_token, region) => { - let endpoint = SwqosConfig::get_endpoint(SwqosType::Bloxroute, region); + SwqosConfig::Bloxroute(auth_token, region, url) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::Bloxroute, region, url); let bloxroute_client = BloxrouteClient::new( rpc_url.clone(), endpoint.to_string(), @@ -175,8 +179,8 @@ impl SwqosConfig { ); Arc::new(bloxroute_client) }, - SwqosConfig::Node1(auth_token, region) => { - let endpoint = SwqosConfig::get_endpoint(SwqosType::Node1, region); + SwqosConfig::Node1(auth_token, region, url) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::Node1, region, url); let node1_client = Node1Client::new( rpc_url.clone(), endpoint.to_string(), @@ -184,8 +188,8 @@ impl SwqosConfig { ); Arc::new(node1_client) }, - SwqosConfig::FlashBlock(auth_token, region) => { - let endpoint = SwqosConfig::get_endpoint(SwqosType::FlashBlock, region); + SwqosConfig::FlashBlock(auth_token, region, url) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::FlashBlock, region, url); let flashblock_client = FlashBlockClient::new( rpc_url.clone(), endpoint.to_string(), @@ -193,8 +197,8 @@ impl SwqosConfig { ); Arc::new(flashblock_client) }, - SwqosConfig::BlockRazor(auth_token, region) => { - let endpoint = SwqosConfig::get_endpoint(SwqosType::BlockRazor, region); + SwqosConfig::BlockRazor(auth_token, region, url) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::BlockRazor, region, url); let blockrazor_client = BlockRazorClient::new( rpc_url.clone(), endpoint.to_string(),