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
use sigsocket_client::{SigSocketClient, SignRequestHandler, SignRequest, Result};
struct MySignHandler;
impl SignRequestHandler for MySignHandler {
    fn handle_sign_request(&self, request: &SignRequest) -> Result<Vec<u8>> {
        // 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
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<Vec<u8>> {
        // 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:
{
  "id": "req_123",
  "message": "dGVzdCBtZXNzYWdl"  // base64-encoded message
}
3. Sign Responses
The client responds with signatures as 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.
trait SignRequestHandler {
    fn handle_sign_request(&self, request: &SignRequest) -> Result<Vec<u8>>;
}
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:
cargo run --example basic_usage
Building
Native Build
cargo build
cargo test
cargo run --example basic_usage
WASM Build
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