Final pass

This commit is contained in:
mfahampshire
2026-04-28 20:25:07 +01:00
parent f9900f6946
commit 7efb81a601
8 changed files with 64 additions and 30 deletions
@@ -3,7 +3,7 @@ import { NYM_SDK_VERSION } from "./versions";
const INSTALL_PATH = "/developers/rust/importing";
export const CratesPaused = () => (
export const VersionBanner = () => (
<Callout type="info">
Code examples target <strong>v{NYM_SDK_VERSION}</strong> of the Nym crates
on{" "}
+1 -1
View File
@@ -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.
@@ -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) |
<Callout type="info">
`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.
@@ -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) |
<Callout type="error">
**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.
</Callout>
## 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) |
+2 -2
View File
@@ -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/)
</Callout>
<CratesPaused />
<VersionBanner />
For an overview of what the SDK can do, see the **[Tour](./rust/tour)**. For setup instructions, see [Installation](./rust/importing).
@@ -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'
<CratesPaused />
<VersionBanner />
```toml
[dependencies]
@@ -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;
}
@@ -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'
<CratesPaused />
<VersionBanner />
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.