Concepts & Architecture
This chapter explains how the SDK fits together: what powers BaseSealClient,
how the ready-made specializations behave, and which operational details matter
when you run the client in production.
BaseSealClient
BaseSealClient (see src/base_client.rs) is the generic core. It exposes six
type parameters that let you decide which pieces to plug in:
- key-server info cache implementation
- derived-keys cache implementation
- Sui RPC error type
- Sui client implementation
- HTTP error type
- HTTP client implementation
You can supply any types that implement the required traits:
SealCachedefines a simple async cache API.SuiClientoutlines the Sui RPC calls the client needs.HttpClientasks for a singlepostmethod to talk to Seal key servers.
Because the generics stay abstract, you can swap components without editing the rest of the crate—use a mock HTTP client in tests, replace the cache with a shared service, or point to a different Sui SDK version.
Specializations
src/native_sui_sdk/client offers ready-to-use type aliases:
SealClientusessui_sdk::SuiClient,reqwest::Client, and theNoCacheadapters. Theclientandnative-sui-sdkfeatures enable it by default.SealClientLeakingCacheaddsArc<Mutex<HashMap<...>>>caches. These caches never evict, so use them only for short-lived tools.SealClientMokaCache(behind themoka-clientfeature) relies onmoka::future::Cache, giving you configurable eviction for long-lived services.
If you need something else, create your own alias that wires the right HTTP
client, Sui client, and caches into BaseSealClient.
Caching strategies
Caching is optional but useful. The client can cache two kinds of data:
- key-server metadata fetched from Sui
- derived keys fetched from the Seal servers
NoCache skips caching. The HashMap and moka adapters show how to keep
results in memory. To integrate a different cache (Redis, a database, etc.),
implement SealCache.
Session keys (JWT analogy)
SessionKey lives in src/session_key.rs. Instead of signing every decrypt
request with a wallet, you sign once to mint a short-lived key. Think of it like
a JWT:
- A signer that implements
Signercreates the session key. - During the TTL window, decrypt calls use that key without asking the wallet again.
Handle the session key like a bearer token: keep it safe in memory and drop it when you no longer need it.
Independent and committee key servers
Seal key servers come in two flavors. An independent server holds the full master secret and serves key requests directly. A committee distributes the secret across multiple participants via threshold cryptography; an aggregator collects partial responses and returns the combined result.
The ServerType enum lets you tell the two apart programmatically:
use seal_sdk_rs::base_client::ServerType;
match &info.server_type {
ServerType::Independent { url } => { /* server URL is available */ }
ServerType::Committee { .. } => { /* needs an external aggregator URL */ }
}
You can retrieve a key server’s metadata (name, public key, server type) at any
time with get_key_server_info:
let info = client.get_key_server_info(key_server_id).await?;
println!("name: {}, type: {:?}", info.name, info.server_type);
For encryption and decryption, the SDK handles both types transparently through
KeyServerConfig. Pass aggregator_url: None for independent servers and
aggregator_url: Some(url) for committees. During decryption, provide a
HashMap<ObjectID, String> mapping committee key server IDs to their aggregator
URLs. See the Committee Servers chapter for details
and examples.
Recovery keys and operational security
Every encrypt helper returns (EncryptedObject, [u8; 32]). The second value is
an emergency recovery key. Store it if you want a break-glass option when key
servers go offline. Drop it if you never want a single authority to decrypt all
payloads without the key-server quorum.
Supported Sui SDKs and bridging types
Today you can choose between two Sui SDK families:
MystenLabs/suiis mature but heavy. It pulls in a large dependency graph and build toolchain.MystenLabs/sui-rust-sdkis lightweight but still experimental.
seal-sdk-rs already bridges both worlds. src/generic_types.rs defines
ObjectID and SuiAddress, and the
BCSSerializableProgrammableTransaction trait hides differences between the SDKs.
Conversions run in both directions and all types support serde.
The built-in specializations (SealClient, SealClientLeakingCache,
SealClientMokaCache) currently target MystenLabs/sui and use JSON-RPC. gRPC
support is on the roadmap because the JSON-RPC endpoints have started their
phase-out. When the lightweight SDK stabilizes, new specializations can land
without changing the overall design.
Feature flags overview
Cargo.toml exposes several public features:
default=client,native-tls,native-sui-sdkclientenables the HTTP layer (reqwest+http).native-tlsswitchesreqwestto native TLS. Disable it if you want to opt intorustlsmanually.native-sui-sdkpulls insui_sdk,sui_types,sui_keys, andshared_crypto, plus the Sui-specific adapters.moka-clientadds themokacache specialization.
Disable the defaults if you want to bring your own implementations and re-enable only the pieces you need.