sal-modular/sigsocket_client/IMPLEMENTATION.md
Sameh Abouel-saad 9f143ded9d Implement native and WASM WebSocket client for sigsocket communication
- Added `NativeClient` for non-WASM environments with automatic reconnection and message handling.
- Introduced `WasmClient` for WASM environments, supporting WebSocket communication and reconnection logic.
- Created protocol definitions for `SignRequest` and `SignResponse` with serialization and deserialization.
- Developed integration tests for the client functionality and sign request handling.
- Implemented WASM-specific tests to ensure compatibility and functionality in browser environments.
2025-06-04 13:03:15 +03:00

6.3 KiB

SigSocket Client Implementation

Overview

This document describes the implementation of the sigsocket_client crate, a WebSocket client library designed for connecting to sigsocket servers with WASM-first support.

Architecture

Core Design Principles

  1. WASM-First: Designed primarily for browser environments with native support as a secondary target
  2. No Signing Logic: The client delegates all signing operations to the application
  3. User Approval Flow: Applications are notified about incoming requests and handle user approval
  4. Protocol Compatibility: Fully compatible with the sigsocket server protocol
  5. Async/Await: Modern async Rust API throughout

Module Structure

sigsocket_client/
├── src/
│   ├── lib.rs           # Main library entry point
│   ├── error.rs         # Error types (native + WASM versions)
│   ├── protocol.rs      # Protocol message definitions
│   ├── client.rs        # Main client interface
│   ├── native.rs        # Native (tokio) implementation
│   └── wasm.rs          # WASM (web-sys) implementation
├── examples/
│   ├── basic_usage.rs   # Native usage example
│   └── wasm_usage.rs    # WASM usage example
├── tests/
│   └── integration_test.rs
└── README.md

Protocol Implementation

The sigsocket protocol is simple and consists of three message types:

1. Introduction Message

When connecting, the client sends its public key as a hex-encoded string:

02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9

2. Sign Request (Server → Client)

{
  "id": "req_123",
  "message": "dGVzdCBtZXNzYWdl"  // base64-encoded message
}

3. Sign Response (Client → Server)

{
  "id": "req_123",
  "message": "dGVzdCBtZXNzYWdl",  // original message
  "signature": "c2lnbmF0dXJl"      // base64-encoded signature
}

Key Features Implemented

Dual Platform Support

  • Native: Uses tokio and tokio-tungstenite for async WebSocket communication
  • WASM: Uses web-sys and wasm-bindgen for browser WebSocket API

Type-Safe Protocol

  • SignRequest and SignResponse structs with serde serialization
  • Helper methods for base64 encoding/decoding
  • Comprehensive error handling

Flexible Sign Handler Interface

trait SignRequestHandler {
    fn handle_sign_request(&self, request: &SignRequest) -> Result<Vec<u8>>;
}

Connection Management

  • Automatic connection state tracking
  • Clean disconnect handling
  • Connection status queries

Error Handling

  • Comprehensive error types for different failure modes
  • Platform-specific error conversions
  • WASM-compatible error handling (no std::error::Error dependency)

Platform-Specific Implementations

Native Implementation (native.rs)

  • Uses tokio-tungstenite for WebSocket communication
  • Spawns separate tasks for reading and writing
  • Thread-safe with Arc<RwLock<T>> for shared state
  • Supports Send + Sync trait bounds

WASM Implementation (wasm.rs)

  • Uses web-sys::WebSocket for browser WebSocket API
  • Event-driven with JavaScript closures
  • Single-threaded (no Send + Sync requirements)
  • Browser console logging for debugging

Usage Patterns

Native Usage

#[tokio::main]
async fn main() -> Result<()> {
    let public_key = hex::decode("02f9308a...")?;
    let mut client = SigSocketClient::new("ws://localhost:8080/ws", public_key)?;
    
    client.set_sign_handler(MySignHandler);
    client.connect().await?;
    
    // Client handles requests automatically
    Ok(())
}

WASM Usage

#[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)?;
    
    client.set_sign_handler(WasmSignHandler);
    client.connect().await?;
    
    Ok(())
}

Testing

Unit Tests

  • Protocol message serialization/deserialization
  • Error handling and conversion
  • Client creation and configuration

Integration Tests

  • End-to-end usage patterns
  • Sign request/response cycles
  • Error scenarios

Documentation Tests

  • Example code in documentation is verified to compile

Dependencies

Core Dependencies (Both Platforms)

  • serde + serde_json - JSON serialization
  • hex - Hex encoding/decoding
  • base64 - Base64 encoding/decoding
  • url - URL parsing and validation

Native-Only Dependencies

  • tokio - Async runtime
  • tokio-tungstenite - WebSocket client
  • futures-util - Stream utilities
  • thiserror - Error derive macros

WASM-Only Dependencies

  • wasm-bindgen - Rust/JavaScript interop
  • web-sys - Browser API bindings
  • js-sys - JavaScript type bindings
  • wasm-bindgen-futures - Async support

Build Targets

Native Build

cargo build --features native
cargo test --features native
cargo run --example basic_usage --features native

WASM Build

cargo check --target wasm32-unknown-unknown --features wasm
wasm-pack build --target web --features wasm

Future Enhancements

Potential Improvements

  1. Reconnection Logic: Automatic reconnection with exponential backoff
  2. Request Queuing: Queue multiple concurrent sign requests
  3. Timeout Handling: Configurable timeouts for requests
  4. Metrics: Connection and request metrics
  5. Logging: Structured logging with configurable levels

WASM Enhancements

  1. Better Callback System: More ergonomic callback handling in WASM
  2. Browser Wallet Integration: Direct integration with MetaMask, etc.
  3. Service Worker Support: Background request handling

Security Considerations

  1. No Private Key Storage: The client never handles private keys
  2. User Approval Required: All signing requires explicit user approval
  3. Message Validation: All incoming messages are validated
  4. Secure Transport: Requires WebSocket Secure (WSS) in production

Compatibility

  • Rust Version: 1.70+
  • WASM Target: wasm32-unknown-unknown
  • Browser Support: Modern browsers with WebSocket support
  • Server Compatibility: Compatible with sigsocket server protocol

This implementation provides a solid foundation for applications that need to connect to sigsocket servers while maintaining security and user control over signing operations.