Expand description
§Affinidi Trusted Messaging SDK
The Affinidi Trusted Messaging (ATM) SDK provides a high-level interface for DIDComm v2 messaging through a mediator service. It handles message encryption, signing, routing, and transport so you can focus on building your application.
§Key Concepts
ATM- The main entry point. Holds configuration, profiles, and manages background tasks (e.g. message deletion).profiles::ATMProfile- Represents a DID identity with an associated mediator. Each profile can independently send and receive messages.- Mediator - A service that stores and forwards DIDComm messages on behalf of your profile. Discovered automatically from the mediator’s DID Document.
protocols::Protocols- Pre-built DIDComm protocol implementations (Trust Ping, Message Pickup 3.0, Routing 2.0, etc.).- Transports - The SDK supports both REST (HTTPS) and WebSocket (WSS) transports. REST is used for authentication and bulk operations; WebSocket enables low-latency sending and live message streaming.
§Getting Started
§1. Initialize the TDK shared state
The SDK builds on top of affinidi-tdk-common which manages DID resolution
and secrets. You need a TDKSharedState instance first:
use affinidi_tdk::common::{TDKSharedState, environments::TDKEnvironments};
use std::sync::Arc;
// Load environment configuration (DIDs, secrets, mediator endpoints)
let mut environment = TDKEnvironments::fetch_from_file(
Some("environments.json"),
"default",
)?;
let tdk = Arc::new(TDKSharedState::default().await);§2. Build an ATM configuration and create the SDK instance
Use config::ATMConfig::builder() to configure the SDK, then pass it to
ATM::new():
use affinidi_messaging_sdk::{ATM, config::ATMConfig};
let config = ATMConfig::builder()
// Add custom SSL/TLS certificates if the mediator uses self-signed certs
.with_ssl_certificates(&mut environment.ssl_certificates)
// Optional: tune the per-profile message fetch cache
.with_fetch_cache_limit_count(100)
.with_fetch_cache_limit_bytes(10 * 1024 * 1024)
.build()?;
let atm = ATM::new(config, tdk).await?;§3. Register a profile
A profile ties a DID to a mediator. Add it to both the TDK (for secrets/DID resolution) and the ATM SDK:
use affinidi_messaging_sdk::profiles::ATMProfile;
// Get a profile from your environment configuration
let alice_tdk = environment.profiles.get("Alice").unwrap();
tdk.add_profile(alice_tdk).await;
// Convert and register with ATM (live_stream=false means no WebSocket yet)
let alice = atm
.profile_add(
&ATMProfile::from_tdk_profile(&atm, alice_tdk).await?,
false,
)
.await?;§4. Send a message (REST)
The simplest way to verify connectivity is a DIDComm Trust Ping:
// Send a signed trust-ping, requesting a pong response
let ping = atm
.trust_ping()
.send_ping(
&alice, // sender profile
&target_did, // recipient DID
true, // signed
true, // request pong response
false, // don't block waiting for response
)
.await?;§5. Retrieve and unpack messages
After sending a message that produces a response, fetch and decrypt it:
use affinidi_messaging_sdk::messages::GetMessagesRequest;
let response = atm
.get_messages(
&alice,
&GetMessagesRequest {
message_ids: vec![msg_id],
delete: true, // delete after retrieval
},
)
.await?;
for msg in response.success {
let (message, metadata) = atm.unpack(&msg.msg.unwrap()).await?;
println!("Received: {:?}", message);
}§6. Upgrade to WebSocket for live streaming
For lower latency and push-based message delivery, enable the WebSocket transport on a profile:
use std::time::Duration;
// Open a WebSocket connection to the mediator
atm.profile_enable_websocket(&alice).await?;
// Send a ping (now routed over WebSocket automatically)
let ping = atm
.trust_ping()
.send_ping(&alice, &target_did, true, true, false)
.await?;
// Wait for the pong via the live stream
let pong = atm
.message_pickup()
.live_stream_get(
&alice,
&ping.message_id,
Duration::from_secs(10),
true, // auto-delete
)
.await?;§7. Graceful shutdown
Always shut down cleanly to close WebSocket connections and stop background tasks:
atm.graceful_shutdown().await;§Module Overview
| Module | Description |
|---|---|
config | SDK configuration via the builder pattern (config::ATMConfig) |
profiles | DID profile and mediator management (profiles::ATMProfile) |
messages | Pack, unpack, send, list, get, fetch, and delete DIDComm messages |
protocols | Higher-level DIDComm protocol implementations (Trust Ping, Message Pickup, Routing) |
transports | REST and WebSocket transport layer |
errors | Error types (errors::ATMError) |
delete_handler | Background message deletion task |
public | Public utility functions (e.g. well-known DID resolution) |
§Debug Logging
Enable SDK debug logs via the RUST_LOG environment variable:
export RUST_LOG=none,affinidi_messaging_sdk=debugRe-exports§
pub use transport_adapter::DidCommTransport;pub use tsp_wire::TSP_MAGIC_BYTE;pub use tsp_wire::looks_like_tsp;
Modules§
- config
- delete_
handler - This module contains the implementation of the delete handler.
- errors
- messages
- profiles
- Profiles modules contains the implementation of the Profile struct and its methods.
- protocols
- This module contains the implementation of the DIDComm protocols supported by the SDK.
- public
- transport_
adapter DidCommTransport— aMessageTransportover the DIDComm ATM wire.- transports
- tsp_
wire - Classifying a TSP frame without the
tspfeature.