titan_client/
lib.rs

1mod error;
2mod http;
3mod tcp;
4
5pub use error::*;
6
7pub use http::{
8    AsyncClient as TitanClient, SyncClient as TitanBlockingClient, TitanApiAsync as TitanApi,
9    TitanApiSync as TitanApiBlocking,
10};
11pub use tcp::{ConnectionStatus, ConnectionStatusTracker};
12pub use tcp::{ReconnectionConfig, ReconnectionManager};
13pub use titan_types_api::*;
14pub use titan_types_core::*;
15
16#[cfg(feature = "tcp_client")]
17pub use tcp::{TitanTcpClient, TitanTcpClientConfig, TitanTcpClientError};
18
19#[cfg(feature = "tcp_client_blocking")]
20pub use tcp::{TitanTcpClientBlocking, TitanTcpClientBlockingConfig, TitanTcpClientBlockingError};
21
22#[cfg(test)]
23mod tests {
24    use super::*;
25    use std::error::Error;
26    use titan_types_api::TcpSubscriptionRequest;
27    use tokio::time::{Duration, Instant};
28
29    // Import the HTTP and TCP client functions.
30    use crate::http::TitanApiAsync as TitanApi;
31    #[cfg(feature = "tcp_client")]
32    use crate::tcp::TitanTcpClient;
33
34    /// End-to-end test for the TCP subscription client.
35    ///
36    /// This test:
37    /// 1. Connects to the TCP subscription server at localhost:8080,
38    ///    subscribing to "TransactionsAdded", "TransactionsReplaced", and "NewBlock".
39    /// 2. Listens for events for 10 seconds, printing each received event.
40    /// 3. Then signals shutdown.
41    #[tokio::test]
42    #[cfg(feature = "tcp_client")]
43    async fn test_tcp_subscription_e2e() -> Result<(), Box<dyn Error>> {
44        use tokio::time::timeout;
45
46        let tcp_addr = "127.0.0.1:8080";
47        let subscription_request = TcpSubscriptionRequest {
48            subscribe: vec![
49                EventType::TransactionsAdded,
50                EventType::TransactionsReplaced,
51                EventType::NewBlock,
52            ],
53        };
54
55        // Connect to the TCP server and subscribe.
56        let client = TitanTcpClient::new();
57        let mut rx = client.subscribe(tcp_addr, subscription_request).await?;
58
59        println!("Connected to TCP subscription server at {}.", tcp_addr);
60
61        // Listen for events for 10 seconds.
62        let listen_duration = Duration::from_secs(10);
63        let start = Instant::now();
64        let mut events = Vec::new();
65        while Instant::now().duration_since(start) < listen_duration {
66            match timeout(Duration::from_millis(500), rx.recv()).await {
67                Ok(Some(event)) => {
68                    // We got an event
69                    println!("Received TCP event: {:?}", event);
70                    events.push(event);
71                }
72                Ok(None) => {
73                    // The sender side or the connection closed
74                    println!("TCP subscription channel closed. Stopping early.");
75                    break;
76                }
77                Err(_) => {
78                    // Timed out waiting for an event
79                    // This means no event arrived in the last 500 ms, but we can keep waiting until 10s is up
80                }
81            }
82        }
83        println!("Total events received in 10 seconds: {}", events.len());
84
85        // Signal shutdown to the subscription task.
86        client.shutdown();
87        println!("Shutdown signal sent to TCP subscription task.");
88
89        Ok(())
90    }
91
92    /// End-to-end test for the HTTP client.
93    ///
94    /// This test:
95    /// 1. Connects to the HTTP server at http://localhost:3030.
96    /// 2. Retrieves and prints the block status and tip.
97    #[tokio::test]
98    async fn test_http_status_tip_e2e() -> Result<(), Box<dyn Error>> {
99        let base_url = "http://localhost:3030";
100        let client = TitanClient::new(base_url);
101
102        println!("Fetching HTTP status from {}...", base_url);
103        match client.get_status().await {
104            Ok(status) => {
105                println!("HTTP Status: {:?}", status);
106            }
107            Err(e) => {
108                eprintln!("Failed to get HTTP status: {}", e);
109            }
110        }
111
112        println!("Fetching block tip from {}...", base_url);
113        match client.get_tip().await {
114            Ok(tip) => {
115                println!("Block Tip: {:?}", tip);
116            }
117            Err(e) => {
118                eprintln!("Failed to get block tip: {}", e);
119            }
120        }
121
122        Ok(())
123    }
124}