diff --git a/documentation/docs/components/crates-paused.tsx b/documentation/docs/components/version-banner.tsx similarity index 92% rename from documentation/docs/components/crates-paused.tsx rename to documentation/docs/components/version-banner.tsx index aee3411536..26b14d6e5b 100644 --- a/documentation/docs/components/crates-paused.tsx +++ b/documentation/docs/components/version-banner.tsx @@ -3,7 +3,7 @@ import { NYM_SDK_VERSION } from "./versions"; const INSTALL_PATH = "/developers/rust/importing"; -export const CratesPaused = () => ( +export const VersionBanner = () => ( Code examples target v{NYM_SDK_VERSION} of the Nym crates on{" "} diff --git a/documentation/docs/components/versions.ts b/documentation/docs/components/versions.ts index 61ef36b788..9eee7a4a54 100644 --- a/documentation/docs/components/versions.ts +++ b/documentation/docs/components/versions.ts @@ -1,7 +1,7 @@ /** * Centralised version constants for documentation. * - * Components (CratesPaused, CodeVerified, etc.) import from here so there is a + * Components (VersionBanner, CodeVerified, etc.) import from here so there is a * single place to update on each release. * * Fenced code blocks still hardcode versions for copy-paste friendliness. diff --git a/documentation/docs/pages/developers/browsers.mdx b/documentation/docs/pages/developers/browsers.mdx index e6df607b26..7d1ed7e939 100644 --- a/documentation/docs/pages/developers/browsers.mdx +++ b/documentation/docs/pages/developers/browsers.mdx @@ -18,8 +18,8 @@ Two integration options are available, both delivered as packages bundled into y | Module | What it does | Links | |---|---|---| -| **mixFetch** | Drop-in `fetch` replacement — HTTP(S) requests via Exit Gateways with an embedded CA store for browser-to-destination TLS over the Mixnet | [docs](./typescript#mixfetch) · [example](./typescript/playground/mixfetch) | -| **WASM Client** | Sphinx packets and cover traffic in WASM, sent over WebSocket to the Entry Gateway — messaging mode only (text/binary payloads), runs in a web worker | [docs](./typescript#mixnet-client) · [example](./typescript/playground/traffic) | +| **mixFetch** | Drop-in `fetch` replacement — HTTP(S) requests via Exit Gateways with an embedded CA store for browser-to-destination TLS over the Mixnet | [docs](/developers/typescript#mixfetch) · [example](/developers/typescript/playground/mixfetch) | +| **WASM Client** | Sphinx packets and cover traffic in WASM, sent over WebSocket to the Entry Gateway — messaging mode only (text/binary payloads), runs in a web worker | [docs](/developers/typescript#mixnet-client) · [example](/developers/typescript/playground/traffic) | `mixFetch` currently supports a maximum of 10 concurrent in-flight requests. `mixFetchv2`, which will function as a general-purpose userspace IP stack, is in development. diff --git a/documentation/docs/pages/developers/native.mdx b/documentation/docs/pages/developers/native.mdx index f44f9175f8..d2edd8e1ab 100644 --- a/documentation/docs/pages/developers/native.mdx +++ b/documentation/docs/pages/developers/native.mdx @@ -19,13 +19,13 @@ Both sides of your app run Nym clients. All traffic stays Sphinx-encrypted the e | SDK Module | What it does | Status | Links | |---|---|---|---| -| **Stream** | `AsyncRead + AsyncWrite` byte streams multiplexed over the mixnet — the closest analogue to TCP sockets | Recommended | [docs](./rust/stream) · [tutorial](./rust/stream/tutorial) | -| **Mixnet** | Raw message API and `MixnetClient` — full control over the communication model | Stable | [docs](./rust/mixnet) · [tutorial](./rust/mixnet/tutorial) | -| **Client Pool** | Pre-connected client pool for bursty workloads | Stable | [docs](./rust/client-pool) | -| **TcpProxy** | Localhost TCP sockets that proxy traffic through the mixnet | Unmaintained | [docs](./rust/tcpproxy) | +| **Stream** | `AsyncRead + AsyncWrite` byte streams multiplexed over the mixnet — the closest analogue to TCP sockets | Recommended | [docs](/developers/rust/stream) · [tutorial](/developers/rust/stream/tutorial) | +| **Mixnet** | Raw message API and `MixnetClient` — full control over the communication model | Stable | [docs](/developers/rust/mixnet) · [tutorial](/developers/rust/mixnet/tutorial) | +| **Client Pool** | Pre-connected client pool for bursty workloads | Stable | [docs](/developers/rust/client-pool) | +| **TcpProxy** | Localhost TCP sockets that proxy traffic through the mixnet | Unmaintained | [docs](/developers/rust/tcpproxy) | -**TcpProxy is unmaintained.** Use the [Stream module](./rust/stream) for new projects. +**TcpProxy is unmaintained.** Use the [Stream module](/developers/rust/stream) for new projects. ## Mixnet-As-Proxy @@ -39,8 +39,8 @@ Traffic is Sphinx-encrypted until the Exit Gateway, where it's unwrapped into HT | Standalone Crate | What it does | Links | |---|---|---| -| **`smolmix`** | Userspace IP tunnel — `TcpStream` and `UdpSocket` over the mixnet, compatible with the entire async Rust ecosystem. Also serves as the core for companion crates that plug into specific frameworks (e.g. hyper connectors, DNS resolvers) | [docs](./smolmix) | +| **`smolmix`** | Userspace IP tunnel — `TcpStream` and `UdpSocket` over the mixnet, compatible with the entire async Rust ecosystem. Also serves as the core for companion crates that plug into specific frameworks (e.g. hyper connectors, DNS resolvers) | [docs](/developers/smolmix) | | SDK Module | What it does | Links | |---|---|---| -| **SOCKS Client** | SOCKS4/4a/5 proxy via the Exit Gateway's Network Requester — works with any SOCKS-capable application without code changes, just point it at the local proxy | [docs](./rust/mixnet) | +| **SOCKS Client** | SOCKS4/4a/5 proxy via the Exit Gateway's Network Requester — works with any SOCKS-capable application without code changes, just point it at the local proxy | [docs](/developers/rust/mixnet) | diff --git a/documentation/docs/pages/developers/rust.mdx b/documentation/docs/pages/developers/rust.mdx index 93affb53ae..0598c40aa8 100644 --- a/documentation/docs/pages/developers/rust.mdx +++ b/documentation/docs/pages/developers/rust.mdx @@ -9,7 +9,7 @@ lastUpdated: "2026-03-13" # Rust SDK import { Callout } from 'nextra/components' -import { CratesPaused } from '../../components/crates-paused' +import { VersionBanner } from '../../components/version-banner' All modules share a common `MixnetClient` that manages gateway connections, Sphinx packet encryption, routing, and cover traffic. @@ -17,7 +17,7 @@ All modules share a common `MixnetClient` that manages gateway connections, Sphi Full API reference: [**docs.rs/nym-sdk**](https://docs.rs/nym-sdk/latest/nym_sdk/) - + For an overview of what the SDK can do, see the **[Tour](./rust/tour)**. For setup instructions, see [Installation](./rust/importing). diff --git a/documentation/docs/pages/developers/rust/importing.mdx b/documentation/docs/pages/developers/rust/importing.mdx index 0a11d0a3f4..858a8b184a 100644 --- a/documentation/docs/pages/developers/rust/importing.mdx +++ b/documentation/docs/pages/developers/rust/importing.mdx @@ -9,10 +9,10 @@ lastUpdated: "2026-04-17" # Installation import { Callout } from 'nextra/components'; -import { CratesPaused } from '../../../components/crates-paused' +import { VersionBanner } from '../../../components/version-banner' import { RUST_MSRV } from '../../../components/versions' - + ```toml [dependencies] diff --git a/documentation/docs/pages/developers/rust/mixnet/tutorial.mdx b/documentation/docs/pages/developers/rust/mixnet/tutorial.mdx index a94ebf9b5e..5699fb0ad9 100644 --- a/documentation/docs/pages/developers/rust/mixnet/tutorial.mdx +++ b/documentation/docs/pages/developers/rust/mixnet/tutorial.mdx @@ -141,19 +141,36 @@ async fn main() { .await .unwrap(); - println!("Address: {}", client.nym_address()); + let our_address = client.nym_address(); + println!("Address: {our_address}"); - // Same API as before — send, receive, reply. + // Same API as before — send, receive, SURB reply. client - .send_plain_message(*client.nym_address(), "persistent identity!") + .send_plain_message(*our_address, "hello from persistent client!") .await .unwrap(); + println!("Sent — waiting for arrival..."); - if let Some(msgs) = client.wait_for_messages().await { - for m in msgs.into_iter().filter(|m| !m.message.is_empty()) { - println!("Received: {}", String::from_utf8_lossy(&m.message)); + let message = loop { + if let Some(msgs) = client.wait_for_messages().await { + if let Some(msg) = msgs.into_iter().find(|m| !m.message.is_empty()) { + break msg; + } } - } + }; + println!("Received: {}", String::from_utf8_lossy(&message.message)); + + let sender_tag = message.sender_tag.expect("should have sender tag"); + client.send_reply(sender_tag, "anonymous reply!").await.unwrap(); + + let reply = loop { + if let Some(msgs) = client.wait_for_messages().await { + if let Some(msg) = msgs.into_iter().find(|m| !m.message.is_empty()) { + break msg; + } + } + }; + println!("Reply: {}", String::from_utf8_lossy(&reply.message)); // Always disconnect for clean shutdown — background tasks need to be // stopped and state files flushed. @@ -281,18 +298,35 @@ async fn main() { .await .unwrap(); - println!("Address: {}", client.nym_address()); + let our_address = client.nym_address(); + println!("Address: {our_address}"); client - .send_plain_message(*client.nym_address(), "persistent identity!") + .send_plain_message(*our_address, "hello from persistent client!") .await .unwrap(); + println!("Sent — waiting for arrival..."); - if let Some(msgs) = client.wait_for_messages().await { - for m in msgs.into_iter().filter(|m| !m.message.is_empty()) { - println!("Received: {}", String::from_utf8_lossy(&m.message)); + let message = loop { + if let Some(msgs) = client.wait_for_messages().await { + if let Some(msg) = msgs.into_iter().find(|m| !m.message.is_empty()) { + break msg; + } } - } + }; + println!("Received: {}", String::from_utf8_lossy(&message.message)); + + let sender_tag = message.sender_tag.expect("should have sender tag"); + client.send_reply(sender_tag, "anonymous reply!").await.unwrap(); + + let reply = loop { + if let Some(msgs) = client.wait_for_messages().await { + if let Some(msg) = msgs.into_iter().find(|m| !m.message.is_empty()) { + break msg; + } + } + }; + println!("Reply: {}", String::from_utf8_lossy(&reply.message)); client.disconnect().await; } diff --git a/documentation/docs/pages/developers/rust/stream.mdx b/documentation/docs/pages/developers/rust/stream.mdx index 38d8d7e10a..ab6531330d 100644 --- a/documentation/docs/pages/developers/rust/stream.mdx +++ b/documentation/docs/pages/developers/rust/stream.mdx @@ -9,9 +9,9 @@ lastUpdated: "2026-03-15" # Stream Module import { Callout } from 'nextra/components' -import { CratesPaused } from '../../../components/crates-paused' +import { VersionBanner } from '../../../components/version-banner' - + The Mixnet is fundamentally message-based: no persistent connections, no guaranteed ordering, no TCP. The default [message API](./mixnet) works at this level, sending individual payloads independently through Mix Nodes. This is effective for privacy but unlike how most networking code is structured.