Remove documentation changes (split to separate branch)
This commit is contained in:
@@ -1,3 +1,2 @@
|
||||
todo.md
|
||||
scripts/generate-api
|
||||
RELEASE_TASKS.md
|
||||
|
||||
@@ -1,33 +1,22 @@
|
||||
import { Callout } from "nextra/components";
|
||||
import { NYM_SDK_VERSION, SMOLMIX_VERSION } from "./versions";
|
||||
|
||||
const VERSIONS: Record<string, string> = {
|
||||
"nym-sdk": NYM_SDK_VERSION,
|
||||
smolmix: SMOLMIX_VERSION,
|
||||
};
|
||||
const COMMIT_SHORT = "97068b2";
|
||||
const COMMIT_FULL = "97068b2aa";
|
||||
const EXAMPLES_URL =
|
||||
"https://github.com/nymtech/nym/tree/develop/sdk/rust/nym-sdk/examples";
|
||||
|
||||
const EXAMPLES_URLS: Record<string, string> = {
|
||||
"nym-sdk":
|
||||
"https://github.com/nymtech/nym/tree/develop/sdk/rust/nym-sdk/examples",
|
||||
smolmix:
|
||||
"https://github.com/nymtech/nym/tree/develop/smolmix/core/examples",
|
||||
};
|
||||
|
||||
interface CodeVerifiedProps {
|
||||
/** Crate name to display. Defaults to "nym-sdk". */
|
||||
crate?: keyof typeof VERSIONS;
|
||||
}
|
||||
|
||||
export const CodeVerified = ({ crate: crateName = "nym-sdk" }: CodeVerifiedProps) => (
|
||||
export const CodeVerified = () => (
|
||||
<Callout type="info">
|
||||
Code verified against{" "}
|
||||
<code>{crateName}</code> v{VERSIONS[crateName]}. If the API has changed
|
||||
since then, check the{" "}
|
||||
Code verified against commit{" "}
|
||||
<a
|
||||
href={EXAMPLES_URLS[crateName]}
|
||||
href={`https://github.com/nymtech/nym/commit/${COMMIT_FULL}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<code>{COMMIT_SHORT}</code>
|
||||
</a>
|
||||
. If the API has changed since then, check the{" "}
|
||||
<a href={EXAMPLES_URL} target="_blank" rel="noopener noreferrer">
|
||||
examples in the repo
|
||||
</a>{" "}
|
||||
for the latest usage.
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Callout } from "nextra/components";
|
||||
|
||||
const CRATES_VERSION = "1.20.4";
|
||||
const INSTALL_PATH = "/developers/rust/importing";
|
||||
|
||||
export const CratesPaused = () => (
|
||||
<Callout type="warning">
|
||||
<strong>Crate publication is paused.</strong> The crates.io release (v
|
||||
{CRATES_VERSION}) doesn't include the Stream module or other recent work.
|
||||
Publication resumes with the Lewes Protocol. Import from Git for now — see{" "}
|
||||
<a href={INSTALL_PATH}>Installation</a>.
|
||||
</Callout>
|
||||
);
|
||||
@@ -153,116 +153,115 @@ export const MixFetch = () => {
|
||||
error: `Error: ${errorMsg}`,
|
||||
};
|
||||
const statusColor: Record<typeof status, string> = {
|
||||
idle: "#9e9e9e",
|
||||
idle: "gray",
|
||||
starting: "orange",
|
||||
ready: "#85E89D",
|
||||
error: "#ff6b6b",
|
||||
ready: "green",
|
||||
error: "red",
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ mt: 2 }}>
|
||||
<Paper sx={{ p: 3 }}>
|
||||
<Stack spacing={3}>
|
||||
{/* --- Start MixFetch Section --- */}
|
||||
<Stack direction="row" alignItems="center" spacing={2}>
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={status === "starting" || status === "ready"}
|
||||
onClick={handleStart}
|
||||
>
|
||||
Start MixFetch
|
||||
</Button>
|
||||
{status === "starting" && <CircularProgress size={20} />}
|
||||
<Typography
|
||||
fontFamily="monospace"
|
||||
fontSize="small"
|
||||
sx={{ color: statusColor[status] }}
|
||||
>
|
||||
{statusText[status]}
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
{/* --- Fetch Controls (disabled until ready) --- */}
|
||||
<Box
|
||||
sx={{
|
||||
opacity: isReady ? 1 : 0.5,
|
||||
pointerEvents: isReady ? "auto" : "none",
|
||||
}}
|
||||
<div style={{ marginTop: "1rem" }}>
|
||||
{/* --- Start MixFetch Section --- */}
|
||||
<Paper sx={{ p: 2, mb: 2 }} variant="outlined">
|
||||
<Stack direction="row" alignItems="center" spacing={2}>
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={status === "starting" || status === "ready"}
|
||||
onClick={handleStart}
|
||||
>
|
||||
{/* Single fetch */}
|
||||
<Stack direction="row" spacing={2}>
|
||||
<TextField
|
||||
disabled={busy}
|
||||
fullWidth
|
||||
label="URL"
|
||||
type="text"
|
||||
variant="outlined"
|
||||
defaultValue={defaultUrl}
|
||||
onChange={(e) => setUrl(e.target.value)}
|
||||
size="small"
|
||||
/>
|
||||
<Button
|
||||
variant="outlined"
|
||||
disabled={busy}
|
||||
onClick={handleFetch}
|
||||
>
|
||||
Fetch
|
||||
</Button>
|
||||
</Stack>
|
||||
{busy && (
|
||||
<Box mt={2}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
)}
|
||||
{html && (
|
||||
<>
|
||||
<Box mt={2}>
|
||||
<strong>Response</strong>
|
||||
</Box>
|
||||
<Paper sx={{ p: 2, mt: 1 }} elevation={4}>
|
||||
<Typography fontFamily="monospace" fontSize="small">
|
||||
{html}
|
||||
</Typography>
|
||||
</Paper>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Concurrent fetch demo */}
|
||||
<Box mt={3}>
|
||||
<strong>Concurrent Requests</strong>
|
||||
<Box mt={1}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
disabled={concurrentBusy}
|
||||
onClick={handleConcurrentFetch}
|
||||
>
|
||||
Send 5 Concurrent Requests (posts/1-5)
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
{concurrentBusy && (
|
||||
<Box mt={2}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
)}
|
||||
{concurrentResults.length > 0 && (
|
||||
<Paper sx={{ p: 2, mt: 2 }} elevation={4}>
|
||||
{concurrentResults.map((result, i) => (
|
||||
<Typography key={i} fontFamily="monospace" fontSize="small">
|
||||
{result}
|
||||
</Typography>
|
||||
))}
|
||||
</Paper>
|
||||
)}
|
||||
</Box>
|
||||
Start MixFetch
|
||||
</Button>
|
||||
{status === "starting" && <CircularProgress size={20} />}
|
||||
<Typography
|
||||
fontFamily="monospace"
|
||||
fontSize="small"
|
||||
sx={{ color: statusColor[status] }}
|
||||
>
|
||||
{statusText[status]}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
{/* --- Fetch Controls (disabled until ready) --- */}
|
||||
<Box
|
||||
sx={{
|
||||
opacity: isReady ? 1 : 0.5,
|
||||
pointerEvents: isReady ? "auto" : "none",
|
||||
}}
|
||||
>
|
||||
{/* Single fetch */}
|
||||
<Stack direction="row">
|
||||
<TextField
|
||||
disabled={busy}
|
||||
fullWidth
|
||||
label="URL"
|
||||
type="text"
|
||||
variant="outlined"
|
||||
defaultValue={defaultUrl}
|
||||
onChange={(e) => setUrl(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
variant="outlined"
|
||||
disabled={busy}
|
||||
sx={{ marginLeft: "1rem" }}
|
||||
onClick={handleFetch}
|
||||
>
|
||||
Fetch
|
||||
</Button>
|
||||
</Stack>
|
||||
{busy && (
|
||||
<Box mt={2}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
)}
|
||||
{html && (
|
||||
<>
|
||||
<Box mt={2}>
|
||||
<strong>Response</strong>
|
||||
</Box>
|
||||
<Paper sx={{ p: 2, mt: 1 }} elevation={4}>
|
||||
<Typography fontFamily="monospace" fontSize="small">
|
||||
{html}
|
||||
</Typography>
|
||||
</Paper>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Concurrent fetch demo */}
|
||||
<Box mt={3}>
|
||||
<strong>Concurrent Requests</strong>
|
||||
<Box mt={1}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
disabled={concurrentBusy}
|
||||
onClick={handleConcurrentFetch}
|
||||
>
|
||||
Send 5 Concurrent Requests (posts/1-5)
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
{concurrentBusy && (
|
||||
<Box mt={2}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
)}
|
||||
{concurrentResults.length > 0 && (
|
||||
<Paper sx={{ p: 2, mt: 2 }} elevation={4}>
|
||||
{concurrentResults.map((result, i) => (
|
||||
<Typography key={i} fontFamily="monospace" fontSize="small">
|
||||
{result}
|
||||
</Typography>
|
||||
))}
|
||||
</Paper>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* --- Log Panel --- */}
|
||||
{logs.length > 0 && (
|
||||
<Paper
|
||||
ref={logContainerRef}
|
||||
sx={{ p: 2, mt: 2, maxHeight: 200, overflow: "auto" }}
|
||||
sx={{ p: 2, mt: 3, maxHeight: 200, overflow: "auto" }}
|
||||
variant="outlined"
|
||||
>
|
||||
<strong>Log</strong>
|
||||
{logs.map((entry, i) => (
|
||||
@@ -277,6 +276,6 @@ export const MixFetch = () => {
|
||||
))}
|
||||
</Paper>
|
||||
)}
|
||||
</Box>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
},
|
||||
"mixmining_reserve": {
|
||||
"denom": "unym",
|
||||
"amount": "166613455567357"
|
||||
"amount": "168575020719057"
|
||||
},
|
||||
"vesting_tokens": {
|
||||
"denom": "unym",
|
||||
@@ -13,6 +13,6 @@
|
||||
},
|
||||
"circulating_supply": {
|
||||
"denom": "unym",
|
||||
"amount": "833386544432643"
|
||||
"amount": "831424979280943"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"nodes": 744,
|
||||
"locations": 77,
|
||||
"mixnodes": 264,
|
||||
"exit_gateways": 473
|
||||
"nodes": 752,
|
||||
"locations": 76,
|
||||
"mixnodes": 273,
|
||||
"exit_gateways": 470
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
833_386_544
|
||||
831_424_979
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
4_628
|
||||
4_682
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.06%
|
||||
0.95%
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
27.103
|
||||
30.134
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
254_977
|
||||
254_377
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
61_194_673
|
||||
61_050_638
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
61_194_672
|
||||
61_050_637
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
| **Item** | **Description** | **Amount in NYM** |
|
||||
|:-------------------|:------------------------------------------------------|--------------------:|
|
||||
| Total Supply | Maximum amount of NYM token in existence | 1_000_000_000 |
|
||||
| Mixmining Reserve | Tokens releasing for operators rewards | 166_613_455 |
|
||||
| Mixmining Reserve | Tokens releasing for operators rewards | 168_575_020 |
|
||||
| Vesting Tokens | Tokens locked outside of circulation for future claim | 0 |
|
||||
| Circulating Supply | Amount of unlocked tokens | 833_386_544 |
|
||||
| Stake Saturation | Optimal size of node self-bond + delegation | 254_977 |
|
||||
| Circulating Supply | Amount of unlocked tokens | 831_424_979 |
|
||||
| Stake Saturation | Optimal size of node self-bond + delegation | 254_377 |
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"interval": {
|
||||
"reward_pool": "166613455567357.391753168447944888",
|
||||
"staking_supply": "61194672938727.325886595653401629",
|
||||
"reward_pool": "168575020719057.456153922699547282",
|
||||
"staking_supply": "61050637328128.353993717821521057",
|
||||
"staking_supply_scale_factor": "0.07342892",
|
||||
"epoch_reward_budget": "4628151543.537705326476901331",
|
||||
"stake_saturation_point": "254977803911.363857860815222506",
|
||||
"epoch_reward_budget": "4682639464.418262670942297209",
|
||||
"stake_saturation_point": "254377655533.868141640490923004",
|
||||
"sybil_resistance": "0.3",
|
||||
"active_set_work_factor": "10",
|
||||
"interval_pool_emission": "0.02"
|
||||
|
||||
@@ -1 +1 @@
|
||||
Tuesday, April 28th 2026, 22:40:06 UTC
|
||||
Thursday, April 9th 2026, 15:33:24 UTC
|
||||
|
||||
@@ -12,8 +12,7 @@ Commands:
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
Options:
|
||||
-c, --config-env-file <CONFIG_ENV_FILE> Path pointing to an env file that configures the nym-node and overrides any preconfigured values [env:
|
||||
NYMNODE_CONFIG_ENV_FILE_ARG=]
|
||||
-c, --config-env-file <CONFIG_ENV_FILE> Path pointing to an env file that configures the nym-node and overrides any preconfigured values [env: NYMNODE_CONFIG_ENV_FILE_ARG=]
|
||||
--no-banner Flag used for disabling the printed banner in tty [env: NYMNODE_NO_BANNER=]
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
@@ -4,116 +4,56 @@ Start this nym-node
|
||||
Usage: nym-node run [OPTIONS]
|
||||
|
||||
Options:
|
||||
--id <ID>
|
||||
Id of the nym-node to use [env: NYMNODE_ID=] [default: default-nym-node]
|
||||
--config-file <CONFIG_FILE>
|
||||
Path to a configuration file of this node [env: NYMNODE_CONFIG=]
|
||||
--accept-operator-terms-and-conditions
|
||||
Explicitly specify whether you agree with the terms and conditions of a nym node operator as defined at <https://nymtech.net/terms-and-conditions/operators/v1.0.0>
|
||||
[env: NYMNODE_ACCEPT_OPERATOR_TERMS=]
|
||||
--deny-init
|
||||
Forbid a new node from being initialised if configuration file for the provided specification doesn't already exist [env: NYMNODE_DENY_INIT=]
|
||||
--init-only
|
||||
If this is a brand new nym-node, specify whether it should only be initialised without actually running the subprocesses [env: NYMNODE_INIT_ONLY=]
|
||||
--local
|
||||
Flag specifying this node will be running in a local setting [env: NYMNODE_LOCAL=]
|
||||
--mode [<MODE>...]
|
||||
Specifies the current mode(s) of this nym-node [env: NYMNODE_MODE=] [possible values: mixnode, entry-gateway, exit-gateway, exit-providers-only]
|
||||
--modes <MODES>
|
||||
Specifies the current mode(s) of this nym-node as a single flag [env: NYMNODE_MODES=] [possible values: mixnode, entry-gateway, exit-gateway, exit-providers-only]
|
||||
-w, --write-changes
|
||||
If this node has been initialised before, specify whether to write any new changes to the config file [env: NYMNODE_WRITE_CONFIG_CHANGES=]
|
||||
--bonding-information-output <BONDING_INFORMATION_OUTPUT>
|
||||
Specify output file for bonding information of this nym-node, i.e. its encoded keys. NOTE: the required bonding information is still a subject to change and this
|
||||
argument should be treated only as a preview of future features [env: NYMNODE_BONDING_INFORMATION_OUTPUT=]
|
||||
-o, --output <OUTPUT>
|
||||
Specify the output format of the bonding information (`text` or `json`) [env: NYMNODE_OUTPUT=] [default: text] [possible values: text, json]
|
||||
--public-ips <PUBLIC_IPS>
|
||||
Comma separated list of public ip addresses that will be announced to the nym-api and subsequently to the clients. In nearly all circumstances, it's going to be
|
||||
identical to the address you're going to use for bonding [env: NYMNODE_PUBLIC_IPS=]
|
||||
--hostname <HOSTNAME>
|
||||
Optional hostname associated with this gateway that will be announced to the nym-api and subsequently to the clients [env: NYMNODE_HOSTNAME=]
|
||||
--location <LOCATION>
|
||||
Optional **physical** location of this node's server. Either full country name (e.g. 'Poland'), two-letter alpha2 (e.g. 'PL'), three-letter alpha3 (e.g. 'POL') or
|
||||
three-digit numeric-3 (e.g. '616') can be provided [env: NYMNODE_LOCATION=]
|
||||
--http-bind-address <HTTP_BIND_ADDRESS>
|
||||
Socket address this node will use for binding its http API. default: `[::]:8080` [env: NYMNODE_HTTP_BIND_ADDRESS=]
|
||||
--landing-page-assets-path <LANDING_PAGE_ASSETS_PATH>
|
||||
Path to assets directory of custom landing page of this node [env: NYMNODE_HTTP_LANDING_ASSETS=]
|
||||
--http-access-token <HTTP_ACCESS_TOKEN>
|
||||
An optional bearer token for accessing certain http endpoints. Currently only used for prometheus metrics [env: NYMNODE_HTTP_ACCESS_TOKEN=]
|
||||
--expose-system-info <EXPOSE_SYSTEM_INFO>
|
||||
Specify whether basic system information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_SYSTEM_INFO=] [possible values: true, false]
|
||||
--expose-system-hardware <EXPOSE_SYSTEM_HARDWARE>
|
||||
Specify whether basic system hardware information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_SYSTEM_HARDWARE=] [possible values: true, false]
|
||||
--expose-crypto-hardware <EXPOSE_CRYPTO_HARDWARE>
|
||||
Specify whether detailed system crypto hardware information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_CRYPTO_HARDWARE=] [possible values: true,
|
||||
false]
|
||||
--mixnet-bind-address <MIXNET_BIND_ADDRESS>
|
||||
Address this node will bind to for listening for mixnet packets default: `[::]:1789` [env: NYMNODE_MIXNET_BIND_ADDRESS=]
|
||||
--mixnet-announce-port <MIXNET_ANNOUNCE_PORT>
|
||||
If applicable, custom port announced in the self-described API that other clients and nodes will use. Useful when the node is behind a proxy [env:
|
||||
NYMNODE_MIXNET_ANNOUNCE_PORT=]
|
||||
--nym-api-urls <NYM_API_URLS>
|
||||
Addresses to nym APIs from which the node gets the view of the network [env: NYMNODE_NYM_APIS=]
|
||||
--nyxd-urls <NYXD_URLS>
|
||||
Addresses to nyxd chain endpoint which the node will use for chain interactions [env: NYMNODE_NYXD=]
|
||||
--enable-console-logging <ENABLE_CONSOLE_LOGGING>
|
||||
Specify whether running statistics of this node should be logged to the console [env: NYMNODE_ENABLE_CONSOLE_LOGGING=] [possible values: true, false]
|
||||
--wireguard-enabled <WIREGUARD_ENABLED>
|
||||
Specifies whether the wireguard service is enabled on this node [env: NYMNODE_WG_ENABLED=] [possible values: true, false]
|
||||
--wireguard-bind-address <WIREGUARD_BIND_ADDRESS>
|
||||
Socket address this node will use for binding its wireguard interface. default: `[::]:51822` [env: NYMNODE_WG_BIND_ADDRESS=]
|
||||
--wireguard-tunnel-announced-port <WIREGUARD_TUNNEL_ANNOUNCED_PORT>
|
||||
Tunnel port announced to external clients wishing to connect to the wireguard interface. Useful in the instances where the node is behind a proxy [env:
|
||||
NYMNODE_WG_ANNOUNCED_PORT=]
|
||||
--wireguard-private-network-prefix <WIREGUARD_PRIVATE_NETWORK_PREFIX>
|
||||
The prefix denoting the maximum number of the clients that can be connected via Wireguard. The maximum value for IPv4 is 32 and for IPv6 is 128 [env:
|
||||
NYMNODE_WG_PRIVATE_NETWORK_PREFIX=]
|
||||
--wireguard-userspace <WIREGUARD_USERSPACE>
|
||||
Use userspace implementation of WireGuard (wireguard-go) instead of kernel module. Useful in containerized environments without kernel WireGuard support [env:
|
||||
NYMNODE_WG_USERSPACE=] [possible values: true, false]
|
||||
--verloc-bind-address <VERLOC_BIND_ADDRESS>
|
||||
Socket address this node will use for binding its verloc API. default: `[::]:1790` [env: NYMNODE_VERLOC_BIND_ADDRESS=]
|
||||
--verloc-announce-port <VERLOC_ANNOUNCE_PORT>
|
||||
If applicable, custom port announced in the self-described API that other clients and nodes will use. Useful when the node is behind a proxy [env:
|
||||
NYMNODE_VERLOC_ANNOUNCE_PORT=]
|
||||
--entry-bind-address <ENTRY_BIND_ADDRESS>
|
||||
Socket address this node will use for binding its client websocket API. default: `[::]:9000` [env: NYMNODE_ENTRY_BIND_ADDRESS=]
|
||||
--announce-ws-port <ANNOUNCE_WS_PORT>
|
||||
Custom announced port for listening for websocket client traffic. If unspecified, the value from the `bind_address` will be used instead [env:
|
||||
NYMNODE_ENTRY_ANNOUNCE_WS_PORT=]
|
||||
--announce-wss-port <ANNOUNCE_WSS_PORT>
|
||||
If applicable, announced port for listening for secure websocket client traffic [env: NYMNODE_ENTRY_ANNOUNCE_WSS_PORT=]
|
||||
--enforce-zk-nyms <ENFORCE_ZK_NYMS>
|
||||
Indicates whether this gateway is accepting only coconut credentials for accessing the mixnet or if it also accepts non-paying clients [env:
|
||||
NYMNODE_ENFORCE_ZK_NYMS=] [possible values: true, false]
|
||||
--mnemonic <MNEMONIC>
|
||||
Custom cosmos wallet mnemonic used for zk-nym redemption. If no value is provided, a fresh mnemonic is going to be generated [env: NYMNODE_MNEMONIC=]
|
||||
--upgrade-mode-attestation-url <UPGRADE_MODE_ATTESTATION_URL>
|
||||
Endpoint to query to retrieve current upgrade mode attestation. This argument should never be set outside testnets and local networks [env:
|
||||
NYMNODE_UPGRADE_MODE_ATTESTATION_URL=]
|
||||
--upgrade-mode-attester-public-key <UPGRADE_MODE_ATTESTER_PUBLIC_KEY>
|
||||
Expected public key of the entity signing the published attestation. This argument should never be set outside testnets and local networks [env:
|
||||
NYMNODE_UPGRADE_MODE_ATTESTER_PUBKEY=]
|
||||
--upstream-exit-policy-url <UPSTREAM_EXIT_POLICY_URL>
|
||||
Specifies the url for an upstream source of the exit policy used by this node [env: NYMNODE_UPSTREAM_EXIT_POLICY=]
|
||||
--open-proxy <OPEN_PROXY>
|
||||
Specifies whether this exit node should run in 'open-proxy' mode and thus would attempt to resolve **ANY** request it receives [env: NYMNODE_OPEN_PROXY=] [possible
|
||||
values: true, false]
|
||||
--lp-control-bind-address <LP_CONTROL_BIND_ADDRESS>
|
||||
Bind address for the TCP LP control traffic. default: `[::]:41264` [env: NYMNODE_LP_CONTROL_BIND_ADDRESS=]
|
||||
--lp-control-announce-port <LP_CONTROL_ANNOUNCE_PORT>
|
||||
Custom announced port for listening for the TCP LP control traffic. If unspecified, the value from the `lp_control_bind_address` will be used instead [env:
|
||||
NYMNODE_LP_CONTROL_ANNOUNCE_PORT=]
|
||||
--lp-data-bind-address <LP_DATA_BIND_ADDRESS>
|
||||
Bind address for the UDP LP data traffic. default: `[::]:51264` [env: NYMNODE_LP_DATA_BIND_ADDRESS=]
|
||||
--lp-data-announce-port <LP_DATA_ANNOUNCE_PORT>
|
||||
Custom announced port for listening for the UDP LP data traffic. If unspecified, the value from the `lp_data_bind_address` will be used instead [env:
|
||||
NYMNODE_LP_DATA_ANNOUNCE_PORT=]
|
||||
--lp-use-mock-ecash <LP_USE_MOCK_ECASH>
|
||||
Use mock ecash manager for LP testing. WARNING: Only use this for local testing! Never enable in production. When enabled, the LP listener will accept any
|
||||
credential without blockchain verification [env: NYMNODE_LP_USE_MOCK_ECASH=] [possible values: true, false]
|
||||
-h, --help
|
||||
Print help
|
||||
--id <ID> Id of the nym-node to use [env: NYMNODE_ID=] [default: default-nym-node]
|
||||
--config-file <CONFIG_FILE> Path to a configuration file of this node [env: NYMNODE_CONFIG=]
|
||||
--accept-operator-terms-and-conditions Explicitly specify whether you agree with the terms and conditions of a nym node operator as defined at <https://nymtech.net/terms-and-conditions/operators/v1.0.0> [env: NYMNODE_ACCEPT_OPERATOR_TERMS=]
|
||||
--deny-init Forbid a new node from being initialised if configuration file for the provided specification doesn't already exist [env: NYMNODE_DENY_INIT=]
|
||||
--init-only If this is a brand new nym-node, specify whether it should only be initialised without actually running the subprocesses [env: NYMNODE_INIT_ONLY=]
|
||||
--local Flag specifying this node will be running in a local setting [env: NYMNODE_LOCAL=]
|
||||
--mode [<MODE>...] Specifies the current mode(s) of this nym-node [env: NYMNODE_MODE=] [possible values: mixnode, entry-gateway, exit-gateway, exit-providers-only]
|
||||
--modes <MODES> Specifies the current mode(s) of this nym-node as a single flag [env: NYMNODE_MODES=] [possible values: mixnode, entry-gateway, exit-gateway, exit-providers-only]
|
||||
-w, --write-changes If this node has been initialised before, specify whether to write any new changes to the config file [env: NYMNODE_WRITE_CONFIG_CHANGES=]
|
||||
--bonding-information-output <BONDING_INFORMATION_OUTPUT> Specify output file for bonding information of this nym-node, i.e. its encoded keys. NOTE: the required bonding information is still a subject to change and this argument should be treated only as a preview of
|
||||
future features [env: NYMNODE_BONDING_INFORMATION_OUTPUT=]
|
||||
-o, --output <OUTPUT> Specify the output format of the bonding information (`text` or `json`) [env: NYMNODE_OUTPUT=] [default: text] [possible values: text, json]
|
||||
--public-ips <PUBLIC_IPS> Comma separated list of public ip addresses that will be announced to the nym-api and subsequently to the clients. In nearly all circumstances, it's going to be identical to the address you're going to use for
|
||||
bonding [env: NYMNODE_PUBLIC_IPS=]
|
||||
--hostname <HOSTNAME> Optional hostname associated with this gateway that will be announced to the nym-api and subsequently to the clients [env: NYMNODE_HOSTNAME=]
|
||||
--location <LOCATION> Optional **physical** location of this node's server. Either full country name (e.g. 'Poland'), two-letter alpha2 (e.g. 'PL'), three-letter alpha3 (e.g. 'POL') or three-digit numeric-3 (e.g. '616') can be
|
||||
provided [env: NYMNODE_LOCATION=]
|
||||
--http-bind-address <HTTP_BIND_ADDRESS> Socket address this node will use for binding its http API. default: `[::]:8080` [env: NYMNODE_HTTP_BIND_ADDRESS=]
|
||||
--landing-page-assets-path <LANDING_PAGE_ASSETS_PATH> Path to assets directory of custom landing page of this node [env: NYMNODE_HTTP_LANDING_ASSETS=]
|
||||
--http-access-token <HTTP_ACCESS_TOKEN> An optional bearer token for accessing certain http endpoints. Currently only used for prometheus metrics [env: NYMNODE_HTTP_ACCESS_TOKEN=]
|
||||
--expose-system-info <EXPOSE_SYSTEM_INFO> Specify whether basic system information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_SYSTEM_INFO=] [possible values: true, false]
|
||||
--expose-system-hardware <EXPOSE_SYSTEM_HARDWARE> Specify whether basic system hardware information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_SYSTEM_HARDWARE=] [possible values: true, false]
|
||||
--expose-crypto-hardware <EXPOSE_CRYPTO_HARDWARE> Specify whether detailed system crypto hardware information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_CRYPTO_HARDWARE=] [possible values: true, false]
|
||||
--mixnet-bind-address <MIXNET_BIND_ADDRESS> Address this node will bind to for listening for mixnet packets default: `[::]:1789` [env: NYMNODE_MIXNET_BIND_ADDRESS=]
|
||||
--mixnet-announce-port <MIXNET_ANNOUNCE_PORT> If applicable, custom port announced in the self-described API that other clients and nodes will use. Useful when the node is behind a proxy [env: NYMNODE_MIXNET_ANNOUNCE_PORT=]
|
||||
--nym-api-urls <NYM_API_URLS> Addresses to nym APIs from which the node gets the view of the network [env: NYMNODE_NYM_APIS=]
|
||||
--nyxd-urls <NYXD_URLS> Addresses to nyxd chain endpoint which the node will use for chain interactions [env: NYMNODE_NYXD=]
|
||||
--enable-console-logging <ENABLE_CONSOLE_LOGGING> Specify whether running statistics of this node should be logged to the console [env: NYMNODE_ENABLE_CONSOLE_LOGGING=] [possible values: true, false]
|
||||
--wireguard-enabled <WIREGUARD_ENABLED> Specifies whether the wireguard service is enabled on this node [env: NYMNODE_WG_ENABLED=] [possible values: true, false]
|
||||
--wireguard-bind-address <WIREGUARD_BIND_ADDRESS> Socket address this node will use for binding its wireguard interface. default: `[::]:51822` [env: NYMNODE_WG_BIND_ADDRESS=]
|
||||
--wireguard-tunnel-announced-port <WIREGUARD_TUNNEL_ANNOUNCED_PORT> Tunnel port announced to external clients wishing to connect to the wireguard interface. Useful in the instances where the node is behind a proxy [env: NYMNODE_WG_ANNOUNCED_PORT=]
|
||||
--wireguard-private-network-prefix <WIREGUARD_PRIVATE_NETWORK_PREFIX> The prefix denoting the maximum number of the clients that can be connected via Wireguard. The maximum value for IPv4 is 32 and for IPv6 is 128 [env: NYMNODE_WG_PRIVATE_NETWORK_PREFIX=]
|
||||
--wireguard-userspace <WIREGUARD_USERSPACE> Use userspace implementation of WireGuard (wireguard-go) instead of kernel module. Useful in containerized environments without kernel WireGuard support [env: NYMNODE_WG_USERSPACE=] [possible values: true,
|
||||
false]
|
||||
--verloc-bind-address <VERLOC_BIND_ADDRESS> Socket address this node will use for binding its verloc API. default: `[::]:1790` [env: NYMNODE_VERLOC_BIND_ADDRESS=]
|
||||
--verloc-announce-port <VERLOC_ANNOUNCE_PORT> If applicable, custom port announced in the self-described API that other clients and nodes will use. Useful when the node is behind a proxy [env: NYMNODE_VERLOC_ANNOUNCE_PORT=]
|
||||
--entry-bind-address <ENTRY_BIND_ADDRESS> Socket address this node will use for binding its client websocket API. default: `[::]:9000` [env: NYMNODE_ENTRY_BIND_ADDRESS=]
|
||||
--announce-ws-port <ANNOUNCE_WS_PORT> Custom announced port for listening for websocket client traffic. If unspecified, the value from the `bind_address` will be used instead [env: NYMNODE_ENTRY_ANNOUNCE_WS_PORT=]
|
||||
--announce-wss-port <ANNOUNCE_WSS_PORT> If applicable, announced port for listening for secure websocket client traffic [env: NYMNODE_ENTRY_ANNOUNCE_WSS_PORT=]
|
||||
--enforce-zk-nyms <ENFORCE_ZK_NYMS> Indicates whether this gateway is accepting only coconut credentials for accessing the mixnet or if it also accepts non-paying clients [env: NYMNODE_ENFORCE_ZK_NYMS=] [possible values: true, false]
|
||||
--mnemonic <MNEMONIC> Custom cosmos wallet mnemonic used for zk-nym redemption. If no value is provided, a fresh mnemonic is going to be generated [env: NYMNODE_MNEMONIC=]
|
||||
--upgrade-mode-attestation-url <UPGRADE_MODE_ATTESTATION_URL> Endpoint to query to retrieve current upgrade mode attestation. This argument should never be set outside testnets and local networks [env: NYMNODE_UPGRADE_MODE_ATTESTATION_URL=]
|
||||
--upgrade-mode-attester-public-key <UPGRADE_MODE_ATTESTER_PUBLIC_KEY> Expected public key of the entity signing the published attestation. This argument should never be set outside testnets and local networks [env: NYMNODE_UPGRADE_MODE_ATTESTER_PUBKEY=]
|
||||
--upstream-exit-policy-url <UPSTREAM_EXIT_POLICY_URL> Specifies the url for an upstream source of the exit policy used by this node [env: NYMNODE_UPSTREAM_EXIT_POLICY=]
|
||||
--open-proxy <OPEN_PROXY> Specifies whether this exit node should run in 'open-proxy' mode and thus would attempt to resolve **ANY** request it receives [env: NYMNODE_OPEN_PROXY=] [possible values: true, false]
|
||||
--lp-control-bind-address <LP_CONTROL_BIND_ADDRESS> Bind address for the TCP LP control traffic. default: `[::]:41264` [env: NYMNODE_LP_CONTROL_BIND_ADDRESS=]
|
||||
--lp-control-announce-port <LP_CONTROL_ANNOUNCE_PORT> Custom announced port for listening for the TCP LP control traffic. If unspecified, the value from the `lp_control_bind_address` will be used instead [env: NYMNODE_LP_CONTROL_ANNOUNCE_PORT=]
|
||||
--lp-data-bind-address <LP_DATA_BIND_ADDRESS> Bind address for the UDP LP data traffic. default: `[::]:51264` [env: NYMNODE_LP_DATA_BIND_ADDRESS=]
|
||||
--lp-data-announce-port <LP_DATA_ANNOUNCE_PORT> Custom announced port for listening for the UDP LP data traffic. If unspecified, the value from the `lp_data_bind_address` will be used instead [env: NYMNODE_LP_DATA_ANNOUNCE_PORT=]
|
||||
--lp-use-mock-ecash <LP_USE_MOCK_ECASH> Use mock ecash manager for LP testing. WARNING: Only use this for local testing! Never enable in production. When enabled, the LP listener will accept any credential without blockchain verification [env:
|
||||
NYMNODE_LP_USE_MOCK_ECASH=] [possible values: true, false]
|
||||
-h, --help Print help
|
||||
```
|
||||
|
||||
@@ -8,15 +8,6 @@
|
||||
"native": "Native Apps",
|
||||
"browsers": "Browser Apps",
|
||||
"concepts": "Nym-Specific Concepts for Integrations",
|
||||
"-----": {
|
||||
"type": "separator",
|
||||
"title": "Standalone Crates"
|
||||
},
|
||||
"smolmix": "smolmix",
|
||||
"smolmix-dns": "smolmix-dns",
|
||||
"smolmix-tls": "smolmix-tls",
|
||||
"smolmix-hyper": "smolmix-hyper",
|
||||
"smolmix-extending": "Building on smolmix",
|
||||
"-": {
|
||||
"type": "separator",
|
||||
"title": "SDKs"
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Callout } from 'nextra/components'
|
||||
|
||||
<Callout type="warning">
|
||||
NymConnect is no longer maintained as of early 2024. Nym is developing a new client called [NymVPN](https://nymvpn.com), an application routing all user traffic through the Mixnet.
|
||||
If you want to route traffic through SOCKS5, use the maintained [Nym Socks5 Client](/developers/clients/socks5/setup).
|
||||
If you want to route traffic through SOCKS5, use the maintained [Nym Socks5 Client](../clients/socks5/setup).
|
||||
</Callout>
|
||||
|
||||
In case you want to run deprecated NymConnect, follow these steps:
|
||||
@@ -29,7 +29,7 @@ Here are some examples of applications which will work behind Socks5 proxy (`nym
|
||||
|
||||
To download Electrum visit the [official webpage](https://electrum.org/#download). To connect to the Mixnet follow these steps:
|
||||
|
||||
1. Start and connect NymConnect (or [`nym-socks5-client`](/developers/clients/socks5/setup))
|
||||
1. Start and connect NymConnect (or [`nym-socks5-client`](../clients/socks5/setup))
|
||||
2. Start your Electrum Bitcoin wallet
|
||||
3. Go to: *Tools* -> *Network* -> *Proxy*
|
||||
4. Set *Use proxy* to ✅, choose `SOCKS5` from the drop-down and add (copy-paste) the values from your NymConnect application
|
||||
@@ -41,7 +41,7 @@ To download Electrum visit the [official webpage](https://electrum.org/#download
|
||||
|
||||
To download Monero wallet visit [getmonero.org](https://www.getmonero.org/downloads/). To connect to the Mixnet follow these steps:
|
||||
|
||||
1. Start and connect NymConnect (or [`nym-socks5-client`](/developers/clients/socks5/setup))
|
||||
1. Start and connect NymConnect (or [`nym-socks5-client`](../clients/socks5/setup))
|
||||
2. Start your Monero wallet
|
||||
3. Go to: *Settings* -> *Interface* -> *Socks5 proxy* -> Add values: IP address `127.0.0.1`, Port `1080` (the values copied from NymConnect)
|
||||
5. Now your Monero wallet runs through the Mixnet and it will be connected only if your NymConnect or `nym-socks5-client` are connected.
|
||||
@@ -51,7 +51,7 @@ To download Monero wallet visit [getmonero.org](https://www.getmonero.org/downlo
|
||||
|
||||
To download Element (chat client for Matrix) visit [element.io](https://element.io/download). To connect to the Mixnet follow these steps:
|
||||
|
||||
1. Start and connect NymConnect (or [`nym-socks5-client`](/developers/clients/socks5/setup))
|
||||
1. Start and connect NymConnect (or [`nym-socks5-client`](../clients/socks5/setup))
|
||||
2. Start `element-desktop` with `--proxy-server` argument:
|
||||
|
||||
**Linux**
|
||||
@@ -70,7 +70,7 @@ To make the start of Element over NymConnect simplier, you can add this command
|
||||
|
||||
### Telegram via NymConnect
|
||||
|
||||
1. Start and connect NymConnect (or [`nym-socks5-client`](/developers/clients/socks5/setup))
|
||||
1. Start and connect NymConnect (or [`nym-socks5-client`](../clients/socks5/setup))
|
||||
2. Start your Telegram chat application
|
||||
3. Open the Telegram proxy settings.
|
||||
- Linux: *Settings* -> *Advanced* -> *Connection type* -> *Use custom proxy*
|
||||
|
||||
@@ -16,15 +16,28 @@ 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](/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
|
||||
|
||||
A drop-in replacement for the browser `fetch` API that makes HTTP(S) requests via Exit Gateways using the SOCKS Network Requester. It ships with an embedded CA certificate store to establish a TLS session between `mixFetch` and the remote host, creating a secure channel from the browser to the destination over the Mixnet.
|
||||
|
||||
Internally, `mixFetch` uses the WASM client.
|
||||
|
||||
- [Docs](./typescript#mixfetch)
|
||||
- [Example](./typescript/playground/mixfetch)
|
||||
|
||||
<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.
|
||||
</Callout>
|
||||
|
||||
<Callout type="warning">
|
||||
The WASM Client does not support IP packet routing (IPR) or stream-like APIs. For HTTP(S) requests from the browser, use `mixFetch`. Standard browser CSP and mixed content restrictions (HTTPS only) apply to the WebSocket connection.
|
||||
</Callout>
|
||||
## WASM Client
|
||||
|
||||
Constructs Sphinx packets and cover traffic in WASM, sent over a WebSocket to the Entry Gateway. Responses arrive the same way.
|
||||
|
||||
This operates in messaging mode only (text or binary payloads) and does not currently support IP packet routing via the Exit Gateway IPR or any stream-like API. For HTTP(S) requests, use `mixFetch`.
|
||||
|
||||
Standard browser CSP and mixed content restrictions (HTTPS only) apply to the WebSocket connection, including in embedded WebViews.
|
||||
|
||||
The client runs in a web worker to keep the UI thread free.
|
||||
|
||||
- [Docs](./typescript#mixnet-client)
|
||||
- [Example](./typescript/playground/traffic)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Socks5 Client (Standalone)
|
||||
|
||||
> This client can also be utilised via the [Rust SDK](/developers/rust).
|
||||
> This client can also be utilised via the [Rust SDK](../rust).
|
||||
|
||||
Many existing applications are able to use either the SOCKS4, SOCKS4A, or SOCKS5 proxy protocols. If you want to send such an application's traffic through the mixnet, you can use the `nym-socks5-client` to bounce network traffic through the Nym network, like this:
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
## Overview
|
||||
The Nym webassembly client allows any webassembly-capable runtime to build and send Sphinx packets to the Nym network, for uses in edge computing and browser-based applications.
|
||||
|
||||
This is currently packaged and distributed for ease of use via the [Nym Typescript SDK library](/developers/typescript). **We imagine most developers will use this client via the SDK for ease.**
|
||||
This is currently packaged and distributed for ease of use via the [Nym Typescript SDK library](../typescript). **We imagine most developers will use this client via the SDK for ease.**
|
||||
|
||||
The webassembly client allows for the easy creation of Sphinx packets from within mobile apps and browser-based client-side apps (including Electron or similar).
|
||||
|
||||
## Building apps with Webassembly Client
|
||||
Check out the [Typescript SDK docs](/developers/typescript) for examples of usage.
|
||||
Check out the [Typescript SDK docs](../typescript) for examples of usage.
|
||||
|
||||
## Think about what you're sending!
|
||||
import { Callout } from 'nextra/components'
|
||||
|
||||
@@ -11,7 +11,7 @@ import { Callout } from 'nextra/components'
|
||||
# Message Queue
|
||||
|
||||
<Callout type="info">
|
||||
Although useful for understanding how the Nym Client works internally, this information is only of practical use if you are using the [`Mixnet`](/developers/rust/mixnet) module of the Rust SDK and interacting with the client at a low level. Most of this is abstracted away by the [`Stream`](/developers/rust/stream) module (`AsyncRead + AsyncWrite` channels) and the [`TcpProxy`](/developers/rust/tcpproxy) module (TCP tunnelling with message ordering).
|
||||
Although useful for understanding how the Nym Client works internally, this information is only of practical use if you are using the [`Mixnet`](../rust/mixnet) module of the Rust SDK and interacting with the client at a low level. Most of this is abstracted away by the [`Stream`](../rust/stream) module (`AsyncRead + AsyncWrite` channels) and the [`TcpProxy`](../rust/tcpproxy) module (TCP tunnelling with message ordering).
|
||||
</Callout>
|
||||
|
||||
## Sphinx Packet Streams
|
||||
@@ -85,6 +85,6 @@ sequenceDiagram
|
||||
When passing a message to a client (however you do it, either piping messages from an app to a standalone client or via one of the `send` functions exposed by the SDKs), you are **putting that message into the queue** to be source encrypted and sent in the future, in order to ensure that traffic leaving the client does so in a manner that to an external observer is uniform / does not create any 'burst' or change in traffic timings that could aid traffic analysis.
|
||||
|
||||
## Note on Client Shutdown
|
||||
Accidentally dropping a client before your message has been sent is something that is possible and should be avoided (see the [troubleshooting guide](/developers/rust/mixnet/troubleshooting) for more on this) but is easy to avoid simply by remembering to:
|
||||
Accidentally dropping a client before your message has been sent is something that is possible and should be avoided (see the [troubleshooting guide](../rust/mixnet/troubleshooting) for more on this) but is easy to avoid simply by remembering to:
|
||||
- keep your client process alive, even if you are not expecting a reply to your message
|
||||
- (in the case of the SDKs) properly disconnecting your client in order to make sure that the message queue is flushed of Sphinx packets with actual payloads.
|
||||
|
||||
@@ -15,7 +15,6 @@ Build applications that protect user metadata using the Nym Mixnet. This section
|
||||
**Choosing an integration approach:** read [Integrations](/developers/integrations) to understand the architectural trade-offs (native SDK vs proxy vs mixFetch), then pick your path:
|
||||
|
||||
- **[Rust SDK](/developers/rust):** full-featured SDK with message passing, `AsyncRead`/`AsyncWrite` streams, and client pooling. Start with the [Tour](/developers/rust/tour).
|
||||
- **[`smolmix`](/developers/smolmix):** standalone crate providing `TcpStream` and `UdpSocket` over the Mixnet via a userspace IP stack. Drop-in compatible with `tokio-rustls`, `hyper`, `tungstenite`, and the rest of the async Rust ecosystem. Also serves as the core for companion crates that plug into specific frameworks (e.g. hyper connectors, DNS resolvers).
|
||||
- **[TypeScript SDK](/developers/typescript):** browser and Node.js SDK for mixFetch, Mixnet client, and smart contract interaction.
|
||||
- **[Standalone Clients](/developers/clients):** language-agnostic SOCKS5 and WebSocket proxies for piping traffic through the Mixnet without an SDK.
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ Any application that integrates with Nym sends its traffic through the Mixnet vi
|
||||
|
||||
Different runtimes have different transport constraints: a browser cannot open raw sockets or access the filesystem, while a desktop app can.
|
||||
|
||||
- **Native / Desktop**: full access to system networking and persistent storage. Use the [Rust SDK](/developers/rust) or [`smolmix`](/developers/smolmix).
|
||||
- **Browser**: restricted to WebSockets, Web Transport, and `fetch`, with HTTPS-only mixed content rules and no filesystem access. Use the [TypeScript SDK](/developers/typescript).
|
||||
- **Native / Desktop**: full access to system networking and persistent storage. Use the [Rust SDK](./rust).
|
||||
- **Browser**: restricted to WebSockets, Web Transport, and `fetch`, with HTTPS-only mixed content rules and no filesystem access. Use the [TypeScript SDK](./typescript).
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -25,10 +25,10 @@ The second factor is whether you control both sides of the communication.
|
||||
|
||||
**End-to-end (E2E)**: both sides run Nym clients. All traffic stays Sphinx-encrypted the entire way. Appropriate for peer-to-peer setups or any case where you control both endpoints.
|
||||
|
||||
**Proxy**: only the client side runs Nym. Traffic exits the Mixnet at an Exit Gateway and continues to the destination as normal internet traffic. Appropriate when connecting to third-party services (blockchain RPCs, external APIs) that you do not control. For Rust, [`smolmix`](/developers/smolmix) provides `TcpStream` and `UdpSocket` types that work as drop-in replacements for their tokio equivalents. Companion crates add DNS ([`smolmix-dns`](/developers/smolmix-dns)), TLS ([`smolmix-tls`](/developers/smolmix-tls)), and HTTP ([`smolmix-hyper`](/developers/smolmix-hyper)) on top.
|
||||
**Proxy**: only the client side runs Nym. Traffic exits the Mixnet at an Exit Gateway and continues to the destination as normal internet traffic. Appropriate when connecting to third-party services (blockchain RPCs, external APIs) that you do not control.
|
||||
|
||||
<Callout type="warning">
|
||||
In proxy mode, the last hop from Exit Gateway to the remote host travels as standard internet traffic. This is weaker than E2E against a global passive adversary, but still provides timing obfuscation and sender-receiver unlinkability.
|
||||
</Callout>
|
||||
|
||||
See the [Native / Desktop](/developers/native) and [Browser](/developers/browsers) pages for the specific modules available in each environment.
|
||||
See the [Native / Desktop](./native) and [Browser](./browsers) pages for the specific modules available in each environment.
|
||||
|
||||
@@ -10,40 +10,54 @@ import { Callout } from 'nextra/components';
|
||||
|
||||
# Native / Desktop Apps
|
||||
|
||||
Desktop apps and CLIs integrate with two broad approaches: embedding Nym clients on both sides of the communication (E2E), or using the Mixnet as a proxy to reach external services.
|
||||
Desktop apps and CLIs integrate via the [Rust SDK](./rust), with two broad approaches: embedding Nym clients on both sides of the communication (E2E), or using the Mixnet as a proxy to reach external services.
|
||||
|
||||
## Mixnet End-To-End
|
||||
## Option 1: Mixnet End-To-End
|
||||
Both sides of your app run Nym clients. All traffic stays Sphinx-encrypted the entire way. Works for peer-to-peer setups or any case where you control both ends.
|
||||
|
||||

|
||||
|
||||
| SDK Module | What it does | Status | Links |
|
||||
|---|---|---|---|
|
||||
| **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) |
|
||||
### Stream Module
|
||||
The [Stream module](./rust/stream) provides `AsyncRead + AsyncWrite` byte streams multiplexed over the mixnet, the closest analogue to TCP sockets.
|
||||
|
||||
- [docs](./rust/stream)
|
||||
- [tutorial](./rust/stream/tutorial)
|
||||
|
||||
### Mixnet & Client Pool Modules
|
||||
The [Mixnet module](./rust/mixnet) exposes the raw message API and `MixnetClient`. The [Client Pool](./rust/client-pool) maintains pre-connected clients for bursty workloads. These are appropriate when you need full control over the communication model.
|
||||
|
||||
- [docs](./rust/mixnet)
|
||||
- [tutorial](./rust/mixnet/tutorial)
|
||||
|
||||
### TcpProxy Module (Unmaintained)
|
||||
|
||||
<Callout type="error">
|
||||
**TcpProxy is unmaintained.** Use the [Stream module](/developers/rust/stream) for new projects.
|
||||
**This module is unmaintained.** Use the [Stream module](./rust/stream) for new projects. Existing users should plan to migrate when possible.
|
||||
</Callout>
|
||||
|
||||
## Mixnet-As-Proxy
|
||||
Exposes localhost TCP sockets that proxy traffic through the mixnet.
|
||||
|
||||
- [docs](./rust/tcpproxy)
|
||||
|
||||
## Option 2: Mixnet-As-Proxy
|
||||
For cases where you only control the client side and need to reach a third-party service such as a blockchain RPC or remote API.
|
||||
|
||||

|
||||
|
||||
<Callout type="warning">
|
||||
Traffic is Sphinx-encrypted until the Exit Gateway, where it's unwrapped into HTTPS ([Network Requester](/network/infrastructure/exit-services#network-requester)) or raw IP ([IP Packet Router](/network/infrastructure/exit-services#ip-packet-router)). The last hop to the remote host **travels as normal internet traffic**. Use TLS or another encryption layer to protect the final hop.
|
||||
|
||||
### Security Considerations
|
||||
|
||||
Traffic is Sphinx-encrypted until the Exit Gateway, where it's unwrapped into HTTPS (Network Requester) or raw IP (IP Packet Router). The last hop to the remote host **travels as normal internet traffic**.
|
||||
|
||||
Weaker than E2E against a global passive adversary, but you still get timing obfuscation and sender-receiver unlinkability between your client and the remote service.
|
||||
</Callout>
|
||||
|
||||
| Standalone Crate | What it does | Links |
|
||||
|---|---|---|
|
||||
| **`smolmix`** | Userspace IP tunnel — `TcpStream` and `UdpSocket` over the mixnet, compatible with the entire async Rust ecosystem | [docs](/developers/smolmix) |
|
||||
| **`smolmix-dns`** | DNS resolution through the tunnel — prevents hostname leaks to local network | [docs](/developers/smolmix-dns) |
|
||||
| **`smolmix-tls`** | TLS connector with webpki roots — encrypts the final hop between exit gateway and destination | [docs](/developers/smolmix-tls) |
|
||||
| **`smolmix-hyper`** | HTTP client routing DNS + TCP + TLS through the mixnet — the "fetch a URL anonymously" crate | [docs](/developers/smolmix-hyper) |
|
||||
### SOCKS Client
|
||||
Applications that support SOCKS4, 4a, or 5 can use the Socks Client exposed by the Mixnet module. Traffic is routed through the Exit Gateway's Network Requester, which uses SURBs to reply to the sender anonymously.
|
||||
|
||||
| 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](/developers/rust/mixnet) |
|
||||
- [docs](./rust/mixnet)
|
||||
|
||||
<Callout type="info">
|
||||
Development is in progress to allow for this proxy method from native Rust, C, and Go without requiring a separate SOCKS client. Stay tuned.
|
||||
</Callout>
|
||||
|
||||
@@ -9,7 +9,7 @@ lastUpdated: "2026-03-13"
|
||||
# Rust SDK
|
||||
|
||||
import { Callout } from 'nextra/components'
|
||||
import { VersionBanner } from '../../components/version-banner'
|
||||
import { CratesPaused } from '../../components/crates-paused'
|
||||
|
||||
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>
|
||||
|
||||
<VersionBanner />
|
||||
<CratesPaused />
|
||||
|
||||
For an overview of what the SDK can do, see the **[Tour](./rust/tour)**. For setup instructions, see [Installation](./rust/importing).
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ use nym_sdk::client_pool::ClientPool;
|
||||
use nym_network_defaults::setup_env;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
nym_bin_common::logging::setup_tracing_logger();
|
||||
// Load mainnet network defaults into env vars (required by ClientPool)
|
||||
setup_env(None::<String>);
|
||||
|
||||
@@ -3,14 +3,13 @@ title: "Client Pool Tutorial: Handle Bursty Traffic"
|
||||
description: "Step-by-step Rust tutorial to use Nym ClientPool for handling bursts of concurrent mixnet operations without blocking on client creation."
|
||||
schemaType: "HowTo"
|
||||
section: "Developers"
|
||||
lastUpdated: "2026-04-17"
|
||||
lastUpdated: "2026-03-26"
|
||||
---
|
||||
|
||||
# Tutorial: Handle Bursty Traffic with Client Pool
|
||||
|
||||
import { Callout } from 'nextra/components'
|
||||
import { CodeVerified } from '../../../../components/code-verified'
|
||||
import { RUST_MSRV } from '../../../../components/versions'
|
||||
|
||||
In this tutorial you'll build a program that uses `ClientPool` to handle bursts of concurrent Mixnet operations without blocking on client creation. You'll see how the pool pre-creates clients in the background, how to pop them under load, and what happens when demand exceeds supply.
|
||||
|
||||
@@ -26,7 +25,7 @@ In this tutorial you'll build a program that uses `ClientPool` to handle bursts
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Rust toolchain ({RUST_MSRV}+)
|
||||
- Rust toolchain (1.70+)
|
||||
- A working internet connection
|
||||
|
||||
## Step 1: Set up the project
|
||||
@@ -40,9 +39,9 @@ Add dependencies to `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
nym-sdk = "X.Y.Z"
|
||||
nym-network-defaults = "X.Y.Z"
|
||||
nym-bin-common = { version = "X.Y.Z", features = ["basic_tracing"] }
|
||||
nym-sdk = { git = "https://github.com/nymtech/nym", rev = "97068b2" }
|
||||
nym-network-defaults = { git = "https://github.com/nymtech/nym", rev = "97068b2" }
|
||||
nym-bin-common = { git = "https://github.com/nymtech/nym", rev = "97068b2", features = ["basic_tracing"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
blake3 = "=1.7.0" # required pin — see https://nymtech.net/docs/developers/rust/importing
|
||||
```
|
||||
@@ -232,33 +231,20 @@ async fn main() {
|
||||
setup_env(None::<String>);
|
||||
|
||||
let pool = ClientPool::new(3);
|
||||
|
||||
let pool_bg = pool.clone();
|
||||
tokio::spawn(async move {
|
||||
pool_bg.start().await.unwrap();
|
||||
});
|
||||
tokio::spawn(async move { pool_bg.start().await.unwrap() });
|
||||
|
||||
println!("Pool started — waiting for clients to connect...");
|
||||
println!("Waiting for pool to fill...");
|
||||
tokio::time::sleep(Duration::from_secs(15)).await;
|
||||
|
||||
let count = pool.get_client_count().await;
|
||||
println!("Pool has {count} clients ready");
|
||||
println!("Pool has {} clients", pool.get_client_count().await);
|
||||
|
||||
let mut handles = vec![];
|
||||
|
||||
for i in 1..=3 {
|
||||
let pool = pool.clone();
|
||||
|
||||
let handle = tokio::spawn(async move {
|
||||
handles.push(tokio::spawn(async move {
|
||||
let mut client = match pool.get_mixnet_client().await {
|
||||
Some(c) => {
|
||||
println!("Task {i}: got client {} from pool", c.nym_address());
|
||||
c
|
||||
}
|
||||
None => {
|
||||
println!("Task {i}: pool empty, creating client on the fly...");
|
||||
nym_sdk::mixnet::MixnetClient::connect_new().await.unwrap()
|
||||
}
|
||||
Some(c) => c,
|
||||
None => nym_sdk::mixnet::MixnetClient::connect_new().await.unwrap(),
|
||||
};
|
||||
|
||||
let addr = *client.nym_address();
|
||||
@@ -268,34 +254,24 @@ async fn main() {
|
||||
.unwrap();
|
||||
|
||||
if let Some(msgs) = client.wait_for_messages().await {
|
||||
for msg in msgs {
|
||||
if !msg.message.is_empty() {
|
||||
println!(
|
||||
"Task {i}: received {:?}",
|
||||
String::from_utf8_lossy(&msg.message)
|
||||
);
|
||||
}
|
||||
for msg in msgs.iter().filter(|m| !m.message.is_empty()) {
|
||||
println!("Task {i}: {}", String::from_utf8_lossy(&msg.message));
|
||||
}
|
||||
}
|
||||
|
||||
client.disconnect().await;
|
||||
println!("Task {i}: done");
|
||||
});
|
||||
|
||||
handles.push(handle);
|
||||
}));
|
||||
}
|
||||
|
||||
for h in handles {
|
||||
h.await.unwrap();
|
||||
}
|
||||
|
||||
println!("\nWaiting for pool to replenish...");
|
||||
println!("Waiting for replenishment...");
|
||||
tokio::time::sleep(Duration::from_secs(15)).await;
|
||||
|
||||
let count = pool.get_client_count().await;
|
||||
println!("Pool has {count} clients ready again");
|
||||
println!("Pool has {} clients", pool.get_client_count().await);
|
||||
|
||||
pool.disconnect_pool().await;
|
||||
println!("Pool shut down");
|
||||
println!("Done");
|
||||
}
|
||||
```
|
||||
|
||||
@@ -3,20 +3,19 @@ title: "Install the Nym Rust SDK"
|
||||
description: "Add nym-sdk to your Rust project from Git or crates.io. Covers version requirements, minimum Rust version, and current feature gate status."
|
||||
schemaType: "TechArticle"
|
||||
section: "Developers"
|
||||
lastUpdated: "2026-04-17"
|
||||
lastUpdated: "2026-03-27"
|
||||
---
|
||||
|
||||
# Installation
|
||||
|
||||
import { Callout } from 'nextra/components';
|
||||
import { VersionBanner } from '../../../components/version-banner'
|
||||
import { RUST_MSRV } from '../../../components/versions'
|
||||
import { CratesPaused } from '../../../components/crates-paused'
|
||||
|
||||
<VersionBanner />
|
||||
<CratesPaused />
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
nym-sdk = "X.Y.Z"
|
||||
nym-sdk = { git = "https://github.com/nymtech/nym", rev = "97068b2" }
|
||||
blake3 = "=1.7.0" # pin to avoid a transitive dependency conflict — see note below
|
||||
```
|
||||
|
||||
@@ -24,11 +23,7 @@ blake3 = "=1.7.0" # pin to avoid a transitive dependency conflict — see note
|
||||
**Temporary pin required.** You must pin `blake3 = "=1.7.0"` in your `Cargo.toml` to avoid a build failure caused by a transitive `digest` version conflict. This will be resolved in a future SDK release.
|
||||
</Callout>
|
||||
|
||||
**Minimum Rust version:** {RUST_MSRV}+
|
||||
|
||||
### From Git
|
||||
|
||||
You can also import directly from Git if you want unreleased changes:
|
||||
You can also track a branch if you want the latest changes:
|
||||
|
||||
```toml
|
||||
# development branch (latest changes, may be unstable)
|
||||
@@ -38,6 +33,19 @@ nym-sdk = { git = "https://github.com/nymtech/nym", branch = "develop" }
|
||||
nym-sdk = { git = "https://github.com/nymtech/nym", branch = "master" }
|
||||
```
|
||||
|
||||
**Minimum Rust version:** 1.70+
|
||||
|
||||
### crates.io (older API only)
|
||||
|
||||
If you don't need the Stream module or other recent additions, you can still use the published crate:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
nym-sdk = "1.20.4"
|
||||
```
|
||||
|
||||
This version includes the Mixnet message API, Client Pool, and TcpProxy modules.
|
||||
|
||||
<Callout type="warning">
|
||||
**No feature gates yet.** Importing `nym-sdk` pulls in everything (mixnet, tcp_proxy, client_pool, etc.) and their full dependency trees. Cargo feature flags are planned.
|
||||
</Callout>
|
||||
|
||||
@@ -3,18 +3,17 @@ title: "Mixnet Tutorial: Send Your First Private Message"
|
||||
description: "Step-by-step Rust tutorial to connect to the Nym mixnet, send and receive messages, reply anonymously with SURBs, and persist client identity."
|
||||
schemaType: "HowTo"
|
||||
section: "Developers"
|
||||
lastUpdated: "2026-04-17"
|
||||
lastUpdated: "2026-03-26"
|
||||
---
|
||||
|
||||
# Tutorial: Send Your First Private Message
|
||||
|
||||
import { Callout } from 'nextra/components'
|
||||
import { CodeVerified } from '../../../../components/code-verified'
|
||||
import { RUST_MSRV } from '../../../../components/versions'
|
||||
|
||||
By the end of this tutorial you'll have a working program that sends a Sphinx-encrypted message to itself through the Nym Mixnet, receives it, and replies anonymously using SURBs. The later sections cover persistent identity and concurrent send/receive.
|
||||
|
||||
**You'll need:** Rust {RUST_MSRV}+ and an internet connection (clients connect to the live Mixnet).
|
||||
**You'll need:** Rust 1.70+ and an internet connection (clients connect to the live Mixnet).
|
||||
|
||||
<CodeVerified />
|
||||
|
||||
@@ -29,8 +28,8 @@ Add dependencies to `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
nym-sdk = "X.Y.Z"
|
||||
nym-bin-common = { version = "X.Y.Z", features = ["basic_tracing"] }
|
||||
nym-sdk = { git = "https://github.com/nymtech/nym", rev = "97068b2" }
|
||||
nym-bin-common = { git = "https://github.com/nymtech/nym", rev = "97068b2", features = ["basic_tracing"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
blake3 = "=1.7.0" # required pin — see https://nymtech.net/docs/developers/rust/importing
|
||||
```
|
||||
@@ -141,36 +140,19 @@ async fn main() {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let our_address = client.nym_address();
|
||||
println!("Address: {our_address}");
|
||||
println!("Address: {}", client.nym_address());
|
||||
|
||||
// Same API as before — send, receive, SURB reply.
|
||||
// Same API as before — send, receive, reply.
|
||||
client
|
||||
.send_plain_message(*our_address, "hello from persistent client!")
|
||||
.send_plain_message(*client.nym_address(), "persistent identity!")
|
||||
.await
|
||||
.unwrap();
|
||||
println!("Sent — waiting for arrival...");
|
||||
|
||||
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;
|
||||
}
|
||||
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));
|
||||
}
|
||||
};
|
||||
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.
|
||||
@@ -288,7 +270,6 @@ async fn main() {
|
||||
nym_bin_common::logging::setup_tracing_logger();
|
||||
|
||||
let paths = StoragePaths::new_from_dir("./my-client-data").unwrap();
|
||||
|
||||
let mut client = mixnet::MixnetClientBuilder::new_with_default_storage(paths)
|
||||
.await
|
||||
.unwrap()
|
||||
@@ -299,10 +280,10 @@ async fn main() {
|
||||
.unwrap();
|
||||
|
||||
let our_address = client.nym_address();
|
||||
println!("Address: {our_address}");
|
||||
println!("Connected: {our_address}");
|
||||
|
||||
client
|
||||
.send_plain_message(*our_address, "hello from persistent client!")
|
||||
.send_plain_message(*our_address, "hello from the mixnet!")
|
||||
.await
|
||||
.unwrap();
|
||||
println!("Sent — waiting for arrival...");
|
||||
@@ -317,7 +298,7 @@ async fn main() {
|
||||
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();
|
||||
client.send_reply(sender_tag, "hello back, anonymously!").await.unwrap();
|
||||
|
||||
let reply = loop {
|
||||
if let Some(msgs) = client.wait_for_messages().await {
|
||||
|
||||
@@ -9,9 +9,9 @@ lastUpdated: "2026-03-15"
|
||||
# Stream Module
|
||||
|
||||
import { Callout } from 'nextra/components'
|
||||
import { VersionBanner } from '../../../components/version-banner'
|
||||
import { CratesPaused } from '../../../components/crates-paused'
|
||||
|
||||
<VersionBanner />
|
||||
<CratesPaused />
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -89,4 +89,4 @@ There is no switching back without disconnecting and creating a new client.
|
||||
|
||||
## Internal details
|
||||
|
||||
For the full implementation details (router task, `StreamMap`, `PollSender` usage, base-client type rationale), see the `ARCHITECTURE.md` file next to the module source code, or the [docs.rs](https://docs.rs/nym-sdk/latest/nym_sdk/) API reference.
|
||||
For the full implementation details (router task, `StreamMap`, `PollSender` usage, base-client type rationale), see the `ARCHITECTURE.md` file next to the module source code. This will also be available on [docs.rs](https://docs.rs/nym-sdk/latest/nym_sdk/) once crate publication resumes with the Lewes Protocol.
|
||||
|
||||
@@ -3,14 +3,13 @@ title: "Stream Tutorial: Build a Private Echo Server"
|
||||
description: "Step-by-step Rust tutorial to build an echo server and client communicating through the Nym mixnet using AsyncRead and AsyncWrite streams."
|
||||
schemaType: "HowTo"
|
||||
section: "Developers"
|
||||
lastUpdated: "2026-04-17"
|
||||
lastUpdated: "2026-03-26"
|
||||
---
|
||||
|
||||
# Tutorial: Build a Private Echo Server
|
||||
|
||||
import { Callout } from 'nextra/components'
|
||||
import { CodeVerified } from '../../../../components/code-verified'
|
||||
import { RUST_MSRV } from '../../../../components/versions'
|
||||
|
||||
In this tutorial you'll build two programs: a server that listens for incoming streams and echoes back whatever it receives, and a client that opens a stream, sends data, and reads the echo. Both communicate through the Nym Mixnet using `AsyncRead` and `AsyncWrite`, just like TCP sockets.
|
||||
|
||||
@@ -26,7 +25,7 @@ In this tutorial you'll build two programs: a server that listens for incoming s
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Rust toolchain ({RUST_MSRV}+)
|
||||
- Rust toolchain (1.70+)
|
||||
- A working internet connection (clients connect to the live Nym Mixnet)
|
||||
|
||||
## Step 1: Set up the project
|
||||
@@ -41,8 +40,8 @@ Add dependencies to `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
nym-sdk = "X.Y.Z"
|
||||
nym-bin-common = { version = "X.Y.Z", features = ["basic_tracing"] }
|
||||
nym-sdk = { git = "https://github.com/nymtech/nym", rev = "97068b2" }
|
||||
nym-bin-common = { git = "https://github.com/nymtech/nym", rev = "97068b2", features = ["basic_tracing"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
rand = "0.8"
|
||||
blake3 = "=1.7.0" # required pin — see https://nymtech.net/docs/developers/rust/importing
|
||||
@@ -280,10 +279,7 @@ async fn main() {
|
||||
loop {
|
||||
let mut stream = match listener.accept().await {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
println!("Listener closed");
|
||||
break;
|
||||
}
|
||||
None => break,
|
||||
};
|
||||
|
||||
let stream_id = stream.id();
|
||||
@@ -291,27 +287,16 @@ async fn main() {
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut buf = vec![0u8; 32_000];
|
||||
|
||||
loop {
|
||||
let n = match stream.read(&mut buf).await {
|
||||
Ok(0) => break,
|
||||
Ok(0) | Err(_) => break,
|
||||
Ok(n) => n,
|
||||
Err(e) => {
|
||||
eprintln!("Stream {stream_id} read error: {e}");
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
let data = &buf[..n];
|
||||
println!("Stream {stream_id} received {n} bytes");
|
||||
|
||||
if let Err(e) = stream.write_all(data).await {
|
||||
eprintln!("Stream {stream_id} write error: {e}");
|
||||
if let Err(_) = stream.write_all(&buf[..n]).await {
|
||||
break;
|
||||
}
|
||||
stream.flush().await.unwrap();
|
||||
}
|
||||
|
||||
println!("Stream {stream_id} closed");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Nym TcpProxy: Route TCP via the Mixnet"
|
||||
description: "Route TCP traffic through the Nym mixnet using the TcpProxy Rust module. Covers architecture, single and multi-connection patterns, and troubleshooting."
|
||||
schemaType: "TechArticle"
|
||||
section: "Developers"
|
||||
lastUpdated: "2026-04-17"
|
||||
lastUpdated: "2026-03-27"
|
||||
---
|
||||
|
||||
# TcpProxy Module
|
||||
@@ -11,7 +11,7 @@ import { Callout } from 'nextra/components';
|
||||
import { CodeVerified } from '../../../components/code-verified'
|
||||
|
||||
<Callout type="error">
|
||||
**This module is unmaintained.** The TcpProxy is no longer actively developed in favour of the [Stream module](/developers/rust/stream), which provides `AsyncRead + AsyncWrite` streams directly over the Mixnet without the TCP socket overhead. Existing users should plan to migrate to streams when possible. The TcpProxy will continue to work but will not receive new features or bug fixes.
|
||||
**This module is unmaintained.** The TcpProxy is no longer actively developed in favour of the [Stream module](./stream), which provides `AsyncRead + AsyncWrite` streams directly over the Mixnet without the TCP socket overhead. Existing users should plan to migrate to streams when possible. The TcpProxy will continue to work but will not receive new features or bug fixes.
|
||||
</Callout>
|
||||
|
||||
The Stream module offers the same key benefit (familiar I/O patterns on top of the Mixnet) with a simpler API. Streams multiplex connections on a single client, eliminate the localhost socket overhead, and now include sequence-based message reordering. There is no remaining reason to choose TcpProxy over Streams for new projects.
|
||||
@@ -20,7 +20,7 @@ The Stream module offers the same key benefit (familiar I/O patterns on top of t
|
||||
|
||||
`NymProxyClient` and `NymProxyServer` proxy TCP traffic through the Mixnet. Both run in a background thread and expose a configurable `localhost` socket that you read and write to like any other TCP connection.
|
||||
|
||||
> Non-Rust/Go developers who want to experiment with this module can start with the [standalone binaries](/developers/tools/standalone-tcpproxy).
|
||||
> Non-Rust/Go developers who want to experiment with this module can start with the [standalone binaries](../tools/standalone-tcpproxy).
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -54,10 +54,11 @@ Add dependencies to `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
nym-sdk = "1.20.4"
|
||||
nym-network-defaults = "1.20.4"
|
||||
nym-bin-common = { version = "1.20.4", features = ["basic_tracing"] }
|
||||
nym-sdk = { git = "https://github.com/nymtech/nym", rev = "97068b2" }
|
||||
nym-network-defaults = { git = "https://github.com/nymtech/nym", rev = "97068b2" }
|
||||
nym-bin-common = { git = "https://github.com/nymtech/nym", rev = "97068b2", features = ["basic_tracing"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
anyhow = "1"
|
||||
blake3 = "=1.7.0" # required pin — see https://nymtech.net/docs/developers/rust/importing
|
||||
|
||||
[[bin]]
|
||||
@@ -77,7 +78,7 @@ The server connects to the Mixnet and forwards incoming traffic to a local TCP s
|
||||
use nym_sdk::tcp_proxy::NymProxyServer;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
nym_bin_common::logging::setup_tracing_logger();
|
||||
|
||||
let mut server = NymProxyServer::new(
|
||||
@@ -105,7 +106,7 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
nym_bin_common::logging::setup_tracing_logger();
|
||||
// Load mainnet network defaults into env vars (required by NymProxyClient's internal ClientPool)
|
||||
setup_env(None::<String>);
|
||||
@@ -168,7 +169,7 @@ The response will take 30–60 seconds to arrive as it traverses the Mixnet in b
|
||||
## Architecture
|
||||
|
||||
Each sub-module handles Nym clients differently:
|
||||
- **`NymProxyClient`** relies on the [Client Pool](/developers/rust/client-pool) to create clients and keep a reserve. If incoming TCP connections outpace the pool, it creates an ephemeral client per connection. One client maps to one TCP connection.
|
||||
- **`NymProxyClient`** relies on the [Client Pool](./client-pool) to create clients and keep a reserve. If incoming TCP connections outpace the pool, it creates an ephemeral client per connection. One client maps to one TCP connection.
|
||||
- **`NymProxyServer`** has a single Nym client with a persistent identity.
|
||||
|
||||
### Sessions & message ordering
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
The `nym-cli` binary can be built by running `cargo build --release` in the `nym/tools/nym-cli` directory.
|
||||
|
||||
## Usage
|
||||
See the [commands](/developers/tools/nym-cli/commands) page for an overview of all command options.
|
||||
See the [commands](commands.mdx) page for an overview of all command options.
|
||||
|
||||
## Staking on someone's behalf (for custodians)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Callout } from 'nextra/components'
|
||||
**Deprecated.** The TcpProxy module is no longer actively developed. The [Stream module](/developers/rust/stream) provides the same functionality (familiar `AsyncRead`/`AsyncWrite` I/O over the Mixnet) with a simpler API, multiplexed connections, and sequence-based message reordering. Use Streams for new projects.
|
||||
</Callout>
|
||||
|
||||
Standalone versions of the `TcpProxyClient` and `TcpProxyServer` [sdk module](/developers/rust/tcpproxy) can be found [here](https://github.com/nymtech/standalone-tcp-proxies/tree/main).
|
||||
Standalone versions of the `TcpProxyClient` and `TcpProxyServer` [sdk module](../rust/tcpproxy) can be found [here](https://github.com/nymtech/standalone-tcp-proxies/tree/main).
|
||||
|
||||
These might be an easy way for developers to start proxying their traffic throught the mixnet and understanding the sort of latency they should expect, and whether their application can currently tolerate it. They might also prove useful for server setups where several components are being run via init scripts, and the addition of a separate process is acceptable.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "mixFetch Example: Private HTTP Requests"
|
||||
description: "Replace browser fetch with mixFetch to route HTTP requests through the Nym mixnet. Covers setup, CA certificates, TLS configuration, and usage examples."
|
||||
description: "Replace browser fetch with mixFetch to route HTTP requests through the Nym mixnet. Covers setup, CA certificates, WSS gateways, and usage examples."
|
||||
schemaType: "TechArticle"
|
||||
section: "Developers"
|
||||
lastUpdated: "2026-03-15"
|
||||
@@ -14,9 +14,13 @@ An easy way to secure parts or all of your web app is to replace calls to [`fetc
|
||||
|
||||
Things to be aware of:
|
||||
|
||||
- **CA certificates** are bundled into the WASM binary at build time. They're updated with each SDK release — if you hit a certificate error, update to the latest `@nymproject/mix-fetch-full-fat` version.
|
||||
- **HTTPS and WSS.** When serving your app over HTTPS, the mixnet connection must also use Secure WebSockets to avoid a [mixed content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) error. Set `forceTls: true` in your `SetupMixFetchOps` config (see below) and the SDK will automatically select a WSS-capable gateway.
|
||||
- `mixFetch` supports **concurrent requests** (up to 10) to the same or different URLs.
|
||||
- CA certificates in `mixFetch` are periodically updated. If you get a certificate error, the root certificate you need might not be valid yet. [Send a PR](https://github.com/nymtech/nym/pulls) if you need changes to the certificates.
|
||||
- If you are using `mixFetch` in a web app with HTTPS, you will need to use a gateway that has Secure Websockets (WSS) to avoid a [mixed content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) error.
|
||||
- `mixFetch` supports concurrent requests (up to 10) to the same or different URLs.
|
||||
|
||||
<Callout type="info">
|
||||
Right now Gateways are not required to run a Secure Websocket (WSS) listener, so only a subset of nodes running in Gateway mode have configured their nodes to do so. You need to select a Gateway that has WSS from [Harbourmaster](https://harbourmaster.nymtech.net/).
|
||||
</Callout>
|
||||
|
||||
## Environment Setup
|
||||
|
||||
@@ -37,34 +41,30 @@ npm run dev
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @nymproject/mix-fetch-full-fat @mui/material @emotion/react @emotion/styled
|
||||
npm install @nymproject/mix-fetch-full-fat
|
||||
```
|
||||
|
||||
The MUI packages are used by the example UI below. If you only need `mixFetch` itself, install just `@nymproject/mix-fetch-full-fat`.
|
||||
|
||||
## Configuration
|
||||
|
||||
```ts
|
||||
import type { SetupMixFetchOps } from '@nymproject/mix-fetch-full-fat';
|
||||
|
||||
const mixFetchOptions: SetupMixFetchOps = {
|
||||
clientId: "my-app",
|
||||
clientId: "docs-mixfetch-demo",
|
||||
preferredGateway: "q2A2cbooyC16YJzvdYaSMH9X3cSiieZNtfBr8cE8Fi1",
|
||||
mixFetchOverride: {
|
||||
requestTimeoutMs: 60_000,
|
||||
},
|
||||
forceTls: true, // use Secure WebSockets (required when serving over HTTPS)
|
||||
forceTls: true, // force WSS
|
||||
};
|
||||
```
|
||||
|
||||
`preferredGateway` is optional — if omitted, the SDK auto-selects a gateway. You can pin a specific one via [Harbourmaster](https://harbourmaster.nymtech.net/).
|
||||
|
||||
## Full Example
|
||||
|
||||
This example shows explicit initialization via `createMixFetch`, single URL fetch, and concurrent requests. Results appear both in the UI and in a visible log panel.
|
||||
|
||||
<Callout type="info">
|
||||
For this example we use the `full-fat` version of the ESM SDK. If you use the unbundled ESM variant, make sure your [bundler configuration](/developers/typescript/bundling/bundling) copies the WASM and web worker files to the output bundle.
|
||||
For this example we use the `full-fat` version of the ESM SDK. If you use the unbundled ESM variant, make sure your [bundler configuration](../bundling/bundling) copies the WASM and web worker files to the output bundle.
|
||||
</Callout>
|
||||
|
||||
```tsx
|
||||
|
||||
@@ -43,7 +43,7 @@ npm install @nymproject/sdk-full-fat
|
||||
This example creates a Mixnet client, connects to a gateway, and provides a UI for sending and receiving messages through the mixnet.
|
||||
|
||||
<Callout type="info">
|
||||
For this example we use the `full-fat` version of the ESM SDK. If you use the unbundled ESM variant, make sure your [bundler configuration](/developers/typescript/bundling/bundling) copies the WASM and web worker files to the output bundle.
|
||||
For this example we use the `full-fat` version of the ESM SDK. If you use the unbundled ESM variant, make sure your [bundler configuration](../bundling/bundling) copies the WASM and web worker files to the output bundle.
|
||||
</Callout>
|
||||
|
||||
```ts copy filename="App.tsx"
|
||||
|
||||
@@ -60,6 +60,4 @@ Replay protection comes from WireGuard's counter-based mechanism and from zk-nym
|
||||
|
||||
dVPN mode shares infrastructure with mixnet mode. Both use the same Entry and Exit Gateways and the same credential system. The difference is in how traffic is handled: mixnet mode routes through three additional Mix Node layers with delays and cover traffic using fixed-size [Sphinx packets](/network/cryptography/sphinx), while dVPN mode routes directly between gateways using WireGuard. The two modes are distinguishable at the protocol level due to their different packet formats and traffic patterns.
|
||||
|
||||
In anonymous (5-hop) mode, NymVPN routes traffic through the full mixnet to the Exit Gateway's [IP Packet Router](/network/infrastructure/exit-services#ip-packet-router), which tunnels raw IP packets to the internet. See [Exit Gateway Services](/network/infrastructure/exit-services) for how the IPR and Network Requester work.
|
||||
|
||||
This shared infrastructure means improvements to Gateways and credentials benefit both modes.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"nyx": "Nyx Blockchain",
|
||||
"nym-nodes": "Nym Nodes",
|
||||
"exit-services": "Exit Gateway Services"
|
||||
"nym-nodes": "Nym Nodes"
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ To run a node, see the [Operator Documentation](/operators/introduction).
|
||||
|
||||
**Mix Nodes** form the three mixing layers that provide core privacy. They receive Sphinx packets, remove one encryption layer, verify integrity, apply a random delay, and forward to the next hop. Mix Nodes cannot determine their position in the route and cannot link incoming packets to outgoing packets.
|
||||
|
||||
**Exit Gateways** handle traffic leaving the mixnet. They run two proxy services: the [Network Requester](/network/infrastructure/exit-services#network-requester) (a SOCKS proxy for application-layer requests) and the [IP Packet Router](/network/infrastructure/exit-services#ip-packet-router) (a raw IP tunnel used by NymVPN and smolmix). Exit Gateways can see destination addresses but cannot identify the original sender. See [Exit Gateway Services](/network/infrastructure/exit-services) for details.
|
||||
**Exit Gateways** handle traffic leaving the mixnet. They communicate with external internet services on behalf of users and return responses through the network. Exit Gateways can see destination addresses but cannot identify the original sender.
|
||||
|
||||
## Unified binary
|
||||
|
||||
|
||||
+1126
-2017
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@
|
||||
- Node operators should use the **`nym-node`** binary. Legacy `nym-mixnode` and `nym-gateway` binaries are deprecated and no longer supported.
|
||||
- When referring to token collateral for nodes, use **"bonding"** not "staking". Nodes operate in **modes** (mixnode, entry gateway, exit gateway), not "roles".
|
||||
- The Nym blockchain is called **Nyx** and runs on Cosmos SDK. The native token is **NYM**.
|
||||
- Code examples in the Rust SDK tutorials are verified against `nym-sdk` vX.Y.Z. If in doubt, check the runnable examples in `sdk/rust/nym-sdk/examples/` in the repo.
|
||||
- Code examples in the Rust SDK tutorials are verified against `nym-sdk` v1.20.4. If in doubt, check the runnable examples in `sdk/rust/nym-sdk/examples/` in the repo.
|
||||
|
||||
## Network
|
||||
|
||||
@@ -27,14 +27,13 @@
|
||||
- [Rust SDK Overview](https://nym.com/docs/developers/rust): Module overview and quick-start for the Rust SDK
|
||||
- [Rust SDK Installation](https://nym.com/docs/developers/rust/importing): Adding nym-sdk to your Cargo.toml
|
||||
- [Mixnet Module](https://nym.com/docs/developers/rust/mixnet): Send and receive Sphinx-encrypted messages
|
||||
- [Mixnet Tutorial](https://nym.com/docs/developers/rust/mixnet/tutorial): Step-by-step — send, receive, SURBs, persistent identity
|
||||
- [Mixnet Tutorial](https://nym.com/docs/developers/rust/mixnet/tutorial): Step-by-step: connect, send, receive, anonymous reply with SURBs, persist identity
|
||||
- [Mixnet Examples](https://nym.com/docs/developers/rust/mixnet/examples): Runnable examples — simple send, SURB reply, builder, storage, parallel tasks
|
||||
- [Stream Module](https://nym.com/docs/developers/rust/stream): TCP-like AsyncRead/AsyncWrite streams over the mixnet
|
||||
- [Stream Tutorial](https://nym.com/docs/developers/rust/stream/tutorial): Build a private echo server with streams
|
||||
- [Stream Tutorial](https://nym.com/docs/developers/rust/stream/tutorial): Build a private echo server with MixnetListener and MixnetStream
|
||||
- [Client Pool](https://nym.com/docs/developers/rust/client-pool): Pre-warm MixnetClients for bursty workloads
|
||||
- [Client Pool Tutorial](https://nym.com/docs/developers/rust/client-pool/tutorial): Handle bursty traffic with pooled clients
|
||||
- [Client Pool Tutorial](https://nym.com/docs/developers/rust/client-pool/tutorial): Handle concurrent operations with pooled clients
|
||||
- [TcpProxy Module](https://nym.com/docs/developers/rust/tcpproxy): Tunnel existing TCP services through the mixnet (unmaintained — use stream instead)
|
||||
- [smolmix](https://nym.com/docs/developers/smolmix): TCP/UDP over the mixnet via a userspace IP stack — drop-in TcpStream and UdpSocket (see examples in source)
|
||||
- [TypeScript SDK](https://nym.com/docs/developers/typescript): Browser and Node.js SDK using WebAssembly
|
||||
- [mix-fetch](https://nym.com/docs/developers/typescript/examples/mix-fetch): Drop-in fetch() replacement that routes HTTP through the mixnet
|
||||
|
||||
|
||||
Reference in New Issue
Block a user