# SigSocket Client A WebSocket client library for connecting to sigsocket servers with **WASM-first support**. ## Features - 🌐 **WASM-first design**: Optimized for browser environments - 🖥️ **Native support**: Works in native Rust applications - 🔐 **No signing logic**: Delegates signing to the application - 👤 **User approval flow**: Notifies applications about incoming requests - 🔌 **sigsocket compatible**: Fully compatible with sigsocket server protocol - 🚀 **Async/await**: Modern async Rust API - 🔄 **Automatic reconnection**: Both platforms support reconnection with exponential backoff - ⏱️ **Connection timeouts**: Proper timeout handling and connection management - 🛡️ **Production ready**: Comprehensive error handling and reliability features ## Quick Start ### Native Usage ```rust use sigsocket_client::{SigSocketClient, SignRequestHandler, SignRequest, Result}; struct MySignHandler; impl SignRequestHandler for MySignHandler { fn handle_sign_request(&self, request: &SignRequest) -> Result> { // 1. Present request to user println!("Sign request: {}", request.message); // 2. Get user approval // ... your UI logic here ... // 3. Sign the message (using your signing logic) let signature = your_signing_function(&request.message_bytes()?)?; Ok(signature) } } #[tokio::main] async fn main() -> Result<()> { // Your public key bytes let public_key = hex::decode("02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388")?; // Create and configure client let mut client = SigSocketClient::new("ws://localhost:8080/ws", public_key)?; client.set_sign_handler(MySignHandler); // Connect and handle requests client.connect().await?; // Client will automatically handle incoming signature requests // Keep the connection alive... Ok(()) } ``` ### WASM Usage ```rust use sigsocket_client::{SigSocketClient, SignRequestHandler, SignRequest, Result}; use wasm_bindgen::prelude::*; struct WasmSignHandler; impl SignRequestHandler for WasmSignHandler { fn handle_sign_request(&self, request: &SignRequest) -> Result> { // Show request to user in browser web_sys::window() .unwrap() .alert_with_message(&format!("Sign request: {}", request.id)) .unwrap(); // Your signing logic here... let signature = sign_with_browser_wallet(&request.message_bytes()?)?; Ok(signature) } } #[wasm_bindgen] pub async fn connect_to_sigsocket() -> Result<(), JsValue> { let public_key = get_user_public_key()?; let mut client = SigSocketClient::new("ws://localhost:8080/ws", public_key) .map_err(|e| JsValue::from_str(&e.to_string()))?; client.set_sign_handler(WasmSignHandler); client.connect().await .map_err(|e| JsValue::from_str(&e.to_string()))?; Ok(()) } ``` ## Protocol The sigsocket client implements a simple WebSocket protocol: ### 1. Introduction Upon connection, the client sends its public key as a hex-encoded string: ``` 02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388 ``` ### 2. Sign Requests The server sends signature requests as JSON: ```json { "id": "req_123", "message": "dGVzdCBtZXNzYWdl" // base64-encoded message } ``` ### 3. Sign Responses The client responds with signatures as JSON: ```json { "id": "req_123", "message": "dGVzdCBtZXNzYWdl", // original message "signature": "c2lnbmF0dXJl" // base64-encoded signature } ``` ## API Reference ### `SigSocketClient` Main client for connecting to sigsocket servers. #### Methods - `new(url, public_key)` - Create a new client - `set_sign_handler(handler)` - Set the signature request handler - `connect()` - Connect to the server with automatic reconnection - `disconnect()` - Disconnect from the server - `send_sign_response(response)` - Manually send a signature response - `state()` - Get current connection state - `is_connected()` - Check if connected #### Reconnection Configuration (WASM only) - `set_auto_reconnect(enabled)` - Enable/disable automatic reconnection - `set_reconnect_config(max_attempts, initial_delay_ms)` - Configure reconnection parameters **Default settings:** - Max attempts: 5 - Initial delay: 1000ms (with exponential backoff: 1s, 2s, 4s, 8s, 16s) - Auto-reconnect: enabled ### `SignRequestHandler` Trait Implement this trait to handle incoming signature requests. ```rust trait SignRequestHandler { fn handle_sign_request(&self, request: &SignRequest) -> Result>; } ``` ### `SignRequest` Represents a signature request from the server. #### Fields - `id: String` - Unique request identifier - `message: String` - Base64-encoded message to sign #### Methods - `message_bytes()` - Decode message to bytes - `message_hex()` - Get message as hex string ### `SignResponse` Represents a signature response to send to the server. #### Methods - `new(id, message, signature)` - Create a new response - `from_request_and_signature(request, signature)` - Create from request and signature bytes ## Examples Run the basic example: ```bash cargo run --example basic_usage ``` ## Building ### Native Build ```bash cargo build cargo test cargo run --example basic_usage ``` ### WASM Build ```bash wasm-pack build --target web wasm-pack test --headless --firefox # Run WASM tests ``` ## Requirements ### Native - Rust 1.70+ - tokio runtime ### WASM - wasm-pack - Modern browser with WebSocket support ## License MIT OR Apache-2.0