Error Handling
The Slipstream SDK uses a unified error type across all three languages.
SdkError Variants
| Variant | Description | Retryable |
|---|---|---|
Config | Invalid configuration | No |
Connection | Network/connection error | Yes |
Auth | Invalid or expired API key | No |
Protocol | Protocol-level error | Yes |
Transaction | Transaction processing error | No |
Timeout | Request timed out | Yes |
AllProtocolsFailed | All protocols in fallback chain failed | Yes |
RateLimited | Too many requests | Yes |
NotConnected | Client not connected | Yes |
StreamClosed | Stream subscription closed | Yes |
InsufficientTokens | Not enough tokens | No |
Internal | Internal server error | Yes |
Error Handling — Rust
1use allenhark_slipstream::SdkError;
2
3match client.submit_transaction(&tx_bytes).await {
4 Ok(result) => println!("Success: {:?}", result.signature),
5 Err(SdkError::Auth(msg)) => {
6 eprintln!("Authentication error: {} — check your API key", msg);
7 }
8 Err(SdkError::InsufficientTokens) => {
9 eprintln!("Not enough tokens — deposit SOL to continue");
10 let deposit = client.get_deposit_address().await?;
11 eprintln!("Deposit to: {:?}", deposit);
12 }
13 Err(SdkError::RateLimited(msg)) => {
14 eprintln!("Rate limited: {}", msg);
15 // SDK retries automatically based on config
16 }
17 Err(SdkError::Timeout(duration)) => {
18 eprintln!("Timed out after {:?}", duration);
19 }
20 Err(SdkError::AllProtocolsFailed) => {
21 eprintln!("All protocols failed — check network connectivity");
22 }
23 Err(SdkError::Connection(msg)) => {
24 eprintln!("Connection error: {}", msg);
25 // SDK will auto-reconnect on next call
26 }
27 Err(SdkError::NotConnected) => {
28 eprintln!("Not connected — reconnecting...");
29 }
30 Err(SdkError::StreamClosed) => {
31 eprintln!("Stream closed — resubscribe");
32 }
33 Err(e) => eprintln!("Unexpected error: {}", e),
34}Error Handling — TypeScript
1import { SlipstreamClient } from "@allenhark/slipstream";
2
3try {
4 const result = await client.submitTransaction(txBytes);
5 console.log("Success:", result.signature);
6} catch (err: any) {
7 switch (err.code) {
8 case "AUTH":
9 console.error("Auth error — check your API key");
10 break;
11 case "INSUFFICIENT_TOKENS":
12 console.error("Not enough tokens");
13 const deposit = await client.getDepositAddress();
14 console.error("Deposit to:", deposit);
15 break;
16 case "RATE_LIMITED":
17 console.error("Rate limited:", err.message);
18 break;
19 case "TIMEOUT":
20 console.error("Request timed out");
21 break;
22 case "ALL_PROTOCOLS_FAILED":
23 console.error("All protocols failed");
24 break;
25 case "CONNECTION":
26 console.error("Connection error:", err.message);
27 break;
28 case "NOT_CONNECTED":
29 console.error("Not connected");
30 break;
31 default:
32 console.error("Unexpected error:", err);
33 }
34}Error Handling — Python
1from allenhark_slipstream import SdkError
2
3try:
4 result = await client.submit_transaction(tx_bytes)
5 print(f"Success: {result.signature}")
6except SdkError as e:
7 if e.is_auth():
8 print(f"Auth error — check your API key: {e}")
9 elif e.is_insufficient_tokens():
10 print("Not enough tokens — deposit SOL")
11 elif e.is_rate_limited():
12 print(f"Rate limited: {e}")
13 elif e.is_timeout():
14 print("Request timed out")
15 elif e.is_connection():
16 print(f"Connection error: {e}")
17 else:
18 print(f"Error: {e}")Retry Configuration
The SDK has built-in retry logic with configurable backoff.
Config-Level Retries — Rust
1let config = Config::builder()
2 .api_key("sk_live_...")
3 .max_retries(3)
4 .retry_backoff(BackoffStrategy::Exponential)
5 .build()?;Per-Request Retries — Rust
1let result = client.submit_transaction_with_options(&tx_bytes, &SubmitOptions {
2 max_retries: 5,
3 retry: Some(RetryOptions {
4 max_retries: 5,
5 backoff_base_ms: 100,
6 cross_sender_retry: true, // Try a different sender on retry
7 }),
8 ..Default::default()
9}).await?;Backoff Strategies
| Strategy | Description |
|---|---|
Linear | Wait = base_ms * attempt |
Exponential | Wait = base_ms * 2^attempt (default) |
Connection Events
Monitor connection state changes.
Events — Rust
1println!("Connected: {}", client.is_connected());
2
3let info = client.connection_info();
4println!("Session: {}, Protocol: {:?}", info.session_id, info.protocol);Events — TypeScript
1client.on("connected", () => console.log("Connected!"));
2client.on("disconnected", () => console.log("Disconnected"));
3client.on("error", (err) => console.error("Error:", err));
4
5console.log("Connected:", client.isConnected());Events — Python
1@client.on("connected")
2async def on_connected():
3 print("Connected!")
4
5@client.on("disconnected")
6async def on_disconnected():
7 print("Disconnected")
8
9@client.on("error")
10async def on_error(err):
11 print(f"Error: {err}")Performance Metrics
Track success rates and latency.
Metrics — Rust
1let metrics = client.metrics();
2println!("Submitted: {}", metrics.transactions_submitted);
3println!("Confirmed: {}", metrics.transactions_confirmed);
4println!("Avg latency: {:.1}ms", metrics.average_latency_ms);
5println!("Success rate: {:.1}%", metrics.success_rate * 100.0);Metrics — TypeScript
1const metrics = client.metrics();
2console.log(`Success rate: ${(metrics.successRate * 100).toFixed(1)}%`);
3console.log(`Avg latency: ${metrics.averageLatencyMs.toFixed(1)}ms`);Next Steps
- Configuration — Timeout and retry settings
- Multi-Region — Region failover
- Webhooks — Error event notifications