hero/interfaces/websocket/client/ARCHITECTURE.md
2025-07-29 01:15:23 +02:00

5.0 KiB

client_ws Architecture

This document details the internal architecture of the client_ws crate, focusing on its cross-platform design, internal modules, and the mechanics of its authentication process.

1. Core Design Principles

The client_ws is built on the following principles:

  • Platform Abstraction: The core client logic is written in a platform-agnostic way. Platform-specific details (like the WebSocket implementation) are abstracted behind a common interface.
  • Modularity: The crate is divided into logical modules, with a clear separation of concerns between the main client logic, authentication procedures, and cryptographic utilities.
  • Asynchronous Operations: All network I/O is asynchronous, using async/await to ensure the client is non-blocking and efficient.
  • Fluent Configuration: A builder pattern (CircleWsClientBuilder) is used for clear and flexible client construction.
  • Self-Managing Clients: Each CircleWsClient handles its own lifecycle including connection, authentication, keep-alive, and reconnection logic internally.

2. Cross-Platform Implementation

To support both native and WebAssembly (WASM) environments, client_ws uses conditional compilation (#[cfg]) to provide different implementations for the underlying WebSocket transport.

  • Native (target_arch != "wasm32"): The tokio-tungstenite crate is used for robust, tokio-based WebSocket communication.
  • WebAssembly (target_arch = "wasm32"): The gloo-net crate provides bindings to the browser's native WebSocket API.

This approach allows the CircleWsClient to expose a single, unified API while the underlying implementation details are handled transparently at compile time.

3. Module Structure

The client_ws crate is organized into the following key modules:

  • lib.rs: The main module that defines the CircleWsClientBuilder and CircleWsClient structs and their public APIs. It orchestrates the entire communication flow.
  • auth/: This module contains all the logic related to the secp256k1 authentication flow.
    • types.rs: Defines the core data structures used in authentication, such as AuthError and AuthCredentials.
    • crypto_utils.rs: A self-contained utility module for handling all secp256k1 cryptographic operations, including key generation, public key derivation, and message signing.

4. Self-Managing Client Architecture

Each CircleWsClient is designed to be completely self-managing, handling its entire lifecycle internally. This includes:

  • Connection Management: Establishing and maintaining WebSocket connections
  • Authentication: Automatic secp256k1 authentication flow when private keys are provided
  • Keep-Alive: Periodic health checks to ensure connection stability
  • Reconnection: Automatic reconnection with exponential backoff on connection failures
  • Connection Status Tracking: Internal state management for connection health

Connection Flow

The connect() method orchestrates the complete connection and authentication process:

sequenceDiagram
    participant User as User Code
    participant Builder as CircleWsClientBuilder
    participant Client as CircleWsClient
    participant CryptoUtils as auth::crypto_utils
    participant WsActor as Server WebSocket Actor

    User->>+Builder: new(url)
    User->>+Builder: with_keypair(private_key)
    User->>+Builder: build()
    Builder-->>-User: client

    User->>+Client: connect()
    
    Note over Client: Self-managing connection process
    Client->>Client: Establish WebSocket connection
    Client->>Client: Start keep-alive loop
    Client->>Client: Start reconnection handler
    
    alt Has Private Key
        Client->>Client: Check for private_key
        Client->>+CryptoUtils: derive_public_key(private_key)
        CryptoUtils-->>-Client: public_key

        Note over Client: Request nonce via WebSocket
        Client->>+WsActor: JSON-RPC "fetch_nonce" (pubkey)
        WsActor-->>-Client: JSON-RPC Response (nonce)

        Client->>+CryptoUtils: sign_message(private_key, nonce)
        CryptoUtils-->>-Client: signature

        Note over Client: Send credentials via WebSocket
        Client->>+WsActor: JSON-RPC "authenticate" (pubkey, signature)
        WsActor-->>-Client: JSON-RPC Response (authenticated: true/false)
    end
    
    Client-->>-User: Connection established and authenticated

Self-Management Features

  • Automatic Keep-Alive: Each client runs its own keep-alive loop to detect connection issues
  • Transparent Reconnection: Failed connections are automatically retried with exponential backoff
  • Status Monitoring: Connection status is tracked internally and can be queried via is_connected()
  • Resource Cleanup: Proper cleanup of resources when clients are dropped

This architecture ensures that the cryptographic operations are isolated, the platform-specific code is cleanly separated, and each client is completely autonomous in managing its connection lifecycle.