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"
): Thetokio-tungstenite
crate is used for robust,tokio
-based WebSocket communication. - WebAssembly (
target_arch = "wasm32"
): Thegloo-net
crate provides bindings to the browser's nativeWebSocket
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 theCircleWsClientBuilder
andCircleWsClient
structs and their public APIs. It orchestrates the entire communication flow.auth/
: This module contains all the logic related to thesecp256k1
authentication flow.types.rs
: Defines the core data structures used in authentication, such asAuthError
andAuthCredentials
.crypto_utils.rs
: A self-contained utility module for handling allsecp256k1
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.