94 lines
5.0 KiB
Markdown
94 lines
5.0 KiB
Markdown
# `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:
|
|
|
|
```mermaid
|
|
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. |