Merge branch 'max/new-docs-framework' into yana/nextra-config

This commit is contained in:
Yana
2024-10-17 16:48:18 +03:00
176 changed files with 22402 additions and 1287 deletions
+18 -22
View File
@@ -1,30 +1,27 @@
# Documentation
# Nym Docs v2
This is v2 of the nym docs, condensed from various mdbooks projects that we had previously.
These docs are hosted at [nymtech.net/docs](www.nymtech.net/docs).
## Doc projects
Each directory contains a readme with more information about running and contributing to the projects. Each is built with [`mdbook`](https://rust-lang.github.io/mdBook/index.html) - use `mdbook serve` to build and serve them (defaults to `localhost:3000`).
* `docs` contains technical documentation hosted at [https://nymtech.net/docs](https://nymtech.net/docs)
* `dev-portal` contains developer documentation hosted at [https://nymtech.net/developers](https://nymtech.net/developers)
* `operators` contains node setup and maintenance guides hosted at [https://nymtech.net/operators](https://nymtech.net/operators)
`docs/pages/` contains several subdirs, each hosting a subsection of the docs:
* `network` contains key concepts, cryptosystems, architecture.
* `developers` contains key concepts for developers, required architecture, and Rust/Typescript SDK docs.
* `operators` contains node setup and maintenance guides.
> If you are looking for the Typescript SDK documentation located at [sdk.nymtech.net](https://sdk.nymtech.net) this can be found in `../sdk/typescript/docs/`
## Contribution
* If you wish to add to the documentation please create a PR against this repo, with a `patch` against `develop`.
## Contribution
* If you wish to add to the documentation please create a PR against this repo.
* If you are **adding a plugin dependency** make sure to also **add that to the list of plugins in `install_mdbook_deps.sh` line 12**.
## Scripts
* There are several autogenerated command files for clients and binaries. These are generated with `generate:commands`, which runs the `autodoc` rust binary, moves the files to their required places, and then if there is an update, commits them to git. This is for remote deployments.
* TODO
## Scripts
* `bump_versions.sh` allows you to update the ~~`platform_release_version` and~~ `wallet_release_version` variable~~s~~ in the `book.toml` of each mdbook project at once. You can also optionally update the `minimum_rust_version` as well. Helpful for lazy-updating when cutting a new version of the docs.
### Autodoc
`autodoc` is a script that generates markdown files containing commands and their output (both command and `--help` output). For the moment the binaries and their commands are manually configured in the script.
* The following scripts are used by the `ci-dev.yml` and `cd-dev.yml` scripts (located in `../.github/workflows/`):
* `build_all_to_dist.sh` is used for building all mdbook projects and moving the rendered html to `../dist/` to be rsynced with various servers.
* `install_mdbook_deps.sh` checks for an existing install of mdbook (and plugins), uninstalls them, and then installs them on a clean slate. This is to avoid weird dependency clashes if relying on an existing mdbook version.
* `post_process.sh` is used to post process CSS/image/href links for serving several mdbooks from a subdirectory.
* `removed_existing_config.sh` is used to check for existing nym client/node config files on the CI/CD server and remove it if it exists. This is to mitigate issues with `mdbook-cmdrun` where e.g. a node is already initialised, and the command fails.
## CI/CD
Deployment of the docs is partially automated and partially manual.
* `ci-docs.yml` will run on pushes to all branches **apart from `master`**
* `cd-docs.yml` must be run manually. This pushes to a staging branch which then must be manually promoted to production.
## CI/CD
TODO
## Licensing and copyright information
This is a monorepo and components that make up Nym as a system are licensed individually, so for accurate information, please check individual files.
@@ -36,4 +33,3 @@ As a general approach, licensing is as follows this pattern:
* Nym applications and binaries are [GPL-3.0-only](https://www.gnu.org/licenses/)
* Used libraries and different components are [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0.html) or [MIT](https://mit-license.org/)
+6 -8
View File
@@ -125,13 +125,12 @@ fn main() -> io::Result<()> {
let mut file = File::create(format!("{}/{}-commands.md", WRITE_PATH, last_word.unwrap()))?;
writeln!(
file,
"# {} Binary Commands",
"# {} Binary Commands (Autogenerated)",
format!("`{}`", last_word.unwrap())
)?;
writeln!(
file,
"\nThese docs are autogenerated by the `autodocs` script.
\n**TODO add link**"
"\nThese docs are autogenerated by the [`autodocs`](https://github.com/nymtech/nym/tree/max/new-docs-framework/documentation/autodoc) script."
)?;
let output = Command::new(main_command).arg("--help").output()?;
write_output_to_file(&mut file, output)?;
@@ -148,20 +147,19 @@ fn main() -> io::Result<()> {
let mut file = File::create(format!("{}/{}-commands.md", WRITE_PATH, last_word.unwrap()))?;
writeln!(
file,
"# {} Binary Commands",
"# {} Binary Commands (Autogenerated)",
format!("`{}`", last_word.unwrap())
)?;
writeln!(
file,
"\nThese docs are autogenerated by the `autodocs` script.
\n**TODO add link**"
"\nThese docs are autogenerated by the [`autodocs`](https://github.com/nymtech/nym/tree/max/new-docs-framework/documentation/autodoc) script."
)?;
let output = Command::new(main_command).arg("--help").output()?;
write_output_to_file(&mut file, output)?;
for (subcommand, subsubcommands) in subcommands {
writeln!(file, "\n### `{}` ", subcommand)?;
writeln!(file, "\n## `{}` ", subcommand)?;
let output = Command::new(main_command)
.arg(subcommand)
.arg("--help")
@@ -250,7 +248,7 @@ fn execute_command(
}
fn write_output_to_file(file: &mut File, output: Output) -> io::Result<()> {
writeln!(file, "```")?;
writeln!(file, "```sh")?;
file.write_all(&output.stdout)?;
writeln!(file, "```")?;
-51
View File
@@ -1,51 +0,0 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
# this is a script called by the github CI and CD workflows to build all 3 docs projects
# and move them to /dist/ in the root of the monorepo. They are rsynced to various servers
# from there by subsequent workflow tasks.
# array of project dirs
declare -a projects=("docs" "dev-portal" "operators")
# check you're calling from the right place
if [ $(pwd | awk -F/ '{print $NF}') != "documentation" ]
then
echo "failure: please run script from documentation/"
else
for i in "${projects[@]}"
do
# cd to project dir
cd "./$i" &&
# little sanity checks
echo $(pwd) && echo $(mdbook --version) &&
# clean old book
echo "cleaning old book"
rm -rf ./book/
# build book
# mdbook test || true
mdbook build
# check for destination, if ! then mkdir & check again else echo thumbs up
if [ ! -d ../../dist/docs/$i ]; then
echo "dest doesn't exist: creating dir"
mkdir -p ../../dist/docs/$i
fi
if [ -d ../../dist/docs/$i ]; then
echo "cp destination exists, all good"
fi
# clean old dist/$i
rm -rf ../../dist/docs/$i
# move newly rendered book/ to dist
rsync -r ./book/html/ ../../dist/docs/$i
# sanity check
ls -laF ../../dist/docs/
# cd back to ../documentation/
cd ../
done
# rename for server paths
rm -rf ../dist/docs/developers
mv ../dist/docs/dev-portal ../dist/docs/developers
fi
-45
View File
@@ -1,45 +0,0 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
# takes one manadatory arg and one optional arg: wallet release and minimum rust versions
# it then uses sed to bump them in the three book.toml files.
#
# e.g if the upcoming wallet release version was 1.2.9 you'd run this as:
# `./bump_versions.sh "1.2.9"`
#
# you can also set the minumum rust version by passing an optional additional argument:
# `./bump_versions.sh "1.2.9" "1.67"`
# array of project dirs
declare -a projects=("docs" "dev-portal" "operators")
# check number of args passed
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ];
then
echo "failure: please pass at least 1 and at most 2 args: "
echo "./bump_version.sh <new wallet_release_version> [OPTIONAL]<new minimum_rust_version>"
exit 0
fi
# check you're calling from the right place
if [ $(pwd | awk -F/ '{print $NF}') != "documentation" ]
then
echo "failure: please run script from documentation/"
exit 0
else
## now loop through the above array sed-ing the variable values in the book.toml files
for i in "${projects[@]}"
do
# sed the vars in the book.toml file for each project
echo "setting wallet version in $i/"
sed -i 's/wallet_release_version =.*/wallet_release_version = "'$2'"/' "$i"/book.toml
if [ "$3" ]
then
echo "setting minimum rust version in $i/"
sed -i 's/minimum_rust_version = .*/minimum_rust_version = "'$3'"/' "$i"/book.toml
fi
done
fi
+17 -1
View File
@@ -9,7 +9,15 @@ npm i
npm run dev
```
Open http://localhost:3000 to browse the output that will hot-reload when you make changes.
Open `http://localhost:3000` to browse the output that will hot-reload when you make changes.
If you are cutting a new version with binaries that have updated commands (and you have updated the command list in `autodocs`) run:
```
npm generate:commands
```
This will regenerate the md command files for the binaries, move them into position, and then commit them to the branch head.
## Build
@@ -19,6 +27,14 @@ npm run build
The static output will be in `./out`;
If you are cutting a new version with binaries that have updated commands (and you have updated the command list in `autodocs`) **run this first**:
```
npm generate:commands
```
This will regenerate the md command files for the binaries, move them into position, and then commit them to the branch head.
## Template details
This documentation was made with [Nextra](https://nextra.site) using the template from here https://github.com/shuding/nextra-docs-template.
+18 -19
View File
@@ -11,39 +11,42 @@ import operatorGuide from "./images/operator-guide.png";
export const LandingPage = () => {
const squares = [
{
text: "Network",
description: "The NYM utility token is the native token.",
text: "Network Docs",
description: "Architecture, crypto systems, and how the Mixnet works",
href: "/network",
icon: networkDocs,
icon: developerDocs,
},
{
text: "Operators",
text: "Operator Guides",
description:
"The NYM utility token is the native token of the mixnet. Learn",
"Guides and maintenance: if you want to run a node, start here",
href: "/operators",
icon: operatorGuide,
},
{
text: "SDKs",
text: "Developer Portal",
description:
"The NYM utility token is the native token of the mixnet. Learn",
"Conceptual overview, clients, and tools for developers and integrations",
href: "/developers",
icon: networkDocs,
},
{
text: "SDKs",
description: "Rust and Typescript SDK docs",
href: "/developers/rust",
icon: sdkDocs,
},
{
text: "Developers",
description:
"The NYM utility token is the native token of the mixnet. Learn",
href: "/developers",
icon: developerDocs,
},
];
return (
<Box maxWidth={1200} margin={"0 auto"}>
<Typography variant="h2" mb={6}>
Nym Docs
</Typography>
<Typography mb={10}>
Nym is a privacy platform. It provides strong network-level privacy
against sophisticated end-to-end attackers, and anonymous access control
@@ -51,10 +54,6 @@ export const LandingPage = () => {
to allow developers to build new applications, or upgrade existing apps,
with privacy features unavailable in other systems.
</Typography>
<Typography variant="h2" mb={6}>
Nym Docs
</Typography>
<Grid container border={"1px solid #262626"}>
{squares.map((square, index) => (
<Grid
@@ -1,11 +1,9 @@
import { Box } from "@mui/material";
import Image from "next/image";
import Link from "next/link";
import matrixLogo from "./matrix-logo.png";
import matrixLogo from "../images/matrix-logo.png";
export const Matrix = () => {
return (
// <Box marginRight={3} height={24} width={24}>
<Link
href={"https://matrix.to/#/#dev:nymtech.chat"}
target="_blank"
@@ -13,6 +11,5 @@ export const Matrix = () => {
>
<Image src={matrixLogo} alt={"Matrix Logo"} width={20} height={24} />
</Link>
// </Box>
);
};
+21 -17
View File
@@ -1,26 +1,25 @@
import React, { useState } from 'react';
import CircularProgress from '@mui/material/CircularProgress';
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import { mixFetch } from '@nymproject/mix-fetch-full-fat';
import Stack from '@mui/material/Stack';
import Paper from '@mui/material/Paper';
import type { SetupMixFetchOps } from '@nymproject/mix-fetch-full-fat';
import React, { useState } from "react";
import CircularProgress from "@mui/material/CircularProgress";
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
import { mixFetch } from "@nymproject/mix-fetch-full-fat";
import Stack from "@mui/material/Stack";
import Paper from "@mui/material/Paper";
import type { SetupMixFetchOps } from "@nymproject/mix-fetch-full-fat";
const defaultUrl = 'https://nymtech.net/favicon.svg';
const args = { mode: 'unsafe-ignore-cors' };
const defaultUrl = "https://nymtech.net/favicon.svg";
const args = { mode: "unsafe-ignore-cors" };
const mixFetchOptions: SetupMixFetchOps = {
preferredGateway: '6Gb7ftQdKveMjPyrxDXeAtfYAX7Zg5mVZHtnRC5MmZ1B', // with WSS
preferredGateway: "6Gb7ftQdKveMjPyrxDXeAtfYAX7Zg5mVZHtnRC5MmZ1B", // with WSS
preferredNetworkRequester:
'8rRGWy54oC8drFL9DepMegBt2DLrsqQwCoHMXt9nsnTo.2XjCPVbb4FpQ9hNRcXwb9mTzEAVVk1zf1tcch3wdtNEA@6Gb7ftQdKveMjPyrxDXeAtfYAX7Zg5mVZHtnRC5MmZ1B',
"8rRGWy54oC8drFL9DepMegBt2DLrsqQwCoHMXt9nsnTo.2XjCPVbb4FpQ9hNRcXwb9mTzEAVVk1zf1tcch3wdtNEA@6Gb7ftQdKveMjPyrxDXeAtfYAX7Zg5mVZHtnRC5MmZ1B",
mixFetchOverride: {
requestTimeoutMs: 60_000,
},
forceTls: true, // force WSS
extra: {},
};
export const MixFetch = () => {
@@ -44,7 +43,7 @@ export const MixFetch = () => {
};
return (
<div style={{ marginTop: '1rem' }}>
<div style={{ marginTop: "1rem" }}>
<Stack direction="row">
<TextField
disabled={busy}
@@ -55,7 +54,12 @@ export const MixFetch = () => {
defaultValue={defaultUrl}
onChange={(e) => setUrl(e.target.value)}
/>
<Button variant="outlined" disabled={busy} sx={{ marginLeft: '1rem' }} onClick={handleFetch}>
<Button
variant="outlined"
disabled={busy}
sx={{ marginLeft: "1rem" }}
onClick={handleFetch}
>
Fetch
</Button>
</Stack>
-6
View File
@@ -1,6 +0,0 @@
import { Tabs } from "nextra/components";
export const MyTab = ({ name, children }) => (
<Tabs.Tab>
{name} {children}
</Tabs.Tab>
);
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

+7 -7
View File
@@ -1,12 +1,13 @@
{
"name": "@nymproject/docs",
"version": "1.0.0",
"description": "Nym Docs Monorepo",
"name": "Nym Docs",
"version": "1.5-rc.0",
"description": "Nym Docs",
"license": "Apache-2.0",
"author": "Nym Technologies SA",
"scripts": {
"generate:commands": "../scripts/next-scripts/autodoc.sh",
"build": "next build",
"dev": "next dev",
"dev": " next dev",
"lint": "next lint",
"lint:fix": "next lint --fix",
"start": "next start"
@@ -34,10 +35,9 @@
"@nymproject/sdk-full-fat": ">=1.2.4-rc.2 || ^1",
"chain-registry": "^1.19.0",
"cosmjs-types": "^0.9.0",
"lucide-react": "^0.438.0",
"next": "^13.4.19",
"nextra": "latest",
"nextra-theme-docs": "latest",
"nextra": "2",
"nextra-theme-docs": "2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"save": "^2.9.0",
@@ -1,31 +0,0 @@
{
"index": {
"display": "hidden"
},
"network": {
"title": "Network",
"type": "page"
},
"developers": {
"title": "Developers",
"type": "page"
},
"sdk": {
"title": "SDKs",
"type": "menu",
"items": {
"rust": {
"title": "Rust SDK",
"href": "/sdk/rust"
},
"typescript": {
"title": "Typescript SDK",
"href": "/sdk/typescript"
}
}
},
"operators": {
"title": "Operators",
"type": "page"
}
}
+9 -1
View File
@@ -1,6 +1,7 @@
module.exports = {
"index": "Introduction",
"concepts": "Core Concepts",
"binaries": "Binaries",
"integrations": "Integration Options",
"clients": "Clients",
"tools": "Tools",
@@ -13,5 +14,12 @@ module.exports = {
"---": {
"type": "separator"
},
<<<<<<< HEAD:documentation/docs/pages/developers/_meta.js
"licensing": "Licensing"
};
};
=======
"archive": "Archive",
"licensing": "Licensing",
"coc": "Coc"
}
>>>>>>> max/new-docs-framework:documentation/docs/pages/developers/_meta.json
@@ -0,0 +1,85 @@
# Archive page: NymConnect Setup
```admonish warning
Since the beginning of 2024 NymConnect is no longer maintained. Nym is developing a new client called [NymVPN](https://nymvpn.com), an application routing all users traffic thorugh the mixnet.
If users want to route their traffic through socks5 we advice to use maintained [Nym Socks5 Client](../clients/socks5/setup.md).
```
In case you want to run deprecated NymConnect, follow these steps:
1. Navigate to our [Github repository](https://github.com/nymtech/nym/releases?q=nym-connect&expanded=true) and download NymConnect binary
2. On Linux and Mac, make executable by opening terminal in the same directory and run:
```sh
chmod +x ./nym-connect_<VERSION>.AppImage
```
1. Start the application
2. Click on `Connect` button to initialise the connection with the Mixnet
3. Anytime you'll need to setup Host and Port in your applications, click on `IP` and `Port` to copy the values to clipboard
4. In case you have problems such as `Gateway Issues`, try to reconnect or restart the application
## Connect Privacy Enhanced Applications (PEApps)
Here are some examples of applications which will work behind Socks5 proxy (`nym-socks5-client` or deprecated NymConnect), to enhance users privacy.
### Electrum Bitcoin wallet via NymConnect
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`](../clients/socks5/setup.md))
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
5. Now your Electrum Bitcoin wallet runs through the Mixnet and it will be connected only if your NymConnect or `nym-socks5-client` are connected.
![Electrum Bitcoin wallet setup](../images/electrum_tutorial/electrum.gif)
### Monero wallet via NymConnect
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`](../clients/socks5/setup.md))
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.
![Monero wallet setup](../images/monero_tutorial/monero-gui-NC.gif)
### Matrix (Element) via NymConnect
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`](../clients/socks5/setup.md))
2. Start `element-desktop` with `--proxy-server` argument:
**Linux**
```sh
element-desktop --proxy-server=socks5://127.0.0.1:1080
```
**Mac**
```sh
open -a Element --args --proxy-server=socks5://127.0.0.1:1080
```
To make the start of Element over NymConnect simplier, you can add this command to your key-binding shortcuts in your system settings.
### Telegram via NymConnect
1. Start and connect NymConnect (or [`nym-socks5-client`](../clients/socks5/setup.md))
2. Start your Telegram chat application
3. Open the Telegram proxy settings.
- Linux: *Settings* -> *Advanced* -> *Connection type* -> *Use custom proxy*
- MacOS: *Settings* -> *Advanced* -> *Data & Storage* -> *Connection Type* -> *Use custom Proxy*
- Windows: *Settings* -> *Data and Storage* -> *Use proxy*
4. Add a proxy with the *Add proxy button*.
5. Select *SOCKS5* and make sure the port details are the same as those generated by NymConnect. Alternatively, follow this link: [https://t.me/socks?server=127.0.0.1&port=1080](https://t.me/socks?server=127.0.0.1&port=1080)
6. *Save the proxy settings* in Telegram.
7. Telegram is now running through the Nym Mixnet and is privacy-enhanced! This allows you to connect from regions which blocked Telegram.
8. Note if you remain idle on Telegram for a while you might lose connectivity and your messages might not get through via SOCKS5 proxy. If that happens reconnect your NymConnect and reset the proxy again.
Follow this [video](https://youtu.be/quj8H2qeOwY?t=97) to see the steps on Telegram setup.
@@ -0,0 +1,38 @@
# NymVPN alpha
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/897010658?h=1f55870fe6&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" style="position:absolute;top:0;left:0;width:100%;height:100%;" title="NYMVPN alpha demo 37C3"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
```admonish tip title="web3summit testing"
**If you testing NymVPN CLI on Web3 Summit Berlin, visit our event page with all info tailored for the event: [nym-vpn-cli.sandbox.nymtech.net](https://nym-vpn-cli.sandbox.nymtech.net/).**
```
**NymVPN alpha** is a client that uses [Nym Mixnet](https://nymtech.net) to anonymise all of a user's internet traffic through either a 5-hop mixnet (for a full network privacy) or the faster 2-hop decentralised VPN (with some extra features).
**You are invited to take part in the alpha testing** of this new application. Register for private testing round at [nymvpn.com](https://nymvpn.com/en), that will grant you access to the [download page](https://nymvpn.com/download). Visit [NymVPN Support & FAQ](https://nymvpn.com/en/support) or join the [NymVPN matrix channel](https://matrix.to/#/#NymVPN:nymtech.chat) if you have any questions, comments or blockers.
Checkout the [release page](https://github.com/nymtech/nym-vpn-client/releases) for available binaries.
*NOTE: NymVPN alpha is experimental software for testing purposes only.*
## NymVPN Overview
To understand what's under the hood of NymVPN and the mixnet, we recommend interested developers to begin with [Nym network overview](https://nymtech.net/docs/architecture/network-overview.html) and the [Mixnet traffic flow](https://nymtech.net/docs/architecture/traffic-flow.html) pages.
The default setup of NymVPN is to run in 5-hop mode (mixnet):
```
┌─►mix──┐ mix mix
│ │
Entry │ │ Exit
client ───► Gateway ──┘ mix │ mix ┌─►mix ───► Gateway ───► internet
│ │
│ │
mix └─►mix──┘ mix
```
Users can switch to 2-hop only mode, which is a faster but less private option. In this mode traffic is only sent between the two Gateways, and is not passed between Mix Nodes. It uses Mixnet Sphinx packets with shorter, fixed routes, which improve latency, but doesn't offer the same level of protection as the 5 hop mode.
<!-- TO BE IMPLEMENTED:
Users can switch to 2-hop only mode, which is a faster but less private option. In this mode traffic is only sent between the two Gateways, and is not passed between Mix Nodes. The client than use two wireguard tunnels with the entry and exit gateway, the Exit Gateway one being tunnelled itself through the entry gateway tunnel. NymVPN uses Mullvad libraries for wrapping `wireguard-go` and to setup local routing rules to route all traffic to the TUN virtual network device.
-->
@@ -0,0 +1,142 @@
# NymVPN alpha CLI Guide
```admonish info
NymVPN is an experimental software and it's for testing purposes only. All users testing the client are expected to sign GDPR Information Sheet and Consent Form (shared at the workshop) so we use their results to improve the client, and submit the form [*NymVPN User research*]({{nym_vpn_form_url}}) with the testing results.
```
## Installation
> Any syntax in `<>` brackets is a user's/version unique variable. Exchange with a corresponding name without the `<>` brackets.
1. Open Github [releases page]({{nym_vpn_releases}}) and download the CLI latest binary for your system
2. Verify sha hash of your downloaded binary with the one listed on the [releases page]({{nym_vpn_releases}}). You can use a simple `shasum` command and compare strings (ie with Python) or run in the same directory the following command, exchanging `<SHA_STRING>` with the one of your binary, like in the example:
```sh
echo "<SHA_STRING>" | shasum -a 256 -c
# choose a correct one according to your binary, this is just an example
# echo "0e4abb461e86b2c168577e0294112a3bacd3a24bf8565b49783bfebd9b530e23 nym-vpn-cli_<!-- cmdrun scripts/nym_vpn_cli_version.sh -->_ubuntu-22.04_amd64.tar.gz" | shasum -a 256 -c
```
3. Extract files:
```sh
tar -xvf <BINARY>.tar.gz
# for example
# tar -xvf nym-vpn-cli_<!-- cmdrun scripts/nym_vpn_cli_version.sh -->_ubuntu-22.04_x86_64.tar.gz
```
4. Make executable:
```sh
# make sure you are in the right sub-directory
chmod u+x ./nym-vpn-cli
```
## Run NymVPN
**For NymVPN to work, all other VPNs must be switched off!** At this alpha stage of NymVPN, the network connection (wifi) must be reconnected after or in between the testing rounds.
Make sure your terminal is open in the same directory as your `nym-vpn-cli` binary.
1. Go to [nymvpn.com/en/alpha](https://nymvpn.com/en/alpha) to get the entire command with all the needed arguments' values and your wireguard private key for testing purposes
2. Run it as root with `sudo` - the command will look like this with specified arguments:
```sh
sudo ./nym-vpn-cli -c ./sandbox.env --entry-gateway-id <ENTRY_GATEWAY_ID> --exit-router-address <EXIT_ROUTER_ADDRESS> --enable-wireguard --private-key <PRIVATE_KEY> --wg-ip <WIREGUARD_IP>
```
3. To choose different Gateways, visit [explorer.nymtech.net/network-components/gateways](https://explorer.nymtech.net/network-components/gateways) and copy-paste an identity key of your choice
4. See all possibilities in [command explanation](#cli-commands-and-options) section below
In case of errors, see [troubleshooting section](troubleshooting.md).
### CLI Commands and Options
The basic syntax of `nym-vpn-cli` is:
```sh
sudo ./nym-vpn-cli <--exit-router-address <EXIT_ROUTER_ADDRESS>|--exit-gateway-id <EXIT_GATEWAY_ID>|--exit-gateway-country <EXIT_GATEWAY_COUNTRY>>
```
* To choose different Gateways, visit [nymvpn.com/en/alpha/api/gateways](https://explorer.nymtech.net/network-components/gateways)
* To see all possibilities run with `--help` flag:
```sh
./nym-vpn-cli --help
```
~~~admonish example collapsible=true title="Console output"
```sh
Usage: nym-vpn-cli [OPTIONS] <--exit-router-address <EXIT_ROUTER_ADDRESS>|--exit-gateway-id <EXIT_GATEWAY_ID>|--exit-gateway-country <EXIT_GATEWAY_COUNTRY>>
Options:
-c, --config-env-file <CONFIG_ENV_FILE>
Path pointing to an env file describing the network
--mixnet-client-path <MIXNET_CLIENT_PATH>
Path to the data directory of a previously initialised mixnet client, where the keys reside
--entry-gateway-id <ENTRY_GATEWAY_ID>
Mixnet public ID of the entry gateway
--entry-gateway-country <ENTRY_GATEWAY_COUNTRY>
Auto-select entry gateway by country ISO
--entry-gateway-low-latency
Auto-select entry gateway by latency
--exit-router-address <EXIT_ROUTER_ADDRESS>
Mixnet recipient address
--exit-gateway-id <EXIT_GATEWAY_ID>
--exit-gateway-country <EXIT_GATEWAY_COUNTRY>
Mixnet recipient address
--enable-wireguard
Enable the wireguard traffic between the client and the entry gateway
--private-key <PRIVATE_KEY>
Associated private key
--wg-ip <WG_IP>
The IP address of the wireguard interface used for the first hop to the entry gateway
--nym-ipv4 <NYM_IPV4>
The IPv4 address of the nym TUN device that wraps IP packets in sphinx packets
--nym-ipv6 <NYM_IPV6>
The IPv6 address of the nym TUN device that wraps IP packets in sphinx packets
--nym-mtu <NYM_MTU>
The MTU of the nym TUN device that wraps IP packets in sphinx packets
--disable-routing
Disable routing all traffic through the nym TUN device. When the flag is set, the nym TUN device will be created, but to route traffic through it you will need to do it manually, e.g. ping -Itun0
--enable-two-hop
Enable two-hop mixnet traffic. This means that traffic jumps directly from entry gateway to exit gateway
--enable-poisson-rate
Enable Poisson process rate limiting of outbound traffic
--disable-background-cover-traffic
Disable constant rate background loop cover traffic
-h, --help
Print help
-V, --version
Print version
```
~~~
Here is a list of the options and their descriptions. Some are essential, some are more technical and not needed to be adjusted by users.
**Fundamental commands and arguments**
- `-c` is a path to the [Sandbox config](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) file saved as `sandbox.env`
- `--entry-gateway-id`: paste one of the values labeled with a key `"identityKey"` (without `" "`) from [here](https://nymvpn.com/en/alpha/api/gateways)
- `--exit-router-address`: paste one of the values labeled with a key `"address"` (without `" "`) from here [here](https://nymvpn.com/en/alpha/api/gateways)
- `--enable-wireguard`: Enable the wireguard traffic between the client and the entry gateway. NymVPN uses Mullvad libraries for wrapping `wireguard-go` and to setup local routing rules to route all traffic to the TUN virtual network device
- `--wg-ip`: The address of the wireguard interface, you can get it [here](https://nymvpn.com/en/alpha)
- `--private-key`: get your private key for testing purposes [here](https://nymvpn.com/en/alpha)
- `--enable-two-hop` is a faster setup where the traffic is routed from the client to Entry Gateway and directly to Exit Gateway (default is 5-hops)
**Advanced options**
- `--enable-poisson`: Enables process rate limiting of outbound traffic (disabled by default). It means that NymVPN client will send packets at a steady stream to the Entry Gateway. By default it's on average one sphinx packet per 20ms, but there is some randomness (poisson distribution). When there are no real data to fill the sphinx packets with, cover packets are generated instead.
- `--ip` is the IP address of the TUN device. That is the IP address of the local private network that is set up between local client and the Exit Gateway.
- `--mtu`: The MTU of the TUN device. That is the max IP packet size of the local private network that is set up between local client and the Exit Gateway.
- `--disable-routing`: Disable routing all traffic through the VPN TUN device.
## Testnet environment
If you want to run NymVPN CLI in Nym Sandbox environment, there are a few adjustments to be done:
1. Create Sandbox environment config file by saving [this](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) as `sandbox.env` in the same directory as your NymVPN binaries by running:
```sh
curl -o sandbox.env -L https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env
```
1. Check available Gateways at [nymvpn.com/en/alpha/api/gateways](https://nymvpn.com/en/alpha/api/gateways)
2. Run with a flag `-c`
```sh
sudo ./nym-vpn-cli -c <PATH_TO>/sandbox.env <--exit-router-address <EXIT_ROUTER_ADDRESS>|--exit-gateway-id <EXIT_GATEWAY_ID>|--exit-gateway-country <EXIT_GATEWAY_COUNTRY>>
```
@@ -0,0 +1,123 @@
# NymVPN alpha CLI: Guide for MacOS
```admonish info
NymVPN is an experimental software and it's for testing purposes only. All users testing the client are expected to sign GDPR Information Sheet and Consent Form (shared at the workshop) so we use their results to improve the client, and submit the form [*NymVPN User research*]({{nym_vpn_form_url}}) with the testing results.
```
## Preparation
> Any syntax in `<>` brackets is a user's/version unique variable. Exchange with a corresponding name without the `<>` brackets.
1. Open Github [releases page]({{nym_vpn_releases}}) and download the binary for MacOS
2. Verify sha hash of your downloaded binary with the one listed on the [releases page]({{nym_vpn_releases}}). You can use a simple `shasum` command and compare strings (ie with Python) or run in the same directory the following command, exchanging `<SHA_STRING>` with the one of your binary, like in the example:
```sh
echo "<SHA_STRING>" | shasum -a 256 -c
# choose a correct one according to your binary, this is just an example
# echo "96623ccc69bc4cc0e4e3e18528b6dae6be69f645d0a592d926a3158ce2d0c269 nym-vpn-cli_<!-- cmdrun scripts/nym_vpn_cli_version.sh -->_macos_x86_64.zip" | shasum -a 256 -c
```
3. Extract files:
```sh
tar -xvf <BINARY>
# for example
# tar -xvf nym-vpn-cli_<!-- cmdrun scripts/nym_vpn_cli_version.sh -->_macos_aarch64.tar.gz
```
4. Make executable by running:
```sh
# possibly you may have to cd into a sub-directory
chmod u+x ./nym-vpn-cli
```
5. Create Sandbox environment config file by saving [this](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) as `sandbox.env` in the same directory as your NymVPN binaries by running:
```sh
curl -L "https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env" -o sandbox.env
```
## Run NymVPN
**For NymVPN to work, all other VPNs must be switched off!** At this alpha stage of NymVPN, the network connection (wifi) must be reconnected after or in between the testing rounds.
Make sure your terminal is open in the same directory as your `nym-vpn-cli` binary.
1. Go to [nymvpn.com/en/alpha](https://nymvpn.com/en/alpha) to get the entire command with all the needed arguments' values and your wireguard private key for testing purposes
2. Run it as root with `sudo` - the command will look like this with specified arguments:
```sh
sudo ./nym-vpn-cli -c ./sandbox.env --entry-gateway-id <ENTRY_GATEWAY_ID> --exit-router-address <EXIT_ROUTER_ADDRESS> --enable-wireguard --private-key <PRIVATE_KEY> --wg-ip <WIREGUARD_IP>
```
3. To choose different Gateways, visit [nymvpn.com/en/alpha/api/gateways](https://nymvpn.com/en/alpha/api/gateways) and pick one
4. See all possibilities in [command explanation](#cli-commands-and-options) section below
In case of errors, see [troubleshooting section](troubleshooting.md).
### CLI Commands and Options
The basic syntax of `nym-vpn-cli` is:
```sh
sudo ./nym-vpn-cli -c ./sandbox.env --entry-gateway-id <ENTRY_GATEWAY_ID> --exit-router-address <EXIT_ROUTER_ADDRESS> --enable-wireguard --private-key <PRIVATE_KEY> --wg-ip <WG_IP>
```
* To choose different Gateways, visit [nymvpn.com/en/alpha/api/gateways](https://nymvpn.com/en/alpha/api/gateways)
* To see all possibilities run with `--help` flag:
```sh
./nym-vpn-cli --help
```
~~~admonish example collapsible=true title="Console output"
```sh
Usage: nym-vpn-cli [OPTIONS]
Options:
-c, --config-env-file <CONFIG_ENV_FILE>
Path pointing to an env file describing the network
--mixnet-client-path <MIXNET_CLIENT_PATH>
Path to the data directory of a previously initialised mixnet client, where the keys reside
--entry-gateway-id <ENTRY_GATEWAY_ID>
Mixnet public ID of the entry gateway
--entry-gateway-country <ENTRY_GATEWAY_COUNTRY>
Auto-select entry gateway by country ISO
--exit-router-address <EXIT_ROUTER_ADDRESS>
Mixnet recipient address
--exit-gateway-id <EXIT_GATEWAY_ID>
--exit-router-country <EXIT_ROUTER_COUNTRY>
Mixnet recipient address
--enable-wireguard
Enable the wireguard traffic between the client and the entry gateway
--private-key <PRIVATE_KEY>
Associated private key
--wg-ip <WG_IP>
The IP address of the wireguard interface used for the first hop to the entry gateway
--nym-ip <NYM_IP>
The IP address of the nym TUN device that wraps IP packets in sphinx packets
--nym-mtu <NYM_MTU>
The MTU of the nym TUN device that wraps IP packets in sphinx packets
--disable-routing
Disable routing all traffic through the nym TUN device. When the flag is set, the nym TUN device will be created, but to route traffic through it you will need to do it manually, e.g. ping -Itun0
--enable-two-hop
Enable two-hop mixnet traffic. This means that traffic jumps directly from entry gateway to exit gateway
--enable-poisson-rate
Enable Poisson process rate limiting of outbound traffic
--disable-background-cover-traffic
Disable constant rate background loop cover traffic
-h, --help
Print help
-V, --version
Print version
```
~~~
Here is a list of the options and their descriptions. Some are essential, some are more technical and not needed to be adjusted by users.
**Fundamental commands and arguments**
- `-c` is a path to the [Sandbox config](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) file saved as `sandbox.env`
- `--entry-gateway-id`: paste one of the values labeled with a key `"identityKey"` (without `" "`) from [here](https://nymvpn.com/en/alpha/api/gateways)
- `--exit-router-address`: paste one of the values labeled with a key `"address"` (without `" "`) from here [here](https://nymvpn.com/en/alpha/api/gateways)
- `--enable-wireguard`: Enable the wireguard traffic between the client and the entry gateway. NymVPN uses Mullvad libraries for wrapping `wireguard-go` and to setup local routing rules to route all traffic to the TUN virtual network device
- `--wg-ip`: The address of the wireguard interface, you can get it [here](https://nymvpn.com/en/alpha)
- `--private-key`: get your private key for testing purposes [here](https://nymvpn.com/en/alpha)
- `--enable-two-hop` is a faster setup where the traffic is routed from the client to Entry Gateway and directly to Exit Gateway (default is 5-hops)
**Advanced options**
- `--enable-poisson`: Enables process rate limiting of outbound traffic (disabled by default). It means that NymVPN client will send packets at a steady stream to the Entry Gateway. By default it's on average one sphinx packet per 20ms, but there is some randomness (poisson distribution). When there are no real data to fill the sphinx packets with, cover packets are generated instead.
- `--ip` is the IP address of the TUN device. That is the IP address of the local private network that is set up between local client and the Exit Gateway.
- `--mtu`: The MTU of the TUN device. That is the max IP packet size of the local private network that is set up between local client and the Exit Gateway.
- `--disable-routing`: Disable routing all traffic through the VPN TUN device.
@@ -0,0 +1,240 @@
# NymVPN CLI Guide
```admonish tip title="web3summit testing"
**If you testing NymVPN CLI on Web3 Summit Berlin, visit our event page with all info tailored for the event: [nym-vpn-cli.sandbox.nymtech.net](https://nym-vpn-cli.sandbox.nymtech.net/).**
```
```admonish info
To download NymVPN desktop version, visit [nymvpn.com/en/download](https://nymvpn.com/en/download).
NymVPN is an experimental software and it's for testing purposes only. Anyone can submit a registration to the private alpha round on [nymvpn.com](https://nymvpn.com/en).
```
## Overview
The core binaries consist of:
- **`nym-vpn-cli`**: Basic commandline client for running the vpn. This runs in the foreground.
- **`nym-vpnd`**: Daemon implementation of the vpn client that can run in the background and interacted with using `nym-vpnc`.
- **`nym-vpnc`**: The commandline client used to interact with `nym-vpnd`.
## Installation
> Any syntax in `<>` brackets is a user's/version unique variable. Exchange with a corresponding name without the `<>` brackets.
1. Open Github [releases page]({{nym_vpn_releases}}) and download the CLI latest binary for your system (labelled as `nym-vpn-core`)
2. Verify sha hash of your downloaded binary with the one listed on the [releases page]({{nym_vpn_releases}}). You can use a simple `shasum` command and compare strings (ie with Python) or run in the same directory the following command, exchanging `<SHA_STRING>` with the one of your binary, like in the example:
```sh
echo "<SHA_STRING>" | shasum -a 256 -c
# choose a correct one according to your binary, this is just an example
# echo "0e4abb461e86b2c168577e0294112a3bacd3a24bf8565b49783bfebd9b530e23 nym-vpn-cli_<!-- cmdrun ../../../scripts/cmdrun/nym_vpn_cli_version.sh -->_ubuntu-22.04_amd64.tar.gz" | shasum -a 256 -c
```
3. Extract files:
```sh
tar -xvf <BINARY>.tar.gz
# for example
# tar -xvf nym-vpn-cli_<!-- cmdrun ../../../scripts/cmdrun/nym_vpn_cli_version.sh -->_ubuntu-22.04_x86_64.tar.gz
```
### Building From Source
NymVPN CLI can be built from source. This process is recommended for more advanced users as the installation may require different dependencies based on the operating system used.
Start by installing [Go](https://go.dev/doc/install) and [Rust](https://rustup.rs/) languages on your system and then follow these steps:
1. Clone NymVPN repository:
```sh
git clone https://github.com/nymtech/nym-vpn-client.git
```
2. Move to `nym-vpn-client` directory and compile `wireguard`:
```sh
cd nym-vpn-client
make build-wireguard
```
3. Compile NymVPN CLI
```sh
make build-nym-vpn-core
```
Now your NymVPN CLI is installed. Navigate to `nym-vpn-core/target/release` and use the commands the section below to run the client.
## Running
If you are running Debian/Ubuntu/PopOS or any other distributio supporting debian packages and systemd, see the [relevant section below](#debian-package-for-debianubuntupopos).
### Daemon
Start the daemon with
```sh
sudo -E ./nym-vpnd
```
Then run
```sh
./nym-vpnc status
./nym-vpnc connect
./nym-vpnc disconnect
```
### CLI
An alternative to the daemon is to run the `nym-vpn-cli` commandline client that runs in the foreground.
```sh
./nym-vpn-cli run
```
## Credentials
NymVPN uses [zkNym bandwidth credentials](https://nymtech.net/docs/bandwidth-credentials.html). Those can be imported as a file or base58 encoded string.
```sh
sudo -E ./nym-vpn-cli import-credential --credential-path </PATH/TO/freepass.nym>
sudo -E ./nym-vpn-cli import-credential --credential-data "<STRING>"
```
## Debian package for Debian/Ubuntu/PopOS
For linux platforms using deb packages and systemd, there are also debian packages.
```sh
sudo apt install ./nym-vpnd_<!-- cmdrun ../../../scripts/cmdrun/nym_vpn_cli_version.sh -->-1_amd64.deb ./nym-vpnc_<!-- cmdrun ../../../scripts/cmdrun/nym_vpn_cli_version.sh -->-1_amd64.deb
# In case of error please substitute the correct version
```
Installing the `nym-vpnd` deb package starts a `nym-vpnd.service`. Check that the daemon is running with
```sh
systemctl status nym-vpnd.service
```
and check its logs with
```sh
sudo journalctl -u nym-vpnd.service -f
```
To stop the background service
```sh
systemctl stop nym-vpnd.service
```
It will start again on startup, so disable with
```sh
systemctl disable nym-vpnd.service
```
Interact with it with `nym-vpnc`
```sh
nym-vpnc status
nym-vpnc connect
nym-vpnc disconnect
```
## Commands & Options
```admonish note
Nym Exit Gateway functionality was implemented just recently and not all the Gateways are upgraded and ready to handle the VPN connections. If you want to make sure you are connecting to a Gateway with an embedded Network Requester, IP Packet Router and applied Nym exit policy, visit [harbourmaster.nymtech.net](https://harbourmaster.nymtech.net/) and search Gateways with all the functionalities enabled.
```
The basic syntax of `nym-vpn-cli` is:
```sh
# choose only one conditional --argument listed in {brackets}
sudo ./nym-vpn-cli { --exit-router-address <EXIT_ROUTER_ADDRESS>|--exit-gateway-id <EXIT_GATEWAY_ID>|--exit-gateway-country <EXIT_GATEWAY_COUNTRY> }
```
To see all the possibilities run with `--help` flag:
```sh
./nym-vpn-cli --help
```
~~~admonish example collapsible=true title="nym-vpn-cli --help"
```sh
Usage: nym-vpn-cli [OPTIONS] <COMMAND>
Commands:
run Run the client
import-credential Import credential
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 describing the network
--data-path <DATA_PATH> Path to the data directory of the mixnet client
-h, --help Print help
-V, --version Print version
```
~~~
You can also run any command with `--help` flag to see a list of all options associated witht that command, the most important may be `run` command, like in this example.
~~~admonish example collapsible=true title="nym-vpn-cli run --help"
```sh
Run the client
Usage: nym-vpn-cli run [OPTIONS]
Options:
--entry-gateway-id <ENTRY_GATEWAY_ID>
Mixnet public ID of the entry gateway
--entry-gateway-country <ENTRY_GATEWAY_COUNTRY>
Auto-select entry gateway by country ISO
--entry-gateway-low-latency
Auto-select entry gateway by latency
--exit-router-address <EXIT_ROUTER_ADDRESS>
Mixnet recipient address
--exit-gateway-id <EXIT_GATEWAY_ID>
Mixnet public ID of the exit gateway
--exit-gateway-country <EXIT_GATEWAY_COUNTRY>
Auto-select exit gateway by country ISO
--wireguard-mode
Enable the wireguard mode
--nym-ipv4 <NYM_IPV4>
The IPv4 address of the nym TUN device that wraps IP packets in sphinx packets
--nym-ipv6 <NYM_IPV6>
The IPv6 address of the nym TUN device that wraps IP packets in sphinx packets
--nym-mtu <NYM_MTU>
The MTU of the nym TUN device that wraps IP packets in sphinx packets
--dns <DNS>
The DNS server to use
--disable-routing
Disable routing all traffic through the nym TUN device. When the flag is set, the nym TUN device will be created, but to route traffic through it you will need to do it manually, e.g. ping -Itun0
--enable-two-hop
Enable two-hop mixnet traffic. This means that traffic jumps directly from entry gateway to exit gateway
--enable-poisson-rate
Enable Poisson process rate limiting of outbound traffic
--disable-background-cover-traffic
Disable constant rate background loop cover traffic
--enable-credentials-mode
Enable credentials mode
--min-mixnode-performance <MIN_MIXNODE_PERFORMANCE>
Set the minimum performance level for mixnodes
-h, --help
Print help
```
~~~
## Testnet environment
If you want to run NymVPN CLI in Nym Sandbox environment, there are a few adjustments to be done:
1. Create Sandbox environment config file by saving [this](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) as `sandbox.env` in the same directory as your NymVPN binaries:
```sh
curl -o sandbox.env -L https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env
```
2. Check available Gateways at [Sandbox API](https://sandbox-nym-api1.nymtech.net/api/v1/gateways) or [Sandbox Swagger page](https://sandbox-nym-api1.nymtech.net/api/swagger/index.html)
3. Run with a flag `-c`
```sh
sudo ./nym-vpn-cli -c <PATH_TO>/sandbox.env <--exit-router-address <EXIT_ROUTER_ADDRESS>|--exit-gateway-id <EXIT_GATEWAY_ID>|--exit-gateway-country <EXIT_GATEWAY_COUNTRY>>
```
@@ -0,0 +1,71 @@
# Frequently Asked Questions
**NymVPN [*Support & FAQ page*](https://nymvpn.com/en/support)** contains all essential FAQs regarding the client. This page (below) is a source of additional information often seeked by users, operators and developers testing NymVPN.
If you interested to read more about Nym platform, you can have a look at [Nym general FAQ](https://nymtech.net/developers/faq/general-faq.html) and read through Nym's technical [documentation](https://nymtech.net/docs), [Developer Portal](https://nymtech.net/developers) and [Operators Guide](https://nymtech.net/operators).
## NymVPN
If this your first time hearing about NymVPN, make sure you visit [NymVPN webpage](https://nymvpn.com/en), the official NymVPN [support & FAQ page](https://nymvpn.com/en/support) and the proceed to the introduction and guide on how to [install, run and test](intro.md#nymvpn-guides) the client.
Below are some extra FAQs which came out during the previous alpha testing rounds.
### What's the difference between 2-hops and 5-hops
The default is 5-hops (including Entry and Exit Gateways), which means that the traffic goes from the local client to Entry Gateway -> through 3 layers of Mix Nodes -> to Exit Gateway -> internet. this option uses all the Nym Mixnet features for maximum privacy.
```
┌─►mix──┐ mix mix
│ │
Entry │ │ Exit
client ───► Gateway ──┘ mix │ mix ┌─►mix ───► Gateway ───► internet
│ │
│ │
mix └─►mix──┘ mix
```
The 2-hop option is going from the local client -> Entry Gateway -> directly to Exit Gateway -> internet. This option is good for operations demanding faster connection. Keep in mind that this setup by-passes the 3 layers of Mix Nodes. The anonymising features done by your local client like breaking data into same-size packets with inserting additional "dummy" ones to break the time and volume patterns is done in both options.
```
Entry Exit
client ───► Gateway ────► Gateway ───► internet
```
We highly recommend to read more about [Nym network overview](https://nymtech.net/docs/architecture/network-overview.html) and the [Mixnet traffic flow](https://nymtech.net/docs/architecture/traffic-flow.html).
### Why do I see different sizes of packets in my terminal log?
One of features of Nym Mixnet's clients is to break data into the same size packets called Sphinx, which is currently ~2kb. When running NymVPN, the data log shows payload sizes, which are the raw sizes of the IP packets, not Sphinx. The payload sizes will be capped by the configured MTU, which is set around 1500 bytes.
### What is 'poisson filter' about?
By default `--enable-poisson` is disabled and packets are sent from the local client to the Entry Gateway as quickly as possible. With the poisson process enabled the Nym client will send packets at a steady stream to the Entry Gateway. By default it's on average one sphinx packet per 20ms, but there is some randomness (poisson distribution). When there are no real data to fill the sphinx packets with, cover packets are generated instead.
Enabling the poisson filter is one of the key mechanisms to de-correlate input and output traffic to the Mixnet. The performance impact however is dramatic:
1 packer per 20ms is 50 packets / sec so ballpark 100kb/s.
For mobile clients that means constantly sending data eating up data allowance.
## Nym Mixnet Architecture and Rewards
We have a list of questions related to Nym Nodes and the incentives behind running them under [FAQ pages](https://nymtech.net/operators/faq/mixnodes-faq.html) in our [Operators Guide](https://nymtech.net/operators). For better knowledge about Nym architecture we recommend to read [Nym network overview](https://nymtech.net/docs/architecture/network-overview.html) and the [Mixnet traffic flow](https://nymtech.net/docs/architecture/traffic-flow.html) in our [technical documentation](https://nymtech.net/docs).
## Project Smoosh
Project Smoosh is a code name for a process in which different components of Nym Mixnet architecture get *smooshed* into one binary. Check out [Smoosh FAQ](https://nymtech.net/operators/faq/smoosh-faq.html) in Operators Guide to read more.
## Exit Gateway
Part of the the transition under code name [Project Smoosh](#project-smoosh) is a creation of [Nym Exit Gateway](https://nymtech.net/operators/legal/exit-gateway.html) functionality. The operators running Gateways would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short [allowed.list](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a more permissive setup. An [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients.
* Read more how the exit policy gets implemented [here](https://nymtech.net/operators/faq/smoosh-faq.html#how-will-the-exit-policy-be-implemented)
* Check out [Nym Operators Legal Forum](https://nymtech.net/operators/legal/exit-gateway.html)
* Do reach out to us with any experiences you may have running Tor Exit relays or legal findings and suggestions for Nym Exit Gateway operators
## Nym Integrations and SDKs
If you are a dev who is interested to integrate Nym, have a look on our SDK tutorials:
* [Rust SDKs](https://nymtech.net/developers/tutorials/cosmos-service/intro.html)
* [TypeScript SDKs](https://sdk.nymtech.net/)
* [Integration FAQ](https://nymtech.net/developers/faq/integrations-faq.html)
@@ -0,0 +1,85 @@
# NymVPN alpha - Desktop: Guide for GNU/Linux
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/908221306?h=404b2bbdc8" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
```admonish info
NymVPN is an experimental software and it's for testing purposes only. All users testing the client are expected to sign GDPR Information Sheet and Consent Form (shared at the workshop) so we use their results to improve the client, and submit the form [*NymVPN User research*]({{nym_vpn_form_url}}) with the testing results.
```
## Preparation
> Any syntax in `<>` brackets is a user's/version unique variable. Exchange with a corresponding name without the `<>` brackets.
### Installation
1. Open Github [releases page]({{nym_vpn_releases}}) and download the binary for Debian based Linux
2. (Optional: if you don't want to check shasum, skip this point) Verify sha hash of your downloaded binary with the one listed on the [releases page]({{nym_vpn_releases}}). You can use a simple `shasum` command and compare strings (ie with Python) or run in the same directory the following command, exchanging `<SHA_STRING>` with the one of your binary, like in the example:
```sh
echo "<SHA_STRING>" | shasum -a 256 -c
# choose a correct one according to your binary, this is just an example
# echo "a5f91f20d587975e30b6a75d3a9e195234cf1269eac278139a5b9c39b039e807 nym-vpn-desktop_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_ubuntu-22.04_x86_64.tar.gz" | shasum -a 256 -c
```
3. Extract files:
```sh
tar -xvf <BINARY>.tar.gz
# for example
# tar -xvf nym-vpn-desktop_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_ubuntu-22.04_x86_64.tar.gz
```
4. If you prefer to run `.AppImage` make executable by running:
```sh
# make sure you cd into the right sub-directory after extraction
chmod u+x ./nym-vpn_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_amd64.AppImage
```
5. If you prefer to use the `.deb` version for installation (works on Debian based Linux only), open terminal in the same directory and run:
```sh
# make sure you cd into the right sub-directory after extraction
sudo dpkg -i ./nym-vpn_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_amd64.deb
# or
sudo apt-get install -f ./nym-vpn_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_amd64.deb
```
<!--
NymVPN alpha version runs over Nym testnet (called sandbox), a little extra configuration is needed for the application to work.
### Configuration
To test NymVPN alpha we must create two configuration files: an environment config file `sandbox.env` and `config.toml` file pointing the application to run over the testnet environment.
6. Create a NymVPN config directory called `nym-vpn` in your `~/.config`, either manually or by a command:
```sh
mkdir $HOME/.config/nym-vpn/
```
7. Create the network testnet config: copy-paste [this](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) and save as `sandbox.env` in the directory `~/.config/nym-vpn/` you just created. Aternatively do it by runnin a command
```sh
curl -o $HOME/.config/nym-vpn/sandbox.env -L https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env
```
8. Create NymVPN main config file: copy-paste the line below and save it as `config.toml` in the same directory `~/.config/nym-vpn/`:
```toml
# change <USER> to your username
env_config_file = "/home/<USER>/.config/nym-vpn/sandbox.env"
```
-->
## Run NymVPN
**For NymVPN to work, all other VPNs must be switched off!** At this alpha stage of NymVPN, the network connection (wifi) must be reconnected after or in between the testing rounds.
In case you used `.deb` package and installed the client, you may be able to have a NymVPN application icon in your app menu. However this may not work as the application needs root permission.
Open terminal and run:
```sh
# .AppImage must be run from the same directory as the binary
sudo -E ./nym-vpn_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_amd64.AppImage
# .deb installation shall be executable from anywhere as
sudo -E nym-vpn
```
In case of errors, see [troubleshooting section](troubleshooting.md).
@@ -0,0 +1,65 @@
# NymVPN alpha - Desktop: Guide for Mac OS
```admonish info
NymVPN is an experimental software and it's for testing purposes only. All users testing the client are expected to sign GDPR Information Sheet and Consent Form (shared at the workshop) so we use their results to improve the client, and submit the form [*NymVPN User research*]({{nym_vpn_form_url}}) with the testing results.
```
## Preparation
> Any syntax in `<>` brackets is a user's/version unique variable. Exchange with a corresponding name without the `<>` brackets.
### Installation
1. Open Github [releases page]({{nym_vpn_releases}}) and download the binary for your version of MacOS
2. Recommended (skip this point if you don't want to verify): Verify sha hash of your downloaded binary with the one listed on the [releases page]({{nym_vpn_releases}}). You can use a simple `shasum` command and compare strings (ie with Python) or run in the same directory the following command, exchanging `<SHA_STRING>` with the one of your binary, like in the example:
```sh
echo "<SHA_STRING>" | shasum -a 256 -c
# choose a correct one according to your binary, this is just an example
# echo "da4c0bf8e8b52658312d341fa3581954cfcb6efd516d9a448c76d042a454b5df nym-vpn-desktop_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_macos_x86_64.zip" | shasum -a 256 -c
```
3. Extract the downloaded file manually or by a command:
```sh
tar -xvf <BINARY>.tar.gz
# for example
# tar -xvf nym-vpn-desktop_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_macos_aarch64.tar.gz
```
4. Mount the `.dmg` image you extracted by double clicking on it and move it (drag it) to your `/Application` folder
<!--
NymVPN alpha version runs over Nym testnet (called sandbox), a little extra configuration is needed for the application to work.
### Configuration
To test NymVPN alpha we must create two configuration files: an environment config file `sandbox.env` and `config.toml` file pointing the application to run over the testnet environment.
5. Create testnet configuration file: Open a text editor, copy-paste [this](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) and save it as `sandbox.env` in `/Applications/nym-vpn.app/Contents/MacOS/`. Alternatively use this command:
```sh
curl -L "https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env" -o "/Applications/nym-vpn.app/Contents/MacOS/sandbox.env"
```
6. Create application configuration file: Open a text editor, copy-paste the line below and save as `config.toml` in the same directory `/Applications/nym-vpn.app/Contents/MacOS/`
```toml
env_config_file = "sandbox.env"
```
Alternatively do it by using this command:
```sh
echo "env_config_file = sandbox.env" > /Applications/nym-vpn.app/Contents/MacOS/config.toml
```
-->
## Run NymVPN
**For NymVPN to work, all other VPNs must be switched off!** At this alpha stage of NymVPN, the network connection (wifi) must be reconnected after or in between the testing rounds.
Run:
```sh
sudo /Applications/nym-vpn.app/Contents/MacOS/nym-vpn
# If it didn't start try to run with -E flag
sudo -E /Applications/nym-vpn.app/Contents/MacOS/nym-vpn
```
In case of errors check out the [troubleshooting](troubleshooting.md#running-gui-failed-due-to-toml-parse-error) section.
@@ -0,0 +1,50 @@
# NymVPN - Desktop (GUI)
```admonish info
Our alpha testing round is done with participants at live workshop events and the application in this stage may not work for everyone.
**If you commit to test NymVPN alpha, please start with the [user research form]({{nym_vpn_form_url}}) where all the steps will be provided**. If you disagree with any of the conditions listed, please leave this page.
```
This is a desktop (GUI) version of NymVPN client. A demo of how the application will look like for majority of day-to-day users.
Follow the simple [automated script](#automated-script-for-gui-installation) below to install and run NymVPN GUI. If the script didn't work for your distribution or you prefer to do a manual setup follow the steps in the guide for [Linux](gui-linux.md) or [MacOS](gui-mac.md) .
Visit NymVPN alpha latest [release page]({{nym_vpn_releases}}) to check sha sums or download the binaries directly.
## Linux AppImage Automated Installation Method
The latest releases contain `appimage.sh` script. This method makes the installation simple for Linux users who want to run NymVPN from AppImmage. Executing the command below will download the binary to `~/.local/bin` and verify the checksum:
```sh
curl -fsSL https://github.com/nymtech/nym-vpn-client/releases/download/nym-vpn-desktop-v<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->/appimage.sh | bash
```
Run with the command:
```sh
sudo -E ~/.local/bin/nym-vpn.appimage
```
## Automated Script for GUI Installation (Linux and Mac)
We wrote a [script](https://gist.github.com/tommyv1987/7d210d4daa8f7abc61f9a696d0321f19) which does download of dependencies and the application, sha256 verification, extraction, installation and configuration for Linux and MacOS users automatically. Turn off all VPNs and follow the steps below.
1. Open a terminal window in a directory where you want the script to be downloaded and run
```sh
curl -o nym-vpn-desktop-install-run.sh -L https://gist.githubusercontent.com/tommyv1987/7d210d4daa8f7abc61f9a696d0321f19/raw/939ac8d0afed69f43739b9cf2e5728454ea2c437/nym-vpn-client-install-run.sh && chmod u+x nym-vpn-desktop-install-run.sh && sudo -E ./nym-vpn-desktop-install-run.sh
```
2. Follow the prompts in the program
To start the application again, reconnect your wifi and run
```sh
# Linux .AppImage
sudo -E ~/nym-vpn-latest/nym-vpn-desktop_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_ubuntu-22.04_x86_64/nym-vpn_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_amd64.AppImage
# Linux .deb
sudo -E nym-vpn
# MacOS
sudo -E $HOME/nym-vpn-latest/nym-vpn
```
In case of errors check out the [troubleshooting](troubleshooting.md#running-gui-failed-due-to-toml-parse-error) section.
@@ -0,0 +1,209 @@
# Testing NymVPN alpha
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/908640440?h=0f7f6dfa53" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
```admonish info
NymVPN is an experimental software and it's for [testing](./testing.md) purposes only. All users testing the client are expected to sign GDPR Information Sheet and Consent Form (shared at the workshop) so we use their results to improve the client, and submit the form [*NymVPN User research*]({{nym_vpn_form_url}}) with the testing results.
```
> Before you get into testing NymVPN, make sure to go through the preparation steps for NymVPN [CLI](cli.md).
One of the main aims of NymVPN alpha release is testing; your results will help us to make NymVPN robust and stabilise both the client and the network through provided measurements.
## Steps to test NymVPN
> Any syntax in `<>` brackets is a user's/version unique variable. Exchange with a corresponding name without the `<>` brackets.
1. Create a directory called `nym-vpn-tests` and copy your `nym-vpn-cli` binary ([download here]({{nym_vpn_releases}}))
2. Copy or download [`sandbox.env`](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) testnet config file to the same directory
```sh
curl -o sandbox.env -L https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env
```
3. Copy the [block below](#testssh) and save it as `tests.sh` to the same folder
4. Open terminal in the same directory and make the script executable
```sh
chmod u+x ./tests.sh
```
5. Turn off any existing VPN's (including NymVPN instances), reconnect your wifi and run the `tests.sh` script
```sh
sudo ./tests.sh
````
6. In case of errors, see the [troubleshooting section](troubleshooting.md#missing-jq-error)
7. The script will print a JSON view of existing Gateways and prompt you to:
- *Make sure to use two different Gateways for entry and exit!*
- `enter a gateway ID:` paste one of the values labeled with a key `"identityKey"` printed above (without `" "`)
- `enter an exit address:` paste one of the values labeled with a key `"address"` printed above (without `" "`)
- `enable WireGuard? (yes/no):` if you chose yes, find your private key and wireguard IP [here](https://nymvpn.com/en/alpha)
8. Note that the testing script doesn't print many logs, in case of doubts you can check logs in the log file `temp_log.txt` located in the same directory.
9. The script shall run the tests and generate a folder called `tests_<LONG_STRING>` and files `perf_test_results.log` or `two_hop_perf_test_results.log` as well as some temp files. This is how the directory structure will look like:
```sh
nym-vpn-tests
├── tests.sh
├── nym-vpn-cli
├── sandbox.env
├── perf_test_results.log
├── tests_<LONG_STRING>
│   ├── api_response_times.txt
│   ├── download_time.txt
│   └── ping_results.txt
├── timeout
└── two_hop_perf_test_results.log
```
10. When the tests are finished, remove the `nym-vpn-cli` binary from the folder and compress the entire folder as `nym-vpn-tests.zip` (both of these can be done in your graphical environment)
11. Upload this compressed file to the [form]({{nym_vpn_form_url}}) drop field when prompted
#### tests.sh
This is the testing script which needs to be copied and saved as `tests.sh` to your `nym-vpn-tests` folder and then run from there as described [above](#steps-to-test-nymvpn).
```sh
#!/bin/bash
ENDPOINT="https://sandbox-nym-api1.nymtech.net/api/v1/gateways/described"
json_array=()
echo "🚀 🏎 - please be patient, i'm fetching you your entry points - 🚀 🏎 "
data=$(curl -s "$ENDPOINT" | jq -c '.[] | {host: .bond.gateway.host, hostname: .self_described.host_information.hostname, identity_key: .bond.gateway.identity_key, exitGateway: .self_described.ip_packet_router.address}')
while IFS= read -r entry; do
host=$(echo "$entry" | jq -r '.host')
hostname=$(echo "$entry" | jq -r '.hostname')
identity_key=$(echo "$entry" | jq -r '.identity_key')
exit_gateway_address=$(echo "$entry" | jq -r '.exitGateway // empty')
valid_ip=$(echo "$host")
if [ -n "$exit_gateway_address" ]; then
exit_gateway="{\"address\": \"${exit_gateway_address}\"}"
else
exit_gateway="{}"
fi
if [[ $valid_ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
country_info=$(curl -s "http://ipinfo.io/${valid_ip}/country" | tr -d '\n')
country_info_escaped=$(echo "$country_info" | tr -d '\n' | jq -aRs . | tr -d '"')
else
country_info_escaped=""
fi
json_object="{\"hostname\": \"${hostname}\", \"identityKey\": \"${identity_key}\", \"exitGateway\": ${exit_gateway}, \"location\": \"${country_info_escaped}\"}"
json_array+=("$json_object")
done < <(echo "$data")
if [ $? -ne 0 ]; then
echo "error fetching data from endpoint"
exit 1
fi
download_file() {
local file_url=$1
local output_file=$2
local time_file=$3
echo "starting download speed test..."
local start_time=$(date +%s)
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
wget -O $output_file $file_url
elif [[ "$OSTYPE" == "darwin"* ]]; then
curl -o $output_file $file_url
fi
local end_time=$(date +%s)
local elapsed_time=$((end_time - start_time))
echo "download speed test completed in $elapsed_time seconds." >"$time_file"
}
if ! command -v jq &>/dev/null; then
echo "jq is not installed. Please install jq to proceed."
exit 1
fi
temp_log_file="temp_log.txt"
perform_tests() {
local gateway_id=$1
local exit_address=$2
local test_directory="tests_${gateway_id}_${exit_address}"
local file_url="http://ipv4.download.thinkbroadband.com/2MB.zip"
mkdir -p "$test_directory"
local ping_results_file="${test_directory}/ping_results.txt"
local download_time_file="${test_directory}/download_time.txt"
local api_response_file="${test_directory}/api_response_times.txt"
# ping test
echo "starting ping test..."
for site in google.com youtube.com facebook.com baidu.com wikipedia.org amazon.com twitter.com instagram.com yahoo.com ebay.com netflix.com; do
ping -c 4 $site >>"$ping_results_file"
done
echo "ping test completed. Results saved in $ping_results_file"
# download speed test
download_file $file_url /dev/null "$download_time_file"
# api test
local api_endpoint="https://validator.nymtech.net/api/v1/mixnodes"
local iterations=10
>"$api_response_file"
for i in $(seq 1 $iterations); do
local start_time=$(date +%s)
local response=$(curl -s -o /dev/null -w '%{http_code}' $api_endpoint)
local end_time=$(date +%s)
local elapsed_seconds=$((end_time - start_time))
local hours=$((elapsed_seconds / 3600))
local minutes=$(((elapsed_seconds % 3600) / 60))
local seconds=$((elapsed_seconds % 60))
local human_readable_time=$(printf "%02dh:%02dm:%02ds" $hours $minutes $seconds)
echo "iteration $i: response Time = ${human_readable_time}, status code = $response" >>"$api_response_file"
done
echo "api response test completed. Results saved in $api_response_file."
}
printf "%s\n" "${json_array[@]}" | jq -s .
read -p "enter a gateway ID: " identity_key
read -p "enter an exit address: " exit_address
while true; do
read -p "enable WireGuard? (yes/no): " enable_wireguard
enable_wireguard=$(echo "$enable_wireguard" | tr '[:upper:]' '[:lower:]')
case "$enable_wireguard" in
"yes")
read -p "enter your WireGuard private key: " priv_key
read -p "enter your WireGuard IP: " wg_ip
wireguard_options="--enable-wireguard --private-key $priv_key --wg-ip $wg_ip"
break
;;
"no")
wireguard_options=""
break
;;
*)
echo "invalid response. please enter 'yes' or 'no'."
;;
esac
done
sudo ./nym-vpn-cli -c sandbox.env --entry-gateway-id ${identity_key} --exit-router-address ${exit_address} --enable-two-hop $wireguard_options >"$temp_log_file" 2>&1 &
timeout=15
start_time=$(date +%s)
while true; do
current_time=$(date +%s)
if grep -q "received plain" "$temp_log_file"; then
echo "successful configuration with identity_key: $identity_key and exit address: $exit_address" >>perf_test_results.log
perform_tests "$identity_key" "$exit_address"
break
fi
if ((current_time - start_time > timeout)); then
echo "failed to connect with identity_key: $identity_key using the exit address: $exit_address" >>perf_test_results.log
break
fi
sleep 1
done
echo "terminating nym-vpn-cli..."
pkill -f './nym-vpn-cli'
sleep 5
rm -f "$temp_log_file"
```
@@ -0,0 +1,97 @@
# Troubleshooting
Below are listed some points which may need to be addressed when testing NymVPN alpha. If you crashed into any errors which are not listed, please contact us at the testing workshop or in the NymVPN [Matrix channel](https://matrix.to/#/#NymVPN:nymtech.chat).
#### NymVPN attempts to connect to sandbox testnet
If you testing the latest versions and you correctly expect the client to run over the mainnet, but it listens to `https://sandbox-nym-api1.nymtech.net`, it's probably because of your previous configuration.
Check your `config.toml` either in the directory from which you run your client or in `~/.config/nym-vpn/` and remove `sandbox.env` from the config file and folder.
If the problem persists (probably due to some locally cache) download [`mainnet.env`](https://github.com/nymtech/nym/blob/master/envs/mainnet.env) and save it to the same directory.
#### Running GUI failed due to `TOML parse error`
If you see this error when running NymVPN alpha desktop, it's because the older versions needed entry location in `config.toml` configuration file. From `v0.0.3` the entry location is selected directly by the user in the application. This error is due to an old `app-data.toml` config in your computer.
```sh
2024-02-15T14:25:02.745331Z ERROR read: nym_vpn_desktop::fs::storage: TOML parse error at line 5, column 1
|
5 | [entry_node_location]
| ^^^^^^^^^^^^^^^^^^^^^
wanted exactly 1 element, more than 1 element
self=AppStorage { data: AppData { monitoring: None, autoconnect: None, killswitch: None, entry_location_selector: None, ui_theme: None, ui_root_font_size: None, vpn_mode: None, entry_node_location: None, exit_node_location: None }, dir_path: "/home/companero/.local/share/nym-vpn", filename: "app-data.toml", full_path: "/home/companero/.local/share/nym-vpn/app-data.toml" }
Error: TOML parse error at line 5, column 1
|
5 | [entry_node_location]
| ^^^^^^^^^^^^^^^^^^^^^
wanted exactly 1 element, more than 1 element
```
Simply delete this file `app-data.toml` from the path listed in the error message. In the example above it would be `/home/companero/.local/share/nym-vpn/app-data.toml`.
The application will create a new one on startup.
#### Thread `main` panicked
If you see a message like:
```sh
thread 'main' panicked at /Users/runner/.cargo/git/checkouts/mullvadvpn-app-a575cf705b5dfd76/ccfbaa2/talpid-routing/src/unix.rs:301:30:
```
Restart your wifi connection and start again.
#### MacOS alert on NymVPN UI startup
If you are running NymVPN on mac OS for the first time, you may see this alert message:
![](images/image3.png)
1. Head to System Settings -> Privacy & Security and click `Allow anyway`
![](images/image5.png)
2. Confirm with your password or TouchID
3. Possibly you may have to confirm again upon running the application
<!--
#### Missing `jq` error
In case of missing `jq` on Linux (Debian) install it with:
```sh
# Linux (Debian)
sudo apt-get install jq
# macOS
brew install jq
```
On some Linux distributions however the [script](testing.md#testssh) returns `jq` error even if your system claims that `jq is already the newest version`.
In that case, comment the `jq` check in the script as follows:
```sh
#if ! command -v jq &>/dev/null; then
# echo "jq is not installed. Please install jq to proceed."
# exit 1
#fi
```
#### Error current_time: not found
When running `sudo sh ./test.sh` you may see an error like: `93: current_time: not found`. This has something to do with the `current_time` setup of your system and on itself shall not have a negative impact on the test. It has nothing to do with the client at all as it only relates to the code in our testing script.
#### Not connecting to the endpoint
In case the automatic download of all the Gateways fail (and it shouldn't), you do an easy manual work around:
1. Open the list of Gateways created by API [here](https://nymvpn.com/en/alpha/api/gateways)
2. On top click on `JSON` option (shall be default view) and `Save`
3. Save it as `data.json` to the `nym-vpn-tests` folder
4. Replace line 3 in the [script `tests.sh`](testing.md#testssh) with:
```sh
NEW_ENDPOINT="http://localhost:8000/data.json"
```
5. In a new terminal window run:
```sh
python3 -m http.server 8000
```
6. Continue with the steps listed in [testing section](testing.md)
-->
@@ -0,0 +1,64 @@
# Nym Binaries
## Building from Source
> Nym runs on Mac OS X, Linux, and Windows. All nodes **except the Desktop Wallet and NymConnect** on Windows should be considered experimental - it works fine if you're an app developer but isn't recommended for running nodes.
## Building Nym
Nym has two main codebases:
- the [Nym platform](https://github.com/nymtech/nym), written in Rust. This contains all of our code _except_ for the validators.
- the [Nym validators](https://github.com/nymtech/nyxd), written in Go.
> This page details how to build the main Nym platform code. **If you want to build and run a validator, [go here]() TODO LINK AFTER MERGE instead.**
## Prerequisites
- Debian/Ubuntu: `pkg-config`, `build-essential`, `libssl-dev`, `curl`, `jq`, `git`
```
apt install pkg-config build-essential libssl-dev curl jq git
```
- Arch/Manjaro: `base-devel`
```
pacman -S base-devel
```
- Mac OS X: `pkg-config` , `brew`, `openss1`, `protobuf`, `curl`, `git`
Running the following the script installs Homebrew and the above dependencies:
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
- `Rust & cargo >= {{minimum_rust_version}}`
We recommend using the [Rust shell script installer](https://www.rust-lang.org/tools/install). Installing cargo from your package manager (e.g. `apt`) is not recommended as the packaged versions are usually too old.
If you really don't want to use the shell script installer, the [Rust installation docs](https://forge.rust-lang.org/infra/other-installation-methods.html) contain instructions for many platforms.
## Download and build Nym binaries
The following commands will compile binaries into the `nym/target/release` directory:
```sh
rustup update
git clone https://github.com/nymtech/nym.git
cd nym
git reset --hard # in case you made any changes on your branch
git pull # in case you've checked it out before
git checkout master # master branch has the latest release version: `develop` will most likely be incompatible with deployed public networks
cargo build --release # build your binaries with **mainnet** configuration
```
> You cannot build from GitHub's .zip or .tar.gz archive files on the releases page - the Nym build scripts automatically include the current git commit hash in the built binary during compilation, so the build will fail if you use the archive code (which isn't a Git repository). Check the code out from github using `git clone` instead.
## Pre-built Binaries
The [Github releases page](https://github.com/nymtech/nym/releases) has pre-built binaries which should work on Ubuntu 20.04 and other Debian-based systems, but at this stage cannot be guaranteed to work everywhere.
If the pre-built binaries don't work or are unavailable for your system, you will need to build the platform yourself.
@@ -1,17 +1,15 @@
# Interacting with Nyx Chain and Smart Contracts
There are two options for interacting with the blockchain to send tokens or interact with deployed smart contracts:
* [`Nym-CLI`](../tools/nym-cli.md) tool
There are two options for interacting with the blockchain to send tokens or interact with deployed smart contracts:
* [`Nym-CLI`](../tools/nym-cli.md) tool
* `nyxd` binary
## Nym-CLI tool (recommended in most cases)
The `nym-cli` tool is a binary offering a simple interface for interacting with deployed smart contract (for instance, bonding and unbonding a mix node from the CLI), as well as creating and managing accounts and keypairs, sending tokens, and querying the blockchain.
## Nym-CLI tool (recommended in most cases)
The `nym-cli` tool is a binary offering a simple interface for interacting with deployed smart contract (for instance, bonding and unbonding a mix node from the CLI), as well as creating and managing accounts and keypairs, sending tokens, and querying the blockchain.
Instructions on how to do so can be found on the [`nym-cli` docs page](../tools/nym-cli.md), and there are example commands in the [integrations FAQ](https://nymtech.net/developers/faq/integrations-faq.html).
## Nyxd binary
The `nyxd` binary, although more complex to compile and use, offers the full range of commands availiable to users of CosmosSDK chains. Use this if you are (e.g.) wanting to perform more granular queries about transactions from the CLI.
You can use the instructions on how to do this on from the [`gaiad` docs page](https://hub.cosmos.network/main/delegators/delegator-guide-cli.html#querying-the-state), and there are example commands in the [integrations FAQ](https://nymtech.net/developers/faq/integrations-faq.html).
Instructions on how to do so can be found on the [`nym-cli` docs page](./tools/nym-cli)
## Nyxd binary
The `nyxd` binary, although more complex to compile and use, offers the full range of commands availiable to users of CosmosSDK chains. Use this if you are (e.g.) wanting to perform more granular queries about transactions from the CLI.
You can use the instructions on how to do this on from the [`gaiad` docs page](https://hub.cosmos.network/main/delegators/delegator-guide-cli.html#querying-the-state).
@@ -0,0 +1,6 @@
# CLI Wallet
If you have already read our [validator setup and maintenance documentation]() TODO LINK AFTER MERGE you will have seen that we compile and use the `nyxd` binary primarily for our validators. This binary can however be used for many other tasks, such as creating and using keypairs for wallets, or automated setups that require the signing and broadcasting of transactions.
### Using `nyxd` binary as a CLI wallet
You can use the `nyxd` as a minimal CLI wallet if you want to set up an account (or multiple accounts). Just compile the binary as per the documentation, **stopping after** the [building your validator]() TODO LINK AFTER MERGE step is complete. You can then run `nyxd keys --help` to see how you can set up and store different keypairs with which to interact with the Nyx blockchain.
@@ -0,0 +1,2 @@
# Cosmos Registry
You can find all relevant information (chain info, RPC endpoints, etc) on the [Cosmos Chain Registry](https://github.com/cosmos/chain-registry/tree/master/nyx).
@@ -1,22 +1,22 @@
# Ledger Live Support
Use the following instructions to interact with the Nyx blockchain - either with deployed smart contracts, or just to send tokens - using your Ledger device to sign transactions.
Use the following instructions to interact with the Nyx blockchain - either with deployed smart contracts, or just to send tokens - using your Ledger device to sign transactions.
## Prerequisites
* Download and install [Ledger Live](https://www.ledger.com/ledger-live).
* Compile the `nyxd` binary as per the instructions [here](https://nymtech.net/operators/nodes/validator-setup.html#building-the-nym-validator). Stop after you can successfully run `nyxd` and get the helptext in your console output.
## Prerequisites
* Download and install [Ledger Live](https://www.ledger.com/ledger-live).
* Compile the `nyxd` binary as per the instructions [here]() TODO LINK AFTER MERGE. Stop after you can successfully run `nyxd` and get the helptext in your console output.
## Prepare your Ledger App
* Plug in your Ledger device
* Install the `Cosmos (ATOM)` app by following the instructions [here](https://hub.cosmos.network/main/resources/ledger.html). This app allows you to interact with **any** Cosmos SDK chain - you can manage your ATOM, OSMOSIS, NYM tokens, etc.
* On the device, navigate to the Cosmos app and open it
## Prepare your Ledger App
* Plug in your Ledger device
* Install the `Cosmos (ATOM)` app by following the instructions [here](https://hub.cosmos.network/main/resources/ledger.html). This app allows you to interact with **any** Cosmos SDK chain - you can manage your ATOM, OSMOSIS, NYM tokens, etc.
* On the device, navigate to the Cosmos app and open it
## Create a keypair
Add a reference to the ledger device on your local machine by running the following command in the same directory as your `nyxd` binary:
## Create a keypair
Add a reference to the ledger device on your local machine by running the following command in the same directory as your `nyxd` binary:
```
nyxd keys add ledger_account --ledger
```
nyxd keys add ledger_account --ledger
```
## Command help with `nyxd`
More information about each command is available by consulting the help section (`--help`) at each layer of `nyxd`'s commands:
@@ -25,7 +25,7 @@ More information about each command is available by consulting the help section
# logging top level command help
nyxd --help
# logging top level command help for transaction commands
# logging top level command help for transaction commands
nyxd tx --help
# logging top level command help for transaction commands utilising the 'bank' module
@@ -33,7 +33,7 @@ nyxd tx bank --help
```
## Sending tokens between addresses
Perform a transaction from the CLI with `nyxd`, appending the `--ledger` option to the command.
Perform a transaction from the CLI with `nyxd`, appending the `--ledger` option to the command.
As an example, the below command will send 1 `NYM` from the ledger account to the `$DESTINATION_ACCOUNT`:
@@ -44,36 +44,35 @@ nyxd tx bank send ledger_account $DESTINATION_ACCOOUNT 1000000unym --ledger --no
> When a command is run, the transaction will appear on the Ledger device and will require physical confirmation from the device before being signed.
## Nym-specific transactions
Nym-specific commands and queries, like bonding a mix node or delegating unvested tokens, are available in the `wasm` module, and follow the following pattern:
Nym-specific commands and queries, like bonding a mix node or delegating unvested tokens, are available in the `wasm` module, and follow the following pattern:
```
# Executing commands
nyxd tx wasm execute $CONTRACT_ADDRESS $JSON_MSG
# Querying the state of a smart contract
# Querying the state of a smart contract
nyxd query wasm contract-state smart $CONTRACT_ADDRESS $JSON_MSG
```
You can find the value of `$CONTRACT_ADDRESS` in the [`network defaults`](https://github.com/nymtech/nym/blob/release/v1.1.7/common/network-defaults/src/mainnet.rs) file.
You can find the value of `$CONTRACT_ADDRESS` in the [`network defaults`](https://github.com/nymtech/nym/blob/master/common/network-defaults/src/mainnet.rs) file.
The value of `$JSON_MSG` will be a blog of `json` formatted as defined for each command and query. You can find these definitions for the mixnet smart contract [here](https://github.com/nymtech/nym/blob/develop/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs) and for the vesting contract [here](https://github.com/nymtech/nym/blob/develop/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs) under `ExecuteMsg` and `QueryMsg`.
The value of `$JSON_MSG` will be a blog of `json` formatted as defined for each command and query. You can find these definitions for the mixnet smart contract [here](https://github.com/nymtech/nym/blob/master/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs) and for the vesting contract [here](https://github.com/nymtech/nym/blob/master/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs) under `ExecuteMsg` and `QueryMsg`.
### Example command execution:
### Example command execution:
#### Delegate to a mix node
You can delegate to a mix node from the CLI using `nyxd` and signing the transaction with your ledger by filling in the values of this example:
You can delegate to a mix node from the CLI using `nyxd` and signing the transaction with your ledger by filling in the values of this example:
```
CONTRACT_ADDRESS=mixnet_contract_address
./nyxd tx wasm execute $CONTRACT_ADDRESS '{"delegate_to_mixnode":{"mix_identity":"MIX_NODE_IDENTITY","amount":{"amount":"100000000000","denom":"unym"}}}' --ledger --from admin --node https://rpc.dev.nymte.ch:443 --gas-prices 0.025unymt --gas auto -b block
```
> By replacing the value of `CONTRACT_ADDRESS` with the address of the vesting contract, you could use the above command to use tokens held in the vesting contract.
> By replacing the value of `CONTRACT_ADDRESS` with the address of the vesting contract, you could use the above command to use tokens held in the vesting contract.
#### Query a vesting schedule
You can query for (e.g.) seeing the current vesting period of an address by filling in the values of the following:
#### Query a vesting schedule
You can query for (e.g.) seeing the current vesting period of an address by filling in the values of the following:
```
CONTRACT_ADDRESS=vesting_contract_address
nyxd query wasm contract-state smart $CONTRACT_ADDRESS '{"get_current_vesting_period"}:{"address": "address_to_query_for"}' --ledger --from admin --node https://rpc.dev.nymte.ch:443 --chain-id qa-net --gas-prices 0.025unymt --gas auto -b block
nyxd query wasm contract-state smart $CONTRACT_ADDRESS '{"get_current_vesting_period"}:{"address": "address_to_query_for"}' --ledger --from admin --node https://rpc.dev.nymte.ch:443 --chain-id qa-net --gas-prices 0.025unymt --gas auto -b block
```
@@ -1,9 +1,9 @@
# RPC Nodes
RPC Nodes (which might otherwise be referred to as 'Lite Nodes' or just 'Full Nodes') differ from Validators in that they hold a copy of the Nyx blockchain, but do **not** participate in consensus / block-production.
RPC Nodes (which might otherwise be referred to as 'Lite Nodes' or just 'Full Nodes') differ from Validators in that they hold a copy of the Nyx blockchain, but do **not** participate in consensus / block-production.
You may want to set up an RPC Node for querying the blockchain, or in order to have an endpoint that your app can use to send transactions.
You may want to set up an RPC Node for querying the blockchain, or in order to have an endpoint that your app can use to send transactions.
In order to set up an RPC Node, simply follow the instructions to set up a [Validator](https://nymtech.net/operators/nodes/validator-setup.html), but **exclude the `nyxd tx staking create-validator` command**.
In order to set up an RPC Node, simply follow the instructions to set up a [Validator]() TODO LINK AFTER MERGE, but **exclude the `nyxd tx staking create-validator` command**.
If you want to fast-sync your node, check out the Polkachu snapshot and their other [resources](https://polkachu.com/seeds/nym).
@@ -1,9 +1,9 @@
# Types of Nym clients
At present, there are three standalone Nym clients. These are built as standalone binaries when building our codebase, but are most easily accessed through one of our SDKs:
At present, there are three Nym clients. These are built as standalone binaries when building our codebase, but are most easily accessed through one of our SDKs:
- the websocket (native) client - most easily accessed via the [Rust SDK]() TODO LINK and Go/C++ FFI TODO LINK
- the SOCKS5 client - most easily accessed via the [Rust SDK]() TODO LINK and Go/C++ FFI TODO LINK
- the wasm (webassembly) client - most easily via the [Typescript SDK]() TODO LINK
- the websocket (native) client - most easily accessed via the [Rust SDK](./rust) and [Go/C++ FFI](./rust/ffi).
- the SOCKS5 client - most easily accessed via the [Rust SDK](./rust) and [Go/C++ FFI](./rust/ffi).
- the wasm (webassembly) client - most easily via the [Typescript SDK](./typescript).
> For information about the role that clients play within the Nym system and their role when communicating with the Mixnet, see the [Client network docs](../network/architecture/mixnet/clients).
@@ -0,0 +1,5 @@
{
"socks5": "Socks5 (standalone)",
"webassembly-client": "Webassembly Client",
"websocket": "Websocket (standalone)"
}
@@ -1,70 +1,61 @@
# Socks5 Client
# Socks5 Client (Standalone)
TODO REMOVE THIS REPLACE WITH A BUILD INSTRUCTIONS DROPDOWN MENU COMPONENT
> The Nym Socks5 Client was built in the [building nym](../binaries/building-nym.md) section. If you haven't yet built Nym and want to run the code on this page, go there first.
## Current version
TODO
```
<!-- cmdrun ../../../../target/release/nym-socks5-client --version | grep "Build Version" | cut -b 21-26 -->
```
> This client can also be utilised via the [Rust SDK](../rust).
## What is this client for?
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:
```
External Systems:
+--------------------+
|------>| Monero blockchain |
| +--------------------+
| +--------------------+
|------>| Email server |
| +--------------------+
| +--------------------+
|------>| RPC endpoint |
| +--------------------+
| +--------------------+
|------>| Website |
| +--------------------+
| +--------------------+
+----------------------------------+ |------>| etc... |
| Mixnet: | | +--------------------+
| * Gateway your client is | |
| connected to | +--------------------+ |
| * Mix nodes 1 -> 3 |<-------->| Network requester |<------+
| * Gateway that network | +--------------------+
| requester is connected to |
+----------------------------------+
^
|
|
|
|
v
+-------------------+
| +---------------+ |
| | Nym client | |
| +---------------+ |
| ^ |
| | |
| | |
| | |
| v |
| +---------------+ |
| | Your app code | |
| +---------------+ |
+-------------------+
Your Local Machine
```mermaid
---
config:
theme: neo-dark
layout: elk
---
flowchart TB
subgraph Local Machine[Local Machine]
A[Application Logic]
B[Nym Socks5 Client]
end
A <-->|Bytes| B
B <-->|Sphinx Packets| EG
subgraph Mixnet Nodes[Mixnet Nodes]
EG[/Entry Gateway/]
M{Mix Nodes 1..3}
ExG[\Exit Gateway\]
end
EG <-->|Sphinx Packets| M
M <-->|Sphinx Packets| ExG
subgraph External Systems
C[Blockchain RPC]
D[Mail Server]
E[Message Server]
F[etc]
end
C <-->|Bytes| ExG
D <-->|Bytes| ExG
E <-->|Bytes| ExG
F <-->|Bytes| ExG
```
There are 2 pieces of software that work together to send SOCKS traffic through the mixnet: the `nym-socks5-client`, and the `nym-network-requester`.
There are 2 pieces of software that work together to send SOCKS traffic through the mixnet: the `nym-socks5-client`, and a `nym-node` running as an Exit Gateway.
> The functionality performed by the Exit Gateway was previously performed by the `nym-network-requester`: this functionality has been migrated into the Exit Gateway mode of the `nym-node`.
The `nym-socks5-client` allows you to do the following from your local machine:
* Take a TCP data stream from a application that can send traffic via SOCKS5.
* Chop up the TCP stream into multiple Sphinx packets, assigning sequence numbers to them, while leaving the TCP connection open for more data
* Send the Sphinx packets through the Nym Network. Packets are shuffled and mixed as they transit the mixnet.
The `nym-network-requester` then reassembles the original TCP stream using the packets' sequence numbers, and make the intended request. It will then chop up the response into Sphinx packets and send them back through the mixnet to your `nym-socks5-client`. The application will then receive its data, without even noticing that it wasn't talking to a "normal" SOCKS5 proxy!
The `nym-node` then reassembles the original TCP stream using the packets' sequence numbers, and make the intended request. It will then chop up the response into Sphinx packets and send them back through the mixnet to your `nym-socks5-client`. The application will then receive its data, without even noticing that it wasn't talking to a "normal" SOCKS5 proxy!
## Download or compile socks5 client
If you are using OSX or a Debian-based operating system, you can download the `nym-socks5-client` binary from our [Github releases page](https://github.com/nymtech/nym/releases).
If you are using a different operating system, or want to build from source, simply use `cargo build --release` from the root of the Nym monorepo.
## Client setup
### Viewing command help
@@ -75,12 +66,6 @@ You can check that your binaries are properly compiled with:
./nym-socks5-client --help
```
~~~admonish example collapsible=true title="Console output"
```
<!-- cmdrun ../../../../target/release/nym-socks5-client --help -->
```
~~~
You can check the necessary parameters for the available commands by running:
```
@@ -94,17 +79,11 @@ Before you can use the client, you need to initalise a new instance of it, which
./nym-socks5-client init --id docs-example --use-reply-surbs true --provider Entztfv6Uaz2hpYHQJ6JKoaCTpDL5dja18SuQWVJAmmx.Cvhn9rBJw5Ay9wgHcbgCnVg89MPSV5s2muPV2YF1BXYu@Fo4f4SQLdoyoGkFae5TpVhRVoXCF8UiypLVGtGjujVPf
```
~~~admonish example collapsible=true title="Console output"
```
<!-- cmdrun ../../../../target/release/nym-socks5-client init --id docs-example --provider Entztfv6Uaz2hpYHQJ6JKoaCTpDL5dja18SuQWVJAmmx.Cvhn9rBJw5Ay9wgHcbgCnVg89MPSV5s2muPV2YF1BXYu@Fo4f4SQLdoyoGkFae5TpVhRVoXCF8UiypLVGtGjujVPf -->
```
~~~
The `--id` in the example above is a local identifier so that you can name your clients and keep track of them on your local system; it is **never** transmitted over the network.
The `--use-reply-surbs` field denotes whether you wish to send [SURBs](https://nymtech.net/docs/architecture/traffic-flow.md#private-replies-using-surbs) along with your request. It defaults to `false`, we are explicitly setting it as `true`. It defaults to `false` for compatibility with older versions of the [Network Requester](https://nymtech.net/nodes/network-requester.md).
The `--use-reply-surbs` field denotes whether you wish to send [SURBs](../../network/concepts/anonymous-replies) along with your request. It defaults to `false`, we are explicitly setting it as `true`. It defaults to `false` for compatibility with versions of the pre-smoosh `nym-network-requester` binary which will soon be deprecated.
The `--provider` field needs to be filled with the Nym address of a Network Requester that can make network requests on your behalf. If you don't want to [run your own](https://nymtech.net/operators/nodes/network-requester.md) you can select one from the [mixnet explorer](https://explorer.nymtech.net/network-components/service-providers) by copying its `Client ID` and using this as the value of the `--provider` flag. Alternatively, you could use [this list](https://harbourmaster.nymtech.net/).
The `--provider` field needs to be filled with the Nym address of an Exit Gateway that can make network requests on your behalf. You can select one from the [mixnet explorer](https://explorer.nymtech.net/network-components/gateways) by copying its `Client ID` and using this as the value of the `--provider` flag. Alternatively, you could use [Harbourmaster](https://harbourmaster.nymtech.net/).
#### Choosing a Gateway
By default - as in the example above - your client will choose a random gateway to connect to.
@@ -116,6 +95,8 @@ However, there are several options for choosing a gateway, if you do not want on
* send few ping messages to all of them, and measure response times.
* create a weighted distribution to randomly choose one, favouring ones with lower latency.
You can select one from the [mixnet explorer](https://explorer.nymtech.net/network-components/gateways) by copying its `Client ID` and using this as the value of the `--provider` flag. Alternatively, you could use [Harbourmaster](https://harbourmaster.nymtech.net/).
> Note this doesn't mean that your client will pick the closest gateway to you, but it will be far more likely to connect to gateway with a 20ms ping rather than 200ms
### Configuring your client
@@ -195,7 +176,7 @@ When trying to connect your app, generally the proxy settings are found in `sett
Here is an example of setting the proxy connecting in Blockstream Green:
![Blockstream Green settings](../images/wallet-proxy-settings/blockstream-green.gif)
![Blockstream Green settings](../../images/wallet-proxy-settings/blockstream-green.gif)
Most wallets and other applications will work basically the same way: find the network proxy settings, enter the proxy url (host: **localhost**, port: **1080**).
@@ -0,0 +1,823 @@
# `nym-socks5-client` Binary Commands (Autogenerated)
These docs are autogenerated by the [`autodocs`](https://github.com/nymtech/nym/tree/max/new-docs-framework/documentation/autodoc) script.
```sh
A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address
Usage: nym-socks5-client [OPTIONS] <COMMAND>
Commands:
init Initialise a Nym client. Do this first!
run Run the Nym client with provided configuration client optionally overriding set parameters
import-credential Import a pre-generated credential
list-gateways List all registered with gateways
add-gateway Add new gateway to this client
switch-gateway Change the currently active gateway. Note that you must have already registered with the new gateway!
show-ticketbooks Display information associated with the imported ticketbooks,
build-info Show build information of this binary
completions Generate shell completions
generate-fig-spec Generate Fig specification
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 client
--no-banner Flag used for disabling the printed banner in tty
-h, --help Print help
-V, --version Print version
```
### `init`
```sh
Initialise a Nym client. Do this first!
Usage: nym-socks5-client init [OPTIONS] --id <ID> --provider <PROVIDER>
Options:
--id <ID>
Id of client we want to create config for
--gateway <GATEWAY>
Id of the gateway we are going to connect to
--force-tls-gateway
Specifies whether the client will attempt to enforce tls connection to the desired gateway
--latency-based-selection
Specifies whether the new gateway should be determined based by latency as opposed to being chosen uniformly
--nym-apis <NYM_APIS>
Comma separated list of rest endpoints of the API validators
--provider <PROVIDER>
Address of the socks5 provider to send messages to
--use-reply-surbs <USE_REPLY_SURBS>
Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. While this is going to hide its actual address information, it will make the actual communication slower and consume nearly double the bandwidth as it will require sending reply SURBs.
Note that some service providers might not support this.
[possible values: true, false]
-p, --port <PORT>
Port for the socket to listen on in all subsequent runs
--host <HOST>
The custom host on which the socks5 client will be listening for requests
-o, --output <OUTPUT>
[default: text]
[possible values: text, json]
-h, --help
Print help (see a summary with '-h')
```
### `run`
```sh
Run the Nym client with provided configuration client optionally overriding set parameters
Usage: nym-socks5-client run [OPTIONS] --id <ID>
Options:
--id <ID>
Id of client we want to create config for
--gateway <GATEWAY>
Id of the gateway we want to connect to. If overridden, it is user's responsibility to ensure prior registration happened
--nym-apis <NYM_APIS>
Comma separated list of rest endpoints of the API validators
--use-anonymous-replies <USE_ANONYMOUS_REPLIES>
Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. While this is going to hide its actual address information, it will make the actual communication slower and consume nearly double the bandwidth as it will require sending reply SURBs.
Note that some service providers might not support this.
[possible values: true, false]
--provider <PROVIDER>
Address of the socks5 provider to send messages to
-p, --port <PORT>
Port for the socket to listen on
--host <HOST>
The custom host on which the socks5 client will be listening for requests
-h, --help
Print help (see a summary with '-h')
```
### `import-credential`
```sh
Import a pre-generated credential
Usage: nym-socks5-client import-credential --id <ID> <--credential-data <CREDENTIAL_DATA>|--credential-path <CREDENTIAL_PATH>>
Options:
--id <ID>
Id of client that is going to import the credential
--credential-data <CREDENTIAL_DATA>
Explicitly provide the encoded credential data (as base58)
--credential-path <CREDENTIAL_PATH>
Specifies the path to file containing binary credential data
-h, --help
Print help
```
### `list-gateways`
```sh
List all registered with gateways
Usage: nym-socks5-client list-gateways [OPTIONS] --id <ID>
Options:
--id <ID> Id of client we want to list gateways for
-o, --output <OUTPUT> [default: text] [possible values: text, json]
-h, --help Print help
```
### `add-gateway`
```sh
Add new gateway to this client
Usage: nym-socks5-client add-gateway [OPTIONS] --id <ID>
Options:
--id <ID> Id of client we want to add gateway for
--gateway-id <GATEWAY_ID> Explicitly specify id of the gateway to register with. If unspecified, a random gateway will be chosen instead
--force-tls-gateway Specifies whether the client will attempt to enforce tls connection to the desired gateway
--latency-based-selection Specifies whether the new gateway should be determined based by latency as opposed to being chosen uniformly
--set-active Specify whether this new gateway should be set as the active one
--nym-apis <NYM_APIS> Comma separated list of rest endpoints of the API validators
-o, --output <OUTPUT> [default: text] [possible values: text, json]
-h, --help Print help
```
### `build-info`
```sh
Show build information of this binary
Usage: nym-socks5-client build-info [OPTIONS]
Options:
-o, --output <OUTPUT> [default: text] [possible values: text, json]
-h, --help Print help
```
Example output:
```sh
Binary Name: nym-socks5-client
Build Timestamp: 2024-10-09T13:56:14.428750844Z
Build Version: 1.1.39
Commit SHA: fac373c1db4fa5389ba61de7943c77023467bccb
Commit Date: 2024-10-09T14:59:40.000000000+02:00
Commit Branch: max/new-docs-framework
rustc Version: 1.80.0
rustc Channel: stable
cargo Profile: release
```
### `completions`
```sh
Generate shell completions
Usage: nym-socks5-client completions <SHELL>
Arguments:
<SHELL> [possible values: bash, elvish, fish, power-shell, zsh]
Options:
-h, --help Print help
```
### `generate-fig-spec`
```sh
Generate Fig specification
Usage: nym-socks5-client generate-fig-spec
Options:
-h, --help Print help
```
Example output:
```sh
const completion: Fig.Spec = {
name: "nym-socks5-client",
description: "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address",
subcommands: [
{
name: "init",
description: "Initialise a Nym client. Do this first!",
options: [
{
name: "--id",
description: "Id of client we want to create config for",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: "--gateway",
description: "Id of the gateway we are going to connect to",
isRepeatable: true,
args: {
name: "gateway",
isOptional: true,
},
},
{
name: "--nyxd-urls",
description: "Comma separated list of rest endpoints of the nyxd validators",
hidden: true,
isRepeatable: true,
args: {
name: "nyxd_urls",
isOptional: true,
},
},
{
name: "--nym-apis",
description: "Comma separated list of rest endpoints of the API validators",
isRepeatable: true,
args: {
name: "nym_apis",
isOptional: true,
},
},
{
name: "--custom-mixnet",
description: "Path to .json file containing custom network specification",
hidden: true,
isRepeatable: true,
args: {
name: "custom_mixnet",
isOptional: true,
template: "filepaths",
},
},
{
name: "--enabled-credentials-mode",
description: "Set this client to work in a enabled credentials mode that would attempt to use gateway with bandwidth credential requirement",
hidden: true,
isRepeatable: true,
args: {
name: "enabled_credentials_mode",
isOptional: true,
suggestions: [
"true",
"false",
],
},
},
{
name: "--provider",
description: "Address of the socks5 provider to send messages to",
isRepeatable: true,
args: {
name: "provider",
},
},
{
name: "--use-reply-surbs",
description: "Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. While this is going to hide its actual address information, it will make the actual communication slower and consume nearly double the bandwidth as it will require sending reply SURBs",
isRepeatable: true,
args: {
name: "use_reply_surbs",
isOptional: true,
suggestions: [
"true",
"false",
],
},
},
{
name: ["-p", "--port"],
description: "Port for the socket to listen on in all subsequent runs",
isRepeatable: true,
args: {
name: "port",
isOptional: true,
},
},
{
name: "--host",
description: "The custom host on which the socks5 client will be listening for requests",
isRepeatable: true,
args: {
name: "host",
isOptional: true,
},
},
{
name: ["-o", "--output"],
isRepeatable: true,
args: {
name: "output",
isOptional: true,
suggestions: [
"text",
"json",
],
},
},
{
name: "--force-tls-gateway",
description: "Specifies whether the client will attempt to enforce tls connection to the desired gateway",
},
{
name: "--latency-based-selection",
description: "Specifies whether the new gateway should be determined based by latency as opposed to being chosen uniformly",
exclusiveOn: [
"--gateway",
],
},
{
name: "--fastmode",
description: "Mostly debug-related option to increase default traffic rate so that you would not need to modify config post init",
},
{
name: "--no-cover",
description: "Disable loop cover traffic and the Poisson rate limiter (for debugging only)",
},
{
name: ["-h", "--help"],
description: "Print help (see more with '--help')",
},
],
},
{
name: "run",
description: "Run the Nym client with provided configuration client optionally overriding set parameters",
options: [
{
name: "--id",
description: "Id of client we want to create config for",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: "--gateway",
description: "Id of the gateway we want to connect to. If overridden, it is user's responsibility to ensure prior registration happened",
isRepeatable: true,
args: {
name: "gateway",
isOptional: true,
},
},
{
name: "--nyxd-urls",
description: "Comma separated list of rest endpoints of the nyxd validators",
hidden: true,
isRepeatable: true,
args: {
name: "nyxd_urls",
isOptional: true,
},
},
{
name: "--nym-apis",
description: "Comma separated list of rest endpoints of the API validators",
isRepeatable: true,
args: {
name: "nym_apis",
isOptional: true,
},
},
{
name: "--custom-mixnet",
description: "Path to .json file containing custom network specification",
hidden: true,
isRepeatable: true,
args: {
name: "custom_mixnet",
isOptional: true,
template: "filepaths",
},
},
{
name: "--enabled-credentials-mode",
description: "Set this client to work in a enabled credentials mode that would attempt to use gateway with bandwidth credential requirement",
hidden: true,
isRepeatable: true,
args: {
name: "enabled_credentials_mode",
isOptional: true,
suggestions: [
"true",
"false",
],
},
},
{
name: "--use-anonymous-replies",
description: "Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. While this is going to hide its actual address information, it will make the actual communication slower and consume nearly double the bandwidth as it will require sending reply SURBs",
isRepeatable: true,
args: {
name: "use_anonymous_replies",
isOptional: true,
suggestions: [
"true",
"false",
],
},
},
{
name: "--provider",
description: "Address of the socks5 provider to send messages to",
isRepeatable: true,
args: {
name: "provider",
isOptional: true,
},
},
{
name: ["-p", "--port"],
description: "Port for the socket to listen on",
isRepeatable: true,
args: {
name: "port",
isOptional: true,
},
},
{
name: "--host",
description: "The custom host on which the socks5 client will be listening for requests",
isRepeatable: true,
args: {
name: "host",
isOptional: true,
},
},
{
name: "--geo-routing",
description: "Set geo-aware mixnode selection when sending mixnet traffic, for experiments only",
hidden: true,
isRepeatable: true,
args: {
name: "geo_routing",
isOptional: true,
},
},
{
name: "--fastmode",
description: "Mostly debug-related option to increase default traffic rate so that you would not need to modify config post init",
},
{
name: "--no-cover",
description: "Disable loop cover traffic and the Poisson rate limiter (for debugging only)",
},
{
name: "--medium-toggle",
description: "Enable medium mixnet traffic, for experiments only. This includes things like disabling cover traffic, no per hop delays, etc",
},
{
name: "--outfox",
},
{
name: ["-h", "--help"],
description: "Print help (see more with '--help')",
},
],
},
{
name: "import-credential",
description: "Import a pre-generated credential",
options: [
{
name: "--id",
description: "Id of client that is going to import the credential",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: "--credential-data",
description: "Explicitly provide the encoded credential data (as base58)",
isRepeatable: true,
args: {
name: "credential_data",
isOptional: true,
},
},
{
name: "--credential-path",
description: "Specifies the path to file containing binary credential data",
isRepeatable: true,
args: {
name: "credential_path",
isOptional: true,
template: "filepaths",
},
},
{
name: "--version",
hidden: true,
isRepeatable: true,
args: {
name: "version",
isOptional: true,
},
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "list-gateways",
description: "List all registered with gateways",
options: [
{
name: "--id",
description: "Id of client we want to list gateways for",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: ["-o", "--output"],
isRepeatable: true,
args: {
name: "output",
isOptional: true,
suggestions: [
"text",
"json",
],
},
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "add-gateway",
description: "Add new gateway to this client",
options: [
{
name: "--id",
description: "Id of client we want to add gateway for",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: "--gateway-id",
description: "Explicitly specify id of the gateway to register with. If unspecified, a random gateway will be chosen instead",
isRepeatable: true,
args: {
name: "gateway_id",
isOptional: true,
},
},
{
name: "--nym-apis",
description: "Comma separated list of rest endpoints of the API validators",
isRepeatable: true,
args: {
name: "nym_apis",
isOptional: true,
},
},
{
name: "--custom-mixnet",
description: "Path to .json file containing custom network specification",
hidden: true,
isRepeatable: true,
args: {
name: "custom_mixnet",
isOptional: true,
template: "filepaths",
},
},
{
name: ["-o", "--output"],
isRepeatable: true,
args: {
name: "output",
isOptional: true,
suggestions: [
"text",
"json",
],
},
},
{
name: "--force-tls-gateway",
description: "Specifies whether the client will attempt to enforce tls connection to the desired gateway",
},
{
name: "--latency-based-selection",
description: "Specifies whether the new gateway should be determined based by latency as opposed to being chosen uniformly",
exclusiveOn: [
"--gateway-id",
],
},
{
name: "--set-active",
description: "Specify whether this new gateway should be set as the active one",
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "switch-gateway",
description: "Change the currently active gateway. Note that you must have already registered with the new gateway!",
options: [
{
name: "--id",
description: "Id of client we want to list gateways for",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: "--gateway-id",
description: "Id of the gateway we want to switch to",
isRepeatable: true,
args: {
name: "gateway_id",
},
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "show-ticketbooks",
description: "Display information associated with the imported ticketbooks,",
options: [
{
name: "--id",
description: "Id of client that is going to display the ticketbook information",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: ["-o", "--output"],
isRepeatable: true,
args: {
name: "output",
isOptional: true,
suggestions: [
"text",
"json",
],
},
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "build-info",
description: "Show build information of this binary",
options: [
{
name: ["-o", "--output"],
isRepeatable: true,
args: {
name: "output",
isOptional: true,
suggestions: [
"text",
"json",
],
},
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "completions",
description: "Generate shell completions",
options: [
{
name: ["-h", "--help"],
description: "Print help",
},
],
args: {
name: "shell",
suggestions: [
"bash",
"elvish",
"fish",
"power-shell",
"zsh",
],
},
},
{
name: "generate-fig-spec",
description: "Generate Fig specification",
options: [
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "help",
description: "Print this message or the help of the given subcommand(s)",
subcommands: [
{
name: "init",
description: "Initialise a Nym client. Do this first!",
},
{
name: "run",
description: "Run the Nym client with provided configuration client optionally overriding set parameters",
},
{
name: "import-credential",
description: "Import a pre-generated credential",
},
{
name: "list-gateways",
description: "List all registered with gateways",
},
{
name: "add-gateway",
description: "Add new gateway to this client",
},
{
name: "switch-gateway",
description: "Change the currently active gateway. Note that you must have already registered with the new gateway!",
},
{
name: "show-ticketbooks",
description: "Display information associated with the imported ticketbooks,",
},
{
name: "build-info",
description: "Show build information of this binary",
},
{
name: "completions",
description: "Generate shell completions",
},
{
name: "generate-fig-spec",
description: "Generate Fig specification",
},
{
name: "help",
description: "Print this message or the help of the given subcommand(s)",
},
],
},
],
options: [
{
name: ["-c", "--config-env-file"],
description: "Path pointing to an env file that configures the client",
isRepeatable: true,
args: {
name: "config_env_file",
isOptional: true,
template: "filepaths",
},
},
{
name: "--no-banner",
description: "Flag used for disabling the printed banner in tty",
},
{
name: ["-h", "--help"],
description: "Print help",
},
{
name: ["-V", "--version"],
description: "Print version",
},
],
};
export default completion;
```
@@ -1,45 +0,0 @@
# Setup
> `nym-socks5-client` now also supports SOCKS4 and SOCKS4A protocols as well as SOCKS5.
The Nym socks5 client allows you to proxy traffic from a desktop application through the mixnet, meaning you can send and receive information from remote application servers without leaking metadata which can be used to deanonymise you, even if you're using an encrypted application such as Signal.
```admonish info
Since the beginning of 2024 NymConnect is no longer maintained. Nym is developing a new client called [NymVPN](https://nymvpn.com), an application routing all users traffic thorugh the mixnet.
If users want to route their traffic through socks5 we advice to use this client. If you want to run deprecated NymConnect, visit [NymConnect archive page](../../archive/nym-connect.md) with setup and application examples.
```
## Setup and Run
### Download or compile socks5 client
If you are using OSX or a Debian-based operating system, you can download the `nym-socks5-client` binary from our [Github releases page](https://github.com/nymtech/nym/releases).
If you are using a different operating system, head over to the [Building from Source](https://nymtech.net/docs/binaries/building-nym.html) page for instructions on how to build the repository from source.
### Initialise your socks5 client
To initialise your `nym-socks5-client` you need to have an address of a Network Requester (NR). Nowadays NR is part of every Exit Gateway (`nym-node --mode exit-gateway`). The easiest way to get a NR address is to visit [harbourmaster.nymtech.net](https://harbourmaster.nymtech.net/) and scroll down to *SOCKS5 Network Requesters* table. There you can filter the NR by Gateways identity address, and other options.
Use the following command to initialise `nym-socs5-client` where `<ID>` can be anything you want (it's only for local config file storage) and `<PROVIDER>` is suplemented with a NR address:
```
./nym-socks5-client init --id <ID> --provider <PROVIDER>
```
~~~admonish tip
Another option to find a NR address associated with a Gateway is to query nodes [*Self Described* API endpoint](https://validator.nymtech.net/api/v1/gateways/described) where the NR address is noted like in this example:
```sh
"network_requester": {
"address": "CyuN49nkyeuiLohSpV5A1MbSqcugHLJQ95B5HooCpjv8.CguTh45Vp99QuGWZRBKpBjZDQbsJaHaXqAMGyc4Qhkzp@2w5RduXRqxKgHt1wtp4qGA4AfXaBj8TuUj1LvcPe2Ea1",
"uses_exit_policy": true
}
```
~~~
### Start your socks5 client
Now your client is initialised, start it with the following:
```
./nym-socks5-client run --id <ID>
```
@@ -1,33 +0,0 @@
# Using Your Client
## Proxying traffic
After completing the steps above, your local `nym-socks5-client` will be listening on `localhost:1080` ready to proxy traffic to the Network Requester set as the `--provider` when initialising.
When trying to connect your app, generally the proxy settings are found in `settings->advanced` or `settings->connection`.
Here is an example of setting the proxy connecting in Blockstream Green:
![Blockstream Green settings](../../images/blockstream-green.gif)
Most wallets and other applications will work basically the same way: find the network proxy settings, enter the proxy url (host: **localhost**, port: **1080**).
In some other applications, this might be written as **localhost:1080** if there's only one proxy entry field.
## Supported Applications
Any application which can be redirected over Socks5 proxy should work. Nym community has been successfully running over Nym Mixnet these applications:
- Bitcoin Electrum wallet
- Monero wallet (GUI and CLI with monerod)
- Telegram chat
- Element/Matrix chat
- Firo wallet
- Blockstream Green
> DarkFi's ircd chat was previously supported: they have moved to DarkIrc: whether the existing integration work is still operational needs to be tested.
Keep in mind that Nym has been developing a new client **[NymVPN](https://nymvpn.com) (GUI and CLI) routing all users traffic through the Mixnet.**
## Further reading
If you want to dig more into the architecture and use of the socks5 client check out its documentation [here](https://nymtech.net/docs/clients/socks5-client.html).
@@ -1,22 +0,0 @@
# Webassembly Client
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](../sdk/typescript.md). **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](https://sdk.nymtech.net) for examples of usage.
There are also example applications located in the `clients/webassembly` directory in the main Nym platform codebase.
## Think about what you're sending!
```admonish caution
Think about what information your app sends. That goes for whatever you put into your Sphinx packet messages as well as what your app's environment may leak.
```
Whenever you write client PEAPPs using HTML/JavaScript, we recommend that you do not load external resources from CDNs. Webapp developers do this all the time, to save load time for common resources, or just for convenience. But when you're writing privacy apps it's better not to make these kinds of requests. Pack everything locally.
If you use only local resources within your Electron app or your browser extensions, explicitly encoding request data in a Sphinx packet does protect you from the normal leakage that gets sent in a browser HTTP request. [There's a lot of stuff that leaks when you make an HTTP request from a browser window](https://panopticlick.eff.org/). Luckily, all that metadata and request leakage doesn't happen in Nym, because you're choosing very explicitly what to encode into Sphinx packets, instead of sending a whole browser environment by default.
@@ -0,0 +1,22 @@
# Webassembly Client
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](../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](../typescript) for examples of usage.
## Think about what you're sending!
import { Callout } from 'nextra/components'
<Callout type="warning" emoji="⚠️">
Think about what information your app sends. That goes for whatever you put into your Sphinx packet messages as well as what your app's environment may leak.
</Callout>
Whenever you write client apps using HTML/JavaScript, we recommend that you **do not load external resources from CDNs**. Webapp developers do this all the time, to save load time for common resources, or just for convenience. But when you're writing privacy apps it's better not to make these kinds of requests. Pack everything locally.
If you use only local resources within your Electron app or your browser extensions, explicitly encoding request data in a Sphinx packet does protect you from the normal leakage that gets sent in a browser HTTP request. [There's a lot of stuff that leaks when you make an HTTP request from a browser window](https://panopticlick.eff.org/). Luckily, all that metadata and request leakage doesn't happen in Nym, because you're choosing very explicitly what to encode into Sphinx packets, instead of sending a whole browser environment by default.
@@ -1,13 +1,13 @@
# Websocket Client
# Websocket Client (Standalone)
> The Nym Websocket Client was built in the [building nym](../binaries/building-nym.md) section. If you haven't yet built Nym and want to run the code on this page, go there first.
> This client can also be utilised via the [Rust SDK](../rust) and [Go/C++ FFI](../rust/ffi).
## Current version
```
<!-- cmdrun ../../../../target/release/nym-client --version | grep "Build Version" | cut -b 21-26 -->
```
You can run this client as a standalone process and pipe traffic into it to be sent through the mixnet. This is useful if you're building an application in a language other than Typescript or Rust and cannot utilise one of the SDKs.
You can run this client as a standalone process and pipe traffic into it to be sent through the mixnet. This is useful if you're building an application in a language other than Typescript or Rust and cannot utilise one of the SDKs.
You can find the code for this client [here](https://github.com/nymtech/nym/tree/master/clients/native).
You can find the code for this client [here](https://github.com/nymtech/nym/tree/develop/clients/native).
## Download or compile client
If you are using OSX or a Debian-based operating system, you can download the `nym-socks5-client` binary from our [Github releases page](https://github.com/nymtech/nym/releases).
If you are using a different operating system, or want to build from source, simply use `cargo build --release` from the root of the Nym monorepo.
@@ -0,0 +1,754 @@
# `nym-client` Binary Commands (Autogenerated)
These docs are autogenerated by the [`autodocs`](https://github.com/nymtech/nym/tree/max/new-docs-framework/documentation/autodoc) script.
```sh
Implementation of the Nym Client
Usage: nym-client [OPTIONS] <COMMAND>
Commands:
init Initialise a Nym client. Do this first!
run Run the Nym client with provided configuration client optionally overriding set parameters
import-credential Import a pre-generated credential
list-gateways List all registered with gateways
add-gateway Add new gateway to this client
switch-gateway Change the currently active gateway. Note that you must have already registered with the new gateway!
show-ticketbooks Display information associated with the imported ticketbooks,
build-info Show build information of this binary
completions Generate shell completions
generate-fig-spec Generate Fig specification
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 client
--no-banner Flag used for disabling the printed banner in tty
-h, --help Print help
-V, --version Print version
```
### `init`
```sh
Initialise a Nym client. Do this first!
Usage: nym-client init [OPTIONS] --id <ID>
Options:
--id <ID>
Id of client we want to create config for
--gateway <GATEWAY>
Id of the gateway we are going to connect to
--force-tls-gateway
Specifies whether the client will attempt to enforce tls connection to the desired gateway
--latency-based-selection
Specifies whether the new gateway should be determined based by latency as opposed to being chosen uniformly
--nym-apis <NYM_APIS>
Comma separated list of rest endpoints of the API validators
--disable-socket <DISABLE_SOCKET>
Whether to not start the websocket [possible values: true, false]
-p, --port <PORT>
Port for the socket (if applicable) to listen on in all subsequent runs
--host <HOST>
Ip for the socket (if applicable) to listen for requests
-o, --output <OUTPUT>
[default: text] [possible values: text, json]
-h, --help
Print help
```
### `run`
```sh
Run the Nym client with provided configuration client optionally overriding set parameters
Usage: nym-client run [OPTIONS] --id <ID>
Options:
--id <ID>
Id of client we want to create config for
--gateway <GATEWAY>
Id of the gateway we want to connect to. If overridden, it is user's responsibility to ensure prior registration happened
--nym-apis <NYM_APIS>
Comma separated list of rest endpoints of the API validators
--disable-socket <DISABLE_SOCKET>
Whether to not start the websocket [possible values: true, false]
-p, --port <PORT>
Port for the socket to listen on
--host <HOST>
Ip for the socket (if applicable) to listen for requests
-h, --help
Print help
```
### `import-credential`
```sh
Import a pre-generated credential
Usage: nym-client import-credential --id <ID> <--credential-data <CREDENTIAL_DATA>|--credential-path <CREDENTIAL_PATH>>
Options:
--id <ID>
Id of client that is going to import the credential
--credential-data <CREDENTIAL_DATA>
Explicitly provide the encoded credential data (as base58)
--credential-path <CREDENTIAL_PATH>
Specifies the path to file containing binary credential data
-h, --help
Print help
```
### `list-gateways`
```sh
List all registered with gateways
Usage: nym-client list-gateways [OPTIONS] --id <ID>
Options:
--id <ID> Id of client we want to list gateways for
-o, --output <OUTPUT> [default: text] [possible values: text, json]
-h, --help Print help
```
### `switch-gateway`
```sh
Change the currently active gateway. Note that you must have already registered with the new gateway!
Usage: nym-client switch-gateway --id <ID> --gateway-id <GATEWAY_ID>
Options:
--id <ID> Id of client we want to list gateways for
--gateway-id <GATEWAY_ID> Id of the gateway we want to switch to
-h, --help Print help
```
### `build-info`
```sh
Show build information of this binary
Usage: nym-client build-info [OPTIONS]
Options:
-o, --output <OUTPUT> [default: text] [possible values: text, json]
-h, --help Print help
```
Example output:
```sh
Binary Name: nym-client
Build Timestamp: 2024-10-09T13:56:14.428750844Z
Build Version: 1.1.39
Commit SHA: fac373c1db4fa5389ba61de7943c77023467bccb
Commit Date: 2024-10-09T14:59:40.000000000+02:00
Commit Branch: max/new-docs-framework
rustc Version: 1.80.0
rustc Channel: stable
cargo Profile: release
```
### `completions`
```sh
Generate shell completions
Usage: nym-client completions <SHELL>
Arguments:
<SHELL> [possible values: bash, elvish, fish, power-shell, zsh]
Options:
-h, --help Print help
```
### `generate-fig-spec`
```sh
Generate Fig specification
Usage: nym-client generate-fig-spec
Options:
-h, --help Print help
```
Example output:
```sh
const completion: Fig.Spec = {
name: "nym-native-client",
description: "Implementation of the Nym Client",
subcommands: [
{
name: "init",
description: "Initialise a Nym client. Do this first!",
options: [
{
name: "--id",
description: "Id of client we want to create config for",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: "--gateway",
description: "Id of the gateway we are going to connect to",
isRepeatable: true,
args: {
name: "gateway",
isOptional: true,
},
},
{
name: "--nyxd-urls",
description: "Comma separated list of rest endpoints of the nyxd validators",
hidden: true,
isRepeatable: true,
args: {
name: "nyxd_urls",
isOptional: true,
},
},
{
name: "--nym-apis",
description: "Comma separated list of rest endpoints of the API validators",
isRepeatable: true,
args: {
name: "nym_apis",
isOptional: true,
},
},
{
name: "--custom-mixnet",
description: "Path to .json file containing custom network specification",
hidden: true,
isRepeatable: true,
args: {
name: "custom_mixnet",
isOptional: true,
template: "filepaths",
},
},
{
name: "--enabled-credentials-mode",
description: "Set this client to work in a enabled credentials mode that would attempt to use gateway with bandwidth credential requirement",
hidden: true,
isRepeatable: true,
args: {
name: "enabled_credentials_mode",
isOptional: true,
suggestions: [
"true",
"false",
],
},
},
{
name: "--disable-socket",
description: "Whether to not start the websocket",
isRepeatable: true,
args: {
name: "disable_socket",
isOptional: true,
suggestions: [
"true",
"false",
],
},
},
{
name: ["-p", "--port"],
description: "Port for the socket (if applicable) to listen on in all subsequent runs",
isRepeatable: true,
args: {
name: "port",
isOptional: true,
},
},
{
name: "--host",
description: "Ip for the socket (if applicable) to listen for requests",
isRepeatable: true,
args: {
name: "host",
isOptional: true,
},
},
{
name: ["-o", "--output"],
isRepeatable: true,
args: {
name: "output",
isOptional: true,
suggestions: [
"text",
"json",
],
},
},
{
name: "--force-tls-gateway",
description: "Specifies whether the client will attempt to enforce tls connection to the desired gateway",
},
{
name: "--latency-based-selection",
description: "Specifies whether the new gateway should be determined based by latency as opposed to being chosen uniformly",
exclusiveOn: [
"--gateway",
],
},
{
name: "--fastmode",
description: "Mostly debug-related option to increase default traffic rate so that you would not need to modify config post init",
},
{
name: "--no-cover",
description: "Disable loop cover traffic and the Poisson rate limiter (for debugging only)",
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "run",
description: "Run the Nym client with provided configuration client optionally overriding set parameters",
options: [
{
name: "--id",
description: "Id of client we want to create config for",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: "--gateway",
description: "Id of the gateway we want to connect to. If overridden, it is user's responsibility to ensure prior registration happened",
isRepeatable: true,
args: {
name: "gateway",
isOptional: true,
},
},
{
name: "--nyxd-urls",
description: "Comma separated list of rest endpoints of the nyxd validators",
hidden: true,
isRepeatable: true,
args: {
name: "nyxd_urls",
isOptional: true,
},
},
{
name: "--nym-apis",
description: "Comma separated list of rest endpoints of the API validators",
isRepeatable: true,
args: {
name: "nym_apis",
isOptional: true,
},
},
{
name: "--custom-mixnet",
description: "Path to .json file containing custom network specification",
hidden: true,
isRepeatable: true,
args: {
name: "custom_mixnet",
isOptional: true,
template: "filepaths",
},
},
{
name: "--enabled-credentials-mode",
description: "Set this client to work in a enabled credentials mode that would attempt to use gateway with bandwidth credential requirement",
hidden: true,
isRepeatable: true,
args: {
name: "enabled_credentials_mode",
isOptional: true,
suggestions: [
"true",
"false",
],
},
},
{
name: "--disable-socket",
description: "Whether to not start the websocket",
isRepeatable: true,
args: {
name: "disable_socket",
isOptional: true,
suggestions: [
"true",
"false",
],
},
},
{
name: ["-p", "--port"],
description: "Port for the socket to listen on",
isRepeatable: true,
args: {
name: "port",
isOptional: true,
},
},
{
name: "--host",
description: "Ip for the socket (if applicable) to listen for requests",
isRepeatable: true,
args: {
name: "host",
isOptional: true,
},
},
{
name: "--fastmode",
description: "Mostly debug-related option to increase default traffic rate so that you would not need to modify config post init",
},
{
name: "--no-cover",
description: "Disable loop cover traffic and the Poisson rate limiter (for debugging only)",
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "import-credential",
description: "Import a pre-generated credential",
options: [
{
name: "--id",
description: "Id of client that is going to import the credential",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: "--credential-data",
description: "Explicitly provide the encoded credential data (as base58)",
isRepeatable: true,
args: {
name: "credential_data",
isOptional: true,
},
},
{
name: "--credential-path",
description: "Specifies the path to file containing binary credential data",
isRepeatable: true,
args: {
name: "credential_path",
isOptional: true,
template: "filepaths",
},
},
{
name: "--version",
hidden: true,
isRepeatable: true,
args: {
name: "version",
isOptional: true,
},
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "list-gateways",
description: "List all registered with gateways",
options: [
{
name: "--id",
description: "Id of client we want to list gateways for",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: ["-o", "--output"],
isRepeatable: true,
args: {
name: "output",
isOptional: true,
suggestions: [
"text",
"json",
],
},
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "add-gateway",
description: "Add new gateway to this client",
options: [
{
name: "--id",
description: "Id of client we want to add gateway for",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: "--gateway-id",
description: "Explicitly specify id of the gateway to register with. If unspecified, a random gateway will be chosen instead",
isRepeatable: true,
args: {
name: "gateway_id",
isOptional: true,
},
},
{
name: "--nym-apis",
description: "Comma separated list of rest endpoints of the API validators",
isRepeatable: true,
args: {
name: "nym_apis",
isOptional: true,
},
},
{
name: "--custom-mixnet",
description: "Path to .json file containing custom network specification",
hidden: true,
isRepeatable: true,
args: {
name: "custom_mixnet",
isOptional: true,
template: "filepaths",
},
},
{
name: ["-o", "--output"],
isRepeatable: true,
args: {
name: "output",
isOptional: true,
suggestions: [
"text",
"json",
],
},
},
{
name: "--force-tls-gateway",
description: "Specifies whether the client will attempt to enforce tls connection to the desired gateway",
},
{
name: "--latency-based-selection",
description: "Specifies whether the new gateway should be determined based by latency as opposed to being chosen uniformly",
exclusiveOn: [
"--gateway-id",
],
},
{
name: "--set-active",
description: "Specify whether this new gateway should be set as the active one",
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "switch-gateway",
description: "Change the currently active gateway. Note that you must have already registered with the new gateway!",
options: [
{
name: "--id",
description: "Id of client we want to list gateways for",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: "--gateway-id",
description: "Id of the gateway we want to switch to",
isRepeatable: true,
args: {
name: "gateway_id",
},
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "show-ticketbooks",
description: "Display information associated with the imported ticketbooks,",
options: [
{
name: "--id",
description: "Id of client that is going to display the ticketbook information",
isRepeatable: true,
args: {
name: "id",
},
},
{
name: ["-o", "--output"],
isRepeatable: true,
args: {
name: "output",
isOptional: true,
suggestions: [
"text",
"json",
],
},
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "build-info",
description: "Show build information of this binary",
options: [
{
name: ["-o", "--output"],
isRepeatable: true,
args: {
name: "output",
isOptional: true,
suggestions: [
"text",
"json",
],
},
},
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "completions",
description: "Generate shell completions",
options: [
{
name: ["-h", "--help"],
description: "Print help",
},
],
args: {
name: "shell",
suggestions: [
"bash",
"elvish",
"fish",
"power-shell",
"zsh",
],
},
},
{
name: "generate-fig-spec",
description: "Generate Fig specification",
options: [
{
name: ["-h", "--help"],
description: "Print help",
},
],
},
{
name: "help",
description: "Print this message or the help of the given subcommand(s)",
subcommands: [
{
name: "init",
description: "Initialise a Nym client. Do this first!",
},
{
name: "run",
description: "Run the Nym client with provided configuration client optionally overriding set parameters",
},
{
name: "import-credential",
description: "Import a pre-generated credential",
},
{
name: "list-gateways",
description: "List all registered with gateways",
},
{
name: "add-gateway",
description: "Add new gateway to this client",
},
{
name: "switch-gateway",
description: "Change the currently active gateway. Note that you must have already registered with the new gateway!",
},
{
name: "show-ticketbooks",
description: "Display information associated with the imported ticketbooks,",
},
{
name: "build-info",
description: "Show build information of this binary",
},
{
name: "completions",
description: "Generate shell completions",
},
{
name: "generate-fig-spec",
description: "Generate Fig specification",
},
{
name: "help",
description: "Print this message or the help of the given subcommand(s)",
},
],
},
],
options: [
{
name: ["-c", "--config-env-file"],
description: "Path pointing to an env file that configures the client",
isRepeatable: true,
args: {
name: "config_env_file",
isOptional: true,
template: "filepaths",
},
},
{
name: "--no-banner",
description: "Flag used for disabling the printed banner in tty",
},
{
name: ["-h", "--help"],
description: "Print help",
},
{
name: ["-V", "--version"],
description: "Print version",
},
],
};
export default completion;
```
@@ -1,4 +1,4 @@
# Setup & Run
# Setup & Run
## Viewing command help
@@ -8,12 +8,6 @@ You can check that your binaries are properly compiled with:
./nym-client --help
```
~~~admonish example collapsible=true title="Console output"
```
<!-- cmdrun ../../../../../target/release/nym-client --help -->
```
~~~
The two most important commands you will issue to the client are:
* `init` - initalise a new client instance.
@@ -35,15 +29,9 @@ Initialising a new client instance can be done with the following command:
./nym-client init --id example-client
```
~~~admonish example collapsible=true title="Console output"
```
<!-- cmdrun ../../../../../target/release/nym-client init --id example-client -->
```
~~~
The `--id` in the example above is a local identifier so that you can name your clients; it is **never** transmitted over the network.
There is an optional `--gateway` flag that you can use if you want to use a specific gateway. The supplied argument is the `Identity Key` of the gateway you wish to use, which can be found on the [mainnet Network Explorer](https://explorer.nymtech.net/network-components/gateways) or [Sandbox Testnet Explorer](https://sandbox-explorer.nymtech.net/network-components/gateways) depending on which network you are on.
There is an optional `--gateway` flag that you can use if you want to use a specific gateway. The supplied argument is the `Identity Key` of the gateway you wish to use, which can be found on the [mixnet explorer](https://explorer.nymtech.net/network-components/gateways). Alternatively, you could use [Harbourmaster](https://harbourmaster.nymtech.net/)
Not passing this argument will randomly select a gateway for your client.
@@ -3,14 +3,10 @@ The Nym native client exposes a websocket interface that your code connects to.
Once you have a websocket connection, interacting with the client involves piping messages down the socket and listening for incoming messages.
# Message Requests
There are a number of message types that you can send up the websocket as defined [here](https://github.com/nymtech/nym/blob/develop/clients/native/websocket-requests/src/requests.rs):
## Message Requests
There are a number of message types that you can send up the websocket as defined [here](https://github.com/nymtech/nym/blob/master/clients/native/websocket-requests/src/responses.rs#L48).
```rust,noplayground
{{#include ../../../../../clients/native/websocket-requests/src/requests.rs:55:97}}
```
## Getting your own address
### Getting your own address
When you start your app, it is best practice to ask the native client to tell you what your own address is (from the generated configuration files <!--add link -->. If you are running a service, you need to do this in order to know what address to give others. In a client-side piece of code you can also use this as a test to make sure your websocket connection is running smoothly. To do this, send:
```json
@@ -32,7 +28,7 @@ See [here](https://github.com/nymtech/nym/blob/93cc281abc2cc951023b51746fa6f2ead
> Note that all the pieces of native client example code begin with printing the selfAddress. Examples exist for Rust, Go, Javascript, and Python.
## Sending text
### Sending text
If you want to send text information through the mixnet, format a message like this one and poke it into the websocket:
```json
@@ -58,7 +54,7 @@ In some applications, e.g. where people are chatting with friends who they know,
**If that fits your security model, good. However, will probably be the case that you want to send anonymous replies using Single Use Reply Blocks (SURBs)**.
You can read more about SURBs [here](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs) but in short they are ways for the receiver of this message to anonymously reply to you - the sender - **without them having to know your client address**.
You can read more about SURBs [here](../../network/concepts/anonymous-replies) but in short they are ways for the receiver of this message to anonymously reply to you - the sender - **without them having to know your client address**.
Your client will send along a number of `replySurbs` to the recipient of the message. These are pre-addressed Sphinx packets that the recipient can write to the payload of (i.e. write response data to), but not view the final destination of. If the recipient is unable to fit the response data into the bucket of SURBs sent to it, it will use a SURB to request more SURBs be sent to it from your client.
@@ -75,7 +71,7 @@ See ['Replying to SURB Messages'](#replying-to-surb-messages) below for an examp
Deciding on the amount of SURBs to generate and send along with outgoing messages depends on the expected size of the reply. You might want to send a lot of SURBs in order to make sure you get your response as quickly as possible (but accept the minor additional latency when sending, as your client has to generate and encrypt the packets), or you might just send a few (e.g. 20) and then if your response requires more SURBs, send them along, accepting the additional latency in getting your response.
## Sending binary data
### Sending binary data
You can also send bytes instead of JSON. For that you have to send a binary websocket frame containing a binary encoded
Nym [`ClientRequest`](https://github.com/nymtech/nym/blob/develop/clients/native/websocket-requests/src/requests.rs#L25) containing the same information.
@@ -83,7 +79,7 @@ Nym [`ClientRequest`](https://github.com/nymtech/nym/blob/develop/clients/native
You can find examples of sending and receiving binary data in the [code examples](https://github.com/nymtech/nym/tree/master/clients/native/examples), and an example project from the Nym community [BTC-BC](https://github.com/sgeisler/btcbc-rs/): Bitcoin transaction transmission via Nym, a client and service provider written in Rust.
## Replying to SURB messages
### Replying to SURB messages
Each bucket of `replySURBs`, when received as part of an incoming message, has a unique session identifier, which **only identifies the bucket of pre-addressed packets**. This is necessary to make sure that your app is replying to the correct people with the information meant for them in a situation where multiple clients are sending requests to a single service.
Constructing a reply with SURBs looks something like this (where `senderTag` was parsed from the incoming message)
@@ -96,7 +92,7 @@ Constructing a reply with SURBs looks something like this (where `senderTag` was
}
```
## Error messages
### Error messages
Errors from the app's client, or from the gateway, will be sent down the websocket to your code in the following format:
```json
@@ -106,12 +102,18 @@ Errors from the app's client, or from the gateway, will be sent down the websock
}
```
## LaneQueueLength
This is currently only used in the [Socks Client](../socks5-client.md) to keep track of the number of Sphinx packets waiting to be sent to the mixnet via being slotted amongst cover traffic. As this value becomes larger, the client signals to the application it should slow down the speed with which it writes to the proxy. This is to stop situations arising whereby an app connected to the client appears as if it has sent (e.g.) a bunch of messages and is awaiting a reply, when they in fact have not been sent through the mixnet yet.
### LaneQueueLength
This is currently only used in the [Socks Client](../socks5) to keep track of the number of Sphinx packets waiting to be sent to the mixnet via being slotted amongst cover traffic. As this value becomes larger, the client signals to the application it should slow down the speed with which it writes to the proxy. This is to stop situations arising whereby an app connected to the client appears as if it has sent (e.g.) a bunch of messages and is awaiting a reply, when they in fact have not been sent through the mixnet yet.
# Message Responses
Responses to your messages are defined [here](https://github.com/nymtech/nym/blob/develop/clients/native/websocket-requests/src/responses.rs):
## Message Responses
Responses to your messages are defined [here](https://github.com/nymtech/nym/blob/master/clients/native/websocket-requests/src/responses.rs#L47):
```rust,noplayground
{{#include ../../../../../clients/native/websocket-requests/src/responses.rs:48:53}}
```rust
#[derive(Debug)]
pub enum ServerResponse {
Received(ReconstructedMessage),
SelfAddress(Box<Recipient>),
LaneQueueLength { lane: u64, queue_length: usize },
Error(error::Error),
}
```
@@ -2,5 +2,10 @@ module.exports = {
"required-architecture": "Required Architecture",
"messages": "Message Based Paradigm",
"message-queue": "Message Queue",
<<<<<<< HEAD:documentation/docs/pages/developers/concepts/_meta.js
"abstractions": "Connection Abstractions"
};
};
=======
"credentials": "Credentials"
}
>>>>>>> max/new-docs-framework:documentation/docs/pages/developers/concepts/_meta.json
@@ -1 +0,0 @@
stub
@@ -0,0 +1,15 @@
import { Callout } from 'nextra/components'
# Credentials
<Callout type="info" emoji="️">
Right now we are still working on the specifics of how credentials will work for developers; this page serves as a stub with what information we do currently have.
</Callout>
Once the [zk-nym](../../network/cryptography/zk-nym) credential system is turned on, all Nym clients will have to present a valid credential to their Gateway on connection.
We plan to supply developers with a credential faucet for their applications, and a pay-per-play backend for large existing applications that wish to integrate and supply their users' with credentials under the hood.
> Remember, due to the [rerandomisation](../../network/cryptography/zk-nym/rerandomise) properties of the zk-nym scheme, that an application supplies a user with a credential in no way affects any privacy properties: the user will always present unlinkable rerandomised credential data to whatever Gateway their app instance connects to!
@@ -1,2 +1,75 @@
# Message Queue
2) actually waiting on messages: `send()` **just puts the message in the queue of cover traffic** so dropping a client before its actually sent is something that is possible and should be avoided (see the troubleshooting example TODO LINK) for more on this.
Clients, once connected to the Mixnet, **are always sending traffic into the Mixnet**; as well as the packets that you as a developer are sending from your application logic, they send [cover traffic](../../network/concepts/cover-traffic) at a constant rate defined by a Poisson process. This is part of the network's mitigation of timing attacks.
There are two constant streams of sphinx packets leaving the client at the rate defined by the Poisson process.
- one that is solely cover traffic
- one that sends a mixture of cover and 'real' traffic
```mermaid
---
config:
theme: neo-dark
layout: elk
title: Cover Traffic Stream
---
sequenceDiagram
box Local Machine
participant App Logic
participant Nym Client
end
participant Entry Gateway
loop Cover Traffic Stream
Nym Client->>Nym Client: Delay
Nym Client->>Entry Gateway: Cover traffic
end
```
```mermaid
---
config:
theme: neo-dark
layout: elk
title: Mixed Stream
---
sequenceDiagram
box Local Machine
participant App Logic
participant Nym Client
end
participant Entry Gateway
loop Cover + Real Traffic Stream
Nym Client->>Nym Client: Check internal queue + delay
Nym Client->>Entry Gateway: Cover traffic
alt Packets with App Payload
App Logic-->>Nym Client: Send(bytes): add to internal queue
Nym Client->>Nym Client: Check internal queue: bytes to send
Nym Client->>Nym Client: Encrypt & packetise bytes
Nym Client->>Entry Gateway: Real Packets
Nym Client->>Nym Client: Check internal queue: bytes to send
Nym Client->>Nym Client: Encrypt & packetise bytes
Nym Client->>Entry Gateway: Real Packets
Nym Client->>Nym Client: Check internal queue: queue empty
end
Nym Client->>Nym Client: Delay
Nym Client->>Entry Gateway: Cover traffic
end
```
> Since Sphinx packets are indistinguishable to an external observer, the only difference between 'real' and cover traffic is whether the payload is empty or not. This can be only known to the eventual receiver of the packet.
## What does `send()` do then?
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](../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.
@@ -1,3 +1,30 @@
stub
# Message-based Paradigm
1) working on messages not streaming / bytes which can be a pain : check the use of the bytecodec logic in the tcpproxy for looking @ how we handle this there
For the moment, Mixnet clients work assuming they will be piped atomic messages looking something like this:
```
MixnetMessage {
Message: Message_Bytes,
To: Nym_Address,
Attached_SURBS: Number_Of_Surbs
}
```
That the client will then encrypt as Sphinx packets and send through the Mixnet.
Likewise, they assume that once they have received and decrypted a Sphinx packet, they will kick back a reconstructed message to the rest of your app logic that look something like:
```
ReconstructedMessage {
Message: Message_Bytes,
From: SURB_Sender_Tag
}
```
This is obviously quite different to e.g. simply being able to read/write from a stream returned from a function call to create a TCP connection, but there are several approaches that developers can take to dealing with this right now.
## Message Abstractions
- Rust/Go (and soon C++) developers can use the `TcpProxy` [stream abstraction](../rust/tcpproxy).
- Developers who are using Typescript/Javascript can also avoid having to deal directly with messages via using [MixFetch](../typescript/examples/mix-fetch).
- As can developers who are bundling and running the standalone [socks5 client](../clients/socks5) using some form of init script.
- There will be a seperate pair of binaries coming soon which other developers can use to run as a persistent secondary proxy process based on the [zcash gRPC demo](https://github.com/nymtech/nym-zcash-grpc-demo) codebase, built using the `TcpProxy` abstraction. These will simply expose a `localhost` socket port to pipe traffic to and from in the same way as you would a TCP connection.
@@ -1,6 +1,48 @@
- what do i need? clients on both sides
- take a traditional client / server app setup: we need to put the mixnet betwen them to get the privacy properties, and each of them need a client in order to connect and authenticate with the mixnet to send and receive messages: since a lot of the functionality happens client-side and the sphinx of it all
# Required Application Architecture
- what dont i need? to run your own infra
- you can basically use the mixnet as a black box
- maybe if you're expecting a load of traffic / dont want to rely on other people's gateways, you could run your own and then connect to them specifically (qu: can we configure the client to connect to a particular gateway?)
Due to the fact that there are a lot of components that make up the Nym network (the Mixnet, Blockchain, etc) there is often confusion / misunderstandings about what is required to run application traffic through the Mixnet and take advantage of its various privacy properties.
## What do I need?
Nym clients on 'both sides' of the Mixnet.
- traditional client / server application setups involve having a Nym client on the local 'client' machine, as well as on the 'server' backend your local app/process wants to remotely communicate with. We need to put the Mixnet betwen them to gain the privacy properties as we need our local app to pipe its traffic to its local Nym client and have this traffic encrypted and slotted into the message queue for sending, and our server code to have a Nym client listening out for incoming messages to decrypt, reconstruct, and pass upstream to the server process. The server-side Nym client can then [anonymously reply via SURBs](../../network/traffic/anonymous-replies) to the client-app.
- P2P app setups may differ only insofar as that they probably shouldn't rely on [ephemeral clients](../rust/mixnet/examples/simple) as they will likely need a persistent Nym address - otherwise the logic is the same as client/server apps.
> We haven't yet tried to integrate a fully P2P application using anonymous replies: reach out if you are trying / have ideas!
That's it - so long as you have a Nym client, you can communicate with other Nym clients through the Mixnet. The content of your message payloads is up to you, and you can approach funneling traffic through the Mixnet as a black box if you want!
```mermaid
---
config:
theme: neo-dark
layout: elk
---
flowchart TB
subgraph Local Machine[Local Machine]
A[Application Logic]
B[Nym Client]
end
A <-->|Bytes| B
B <-->|Sphinx Packets| Mixnet
Mixnet{Mixnet Nodes}
subgraph Remote Machine
C[Application Logic]
D[Nym Client]
end
C <-->|Bytes| D
D <-->|Sphinx Packets| Mixnet
```
## What don't I need (but is maybe nice to have)?
You **do not need to run any infrastructure to integrate Mixnet functionality**.
That said, if you are expecting a lot of traffic and perhaps don't want to rely on other people's Gateway infrastructure, you could run your own. However, this is something that is more in the 'nice to have'/'quality of service' category, and is not necessarily expected when starting to build on Nym. Furthermore, if our tokenomic incentives are working as they should, Gateway uptimes should be so good as to not require this regardless!
## What do I definitely not need?
- To run a Mix Node. Defining which Mix Nodes you want to run traffic through is, although [technically possible](../rust/mixnet/examples/custom-topology), **only to be used in testing or research scenarios**; limiting the potential paths of your packets to a subset of the overall Mixnet topology is effectively reducing your anonymity set, and potentially leaking this subset through e.g. having the calculation logic open sourced is even worse. The best performing Mix Nodes are selected to route traffic per epoch, and will be used by your Nym clients when routing packets.
- To run a Validator / NymAPI instance.
- `NYM` tokens: for the moment the Mixnet is free to use. Developers will have access to a Credential faucet once the [zk-nym](../../network/cryptography/zk-nym) scheme is enabled in mainnet.
@@ -9,31 +9,33 @@ Developers might want to either integrate a Mixnet client or just to interact wi
### Integrating Mixnet Functionality
There are several options available to developers wanting to embed a Nym client in their application code.
<Tabs items={['Typescript/Javascript', 'Rust/Go/C++', 'Other']}>
<Tabs items={['Rust/Go/C++', 'Typescript/Javascript','Other']}>
<Tabs.Tab >
<>
Typescript and Javascript developers have several options avaliable to them:
- [`mixfetch`]() TODO LINK is an almost-dropin replacement for the `fetch` library. The best way to integrate Nym's `mixFetch` into your application will be where external network calls and RPC happens, for example, something in the lines of `sendRawTransaction` if you have an ETH-compatible wallet or `JsonRpcClient` if you use CosmJS. Although you can simply search for any JS `fetch` calls in your code (using our tool below) that are easily replaceable with `mixFetch`, keep in mind that `fetch` is not the only way to make `JSONRPC` or `XHR` calls. We advise to approach the integration process in a semantic way, searching for a module that is the common denominator for external communication in the codebase. Usually these are API controllers, middlewares or repositories.
<GitHubRepoSearch />
Rust developers can rely on our Rust SDK to import Nym client functionality into their code. This can either be in the form of a standard message-based client, the `socks5` client, or the `TcpProxy` modules.
- Otherwise, a well-modularized JS/TS codebase should permit the integration of one of our other SDK components, which will allow more flexibility and control (or if your codebase is not using something that can be covered by `fetch` for networking). Read more about our different SDK components in the [TS SDK overview page](). TODO LINK
We aim to expose at least the majority of this functionality via FFI to Go and C/C++. This is detailed alongside the Rust SDK components in the [Rust SDK docs](./rust).
</>
</>
</Tabs.Tab>
<Tabs.Tab>
<>
Rust developers can rely on our Rust SDK to import Nym client functionality into their code. This can either be in the form of a standard message-based client, the `socks5` client, or the `TcpProxy` modules.
We aim to expose at least the majority of this functionality via FFI to Go and C/C++. This is detailed alongside the Rust SDK components in the [Rust SDK docs]() TODO LINK.
Typescript and Javascript developers have several options avaliable to them:
- [`mixfetch`](./typescript/examples/mix-fetch) is an almost-dropin replacement for the `fetch` library. The best way to integrate Nym's `mixFetch` into your application will be where external network calls and RPC happens, for example, something in the lines of `sendRawTransaction` if you have an ETH-compatible wallet or `JsonRpcClient` if you use CosmJS. Although you can simply search for any JS `fetch` calls in your code (using our tool below) that are easily replaceable with `mixFetch`, keep in mind that `fetch` is not the only way to make `JSONRPC` or `XHR` calls. We advise to approach the integration process in a semantic way, searching for a module that is the common denominator for external communication in the codebase. Usually these are API controllers, middlewares or repositories.
</ >
<GitHubRepoSearch />
- Otherwise, a well-modularized JS/TS codebase should permit the integration of one of our other SDK components, which will allow more flexibility and control (or if your codebase is not using something that can be covered by `fetch` for networking). Read more about our different SDK components in the [TS SDK overview page](./typescript/overview).
</ >
</Tabs.Tab>
<Tabs.Tab> If your app is not written in any of the supported languages, you might still be able to send traffic through a standalone socks5 client TODO LINK but will have to think about packaging and bundling the client binary with e.g. a `systemd` file for autostart to run the client as a daemon. If you want to discuss FFI options reach out to us via our public dev channel. TODO LINK </Tabs.Tab>
<Tabs.Tab> If your app is not written in any of the supported languages, you might still be able to send traffic through a standalone socks5 client TODO LINK but will have to think about packaging and bundling the client binary with e.g. a `systemd` file for autostart to run the client as a daemon. If you want to discuss FFI options reach out to us via our public dev channel. </Tabs.Tab>
</Tabs>
### Interacting with Nyx
If instead of relying on the Mixnet you wish to interact with the [Nyx]() TODO LINK chain, either as a payment processor or to get on-chain events, see [interacting with the chain]() TODO LINK.
If instead of relying on the Mixnet you wish to interact with the Nyx chain, either as a payment processor or to get on-chain events, see [interacting with the chain](./chain).
> Note that depending on your setup, you might already be able to combine interacting with the chain with using the Mixnet: check the options above for more.
+2 -2
View File
@@ -1,7 +1,7 @@
# Introduction
The Rust SDK allows developers building applications in Rust to import and interact with Nym clients as they would any other dependency, instead of running the client as a separate process on their machine. This makes both developing and running applications much easier, reducing complexity in the development process (not having to restart another client in a separate console window/tab) and being able to have a single binary for other people to use.
The Rust SDK allows developers building applications in Rust to import and interact with Nym clients as they would any other dependency, instead of running the client as a separate process on their machine.
Currently developers can use the Rust SDK to import either websocket client ([`nym-client`](../../clients/websocket-client.md)) or [`socks-client`](../../clients/socks5-client.md) functionality into their Rust code.
Check the [development status](./rust/development-status) page to see the various modules that make up the SDK, and the [FFI](./rust/ffi) page for Go/C++ developers.
### Generate Crate Docs
In order to generate the crate docs run `cargo doc --open` from `nym/sdk/rust/nym-sdk/`
@@ -1,10 +1,13 @@
<<<<<<< HEAD:documentation/docs/pages/developers/rust/_meta.js
module.exports = {
"development-status": "Development Status",
=======
{
>>>>>>> max/new-docs-framework:documentation/docs/pages/developers/rust/_meta.json
"importing": "Importing",
"examples": "Basic Examples",
"message-helpers": "Message Helpers",
"message-types": "Message Types",
"troubleshooting": "Troubleshooting",
"development-status": "Development Status",
"mixnet": "Mixnet Module",
"tcpproxy": "TcpProxy Module",
"ffi": "FFI",
"tutorials": "Tutorials (Coming Soon)"
};
@@ -1,14 +1,15 @@
# Development status
The SDK is still somewhat a work in progress: interfaces are fairly stable but still may change in subsequent releases.
In the future the SDK will be made up of several components, each of which will allow developers to interact with different parts of Nym infrastructure.
In the future the SDK will be made up of several modules, each of which will allow developers to interact with different parts of Nym infrastructure.
| Component | Functionality | Released |
| Module | Functionality | Released |
|-----------|---------------------------------------------------------------------------------------|----------|
| Mixnet | Create / load clients & keypairs, subscribe to Mixnet events, send & receive messages | ✔️ |
| Ecash | Create & verify Ecash credentials | 🛠 |
| TcpProxy | Utilise the TcpProxyClient and TcpProxyServer abstractions for streaming | |
| Ecash | Create & verify Ecash credentials | ❌ |
| Validator | Sign & broadcast Nyx blockchain transactions, query the blockchain | ❌ |
The `mixnet` component currently exposes the logic of two clients: the [websocket client]() TODO LINK, and the [socks]() TODO client.
The `Mixnet` module currently exposes the logic of two clients: the [websocket client](../clients/websocket), and the [socks client](../clients/socks5).
The `ecash` component is currently being worked on. Right now it exposes logic allowing for the creation of Ecash credentials on the Sandbox testnet.
The `TcpProxy` module exposes functionality to set up client/server instances that expose a localhost TcpSocket to read/write to.
@@ -3,49 +3,58 @@ import { Callout } from 'nextra/components'
# FFI Bindings
<Callout type="info" emoji="️">
We are only working on the intitial versions of the FFI code to allow developers to experiment and get feedback. Please get in touch if you think the FFI bindings are lacking certain functionality.
We are working on the intitial versions of the FFI code to allow developers to experiment and get feedback. Please get in touch if you think the FFI bindings are lacking certain functionality.
</Callout>
We currently have FFI bindings for Go and C/C++. See the table below to check the coverage of functionality we expect devs would like to see.
The [`nym/sdk/ffi`](https://github.com/nymtech/nym/tree/master/sdk/ffi) directory has the following structure:
```
ffi
├── cpp
├── go
├── README.md
└── shared
```
The main functionality of exposed functions will be imported from `sdk/ffi/shared` into `sdk/ffi/<LANGUAGE>` in order to cut down on code duplication, and so that the imported bindings can be language-specific with regards to types and any `unsafe` code that is required, as well as allowing for the use of language-specific FFI libraries in the future (e.g. we are using `uniffi-bindgen-go` for Go, and at the moment have custom C/C++ bindings, which we might in the future replace with `cxx`).
Furthermore, the `shared/` code makes sure that client access is thread-safe, and that client actions happen in blocking threads on the Rust side of the FFI boundary.
### Mixnet Module
This is the basic mixnet component of the SDK, exposing client functionality with which people can build custom interfaces with the Mixnet.
This is the basic mixnet component of the SDK, exposing client functionality with which people can build custom interfaces with the Mixnet. These functions are exposed to both Go and C/C++ via the `sdk/ffi/shared/` crate.
| Rust Function | Go | C/C++ |
| :----------------------------------------------- | :--: | ----: |
| `MixnetClient::connect_new()` | ✔️ | ✔️ |
| `MixnetClientBuilder::new_with_default_storage` | ✔️ | ✔️ |
| `MixnetClientBuilder::OTHERS` | | |
| `MixnetClientBuilder::OTHERS` | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| `shared/lib.rs` function | Rust Function |
| ------------------------------------------------------------- | ----------------------------------------------------------------------- |
| `init_ephemeral_internal()` | `MixnetClient::connect_new()` |
| `init_default_storage_internal(config_dir: PathBuf)` | `MixnetClientBuilder::new_with_default_storage(config_dir)` |
| `get_self_address_internal()` | `MixnetClient.nym_address()` |
| `send_message_internal(recipient: Recipient, message: &str)` | `MixnetClient.send_plain_message(recipient, message)` |
| `reply_internal(recipient: AnonymousSenderTag, message: &str)`| `MixnetClient.send_reply(recipient, message)` |
> We have also implemented `listen_for_incoming()` which is a wrapper around the Mixnet client's `wait_for_messages()` which is exposed to Go and C/C++. This is a helper method for listening out for and handling incoming messages.
> We have also implemented `listen_for_incoming_internal()` which is a wrapper around the Mixnet client's `wait_for_messages()`. This is a helper method for listening out for and handling incoming messages.
#### Currently Unsupported Functionality
At the time of writing the following functionality is not exposed to the shared FFI library:
- `split_sender()`: the ability to [split a client into sender and receiver](./mixnet/examples/split-send) for concurrent send/receive.
- The use of [custom network topologies](./mixnet/examples/custom-topology).
- `Socks5::new()`: creation and use of the [socks5/4a/4 proxy client](./mixnet/examples/socks).
### TcpProxy Module
A connection abstraction TODO LINK which exposes a local TCP socket which developers are able to interact with basically as expected, being able to read/write to/from a bytestream, without really having to take into account the workings of the Mixnet/Sphinx/the message-based TODO LINK format of the underlying client.
A connection abstraction which exposes a local TCP socket which developers are able to interact with basically as expected, being able to read/write to/from a bytestream, without really having to take into account the workings of the Mixnet/Sphinx/the [message-based](../concepts/messages) format of the underlying client.
| Rust Function | Go | C/C++ |
| :----------------- | :--: | ----: |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
<Callout type="info" emoji="️">
At the time of writing this functionality is **only** exposed to Go. C/C++ bindings will follow in the future in a larger update to the C FFI.
</Callout>
----------------
for copypaste
❌ ✔️
----------------
| `shared/lib.rs` function | Rust Function |
| --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `proxy_client_new_internal(server_address: Recipient, listen_address: &str, listen_port: &str, close_timeout: u64, env: Option<String>)`| `NymProxyClient::new(server_address, listen_address, listen_port, close_timeout, env)`|
| `proxy_client_new_defaults_internal(server_address, env)` | `NymProxyClient::new_with_defaults(server_address, env)` |
| `proxy_client_run_internal()` | `NymProxyClient.run()` |
| `proxy_server_new_internal(upstream_address: &str, config_dir: &str, env: Option<String>)` | `NymProxyServer::new(upstream_address, config_dir, env)` |
| `proxy_server_run_internal()` | `NymProxyServer.run_with_shutdown()` |
| `proxy_server_address_internal()` | `NymProxyServer.nym_address()` |
@@ -1,11 +1,5 @@
# Installation
The `nym-sdk` crate is **not yet available via [crates.io](https://crates.io)**. As such, in order to import the crate you must specify the Nym monorepo in your `Cargo.toml` file:
```toml
nym-sdk = { git = "https://github.com/nymtech/nym" }
```
By default the above command will import the current `HEAD` of the default branch, which in our case is `develop`. Assuming instead you wish to pull in another branch (e.g. `master` or a particular release) you can specify this like so:
The `nym-sdk` crate is **not yet available via [crates.io](https://crates.io)**. As such, in order to import the crate you must specify the Nym monorepo in your `Cargo.toml` file. Since the `HEAD` of `master` is always the most recent release, we recommend developers use that for their imports, unless they have a reason to pull in a specific historic version of the code.
```toml
# importing HEAD of master branch
@@ -14,10 +8,4 @@ nym-sdk = { git = "https://github.com/nymtech/nym", branch = "master" }
nym-sdk = { git = "https://github.com/nymtech/nym", branch = "release/2023.3-kinder" }
```
You can also define a particular git commit to use as your import like so:
```toml
nym-sdk = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" }
```
Since the `HEAD` of `master` is always the most recent release, we recommend developers use that for their imports, unless they have a reason to pull in a specific historic version of the code.
Work will occur in the future to break the monorepo down into importable features, in order to reduce the number of dependencies imported by developers.
@@ -1,5 +0,0 @@
# Message Types
[//]: # (TODO expand! )
There are two methods for sending messages through the mixnet using your client:
* `send_plain_message()` is the most simple: pass the recipient address and the message you wish to send as a string (this was previously `send_str()`). This is a nicer-to-use wrapper around `send_message()`.
* `send_message()` allows you to also define the amount of SURBs to send along with your message (which is sent as bytes).
@@ -0,0 +1,5 @@
# Mixnet Module
This module exposes the logic of creating and interacting with clients and Mixnet messages. This is recommended for those wanting to either start playing around with the Mixnet and how it works, or build connection logic.
> For developers wanting something more 'plug and play' we recommend the [`TcpProxy` module](./tcpproxy).
@@ -0,0 +1,6 @@
{
"examples": "Basic Examples",
"message-helpers": "Message Helpers",
"message-types": "Message Types",
"troubleshooting": "Troubleshooting"
}
@@ -1,6 +1,7 @@
module.exports = {
"simple": "Simple Send",
"builders": "Builder Patterns",
"testnet": "Configurable Network",
"custom-topology": "Custom Network Topologies",
"split-send": "Concurrent Send & Receive",
"socks": "Socks Proxy",
@@ -0,0 +1,10 @@
module.exports = {
"simple": "Simple Send",
"builders": "Builder Patterns",
"testnet": "Configurable Network",
"custom-topology": "Custom Network Topologies",
"split-send": "Concurrent Send & Receive",
"socks": "Socks Proxy",
"storage": "Manually Handle Storage",
"surbs": "Anonymous Replies"
};
@@ -0,0 +1,4 @@
module.exports = {
"builder": "Ephemeral",
"builder-with-storage": "With Storage"
};
@@ -1,6 +1,12 @@
# Importing and using a custom network topology
If you want to send traffic through a sub-set of nodes (for instance, ones you control, or a small test setup) when developing, debugging, or performing research, you will need to import these nodes as a custom network topology, instead of grabbing it from the [`Mainnet Nym-API`](https://validator.nymtech.net/api/swagger/index.html).
import { Callout } from 'nextra/components'
<Callout type="warning" emoji="⚠️">
These examples are **not** the same as using a configurable network: these functions define a subset of nodes to use on a given network, whereas the [testnet](./testnet) example is an example of switching to use a different network entirely. The two can be combined, but if you are looking for how to connect your client to a testnet, see the `testnet` file.
</Callout>
If you want to send traffic through a sub-set of nodes (for instance, ones you control, or a small test setup) when developing, debugging, or performing research, you will need to import these nodes as a custom network topology, instead of grabbing it from the [`Mainnet Nym-API`](https://validator.nymtech.net/api/swagger/index.html).
There are two ways to do this:
@@ -0,0 +1,4 @@
module.exports = {
"custom-provider": "Custom Topology Provider",
"manual-topology": "Manually Overwrite Topology"
};
@@ -1,7 +1,7 @@
# Anonymous Replies with SURBs (Single Use Reply Blocks)
Both functions used to send messages through the mixnet (`send_message` and `send_plain_message`) send a pre-determined number of SURBs along with their messages by default.
You can read more about how SURBs function under the hood [here](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs). **TODO change link**
You can read more about how SURBs function under the hood [here](../../../../network/traffic/anonymous-replies).
In order to reply to an incoming message using SURBs, you can construct a `recipient` from the `sender_tag` sent along with the message you wish to reply to.
@@ -0,0 +1,44 @@
# Configurable Network
If you want to connect your Mixnet client to a different network than Mainnet, simply pull in a file from [`nym/envs`](https://github.com/nymtech/nym/tree/master/envs) as such:
```rust
use futures::StreamExt;
use nym_network_defaults::setup_env;
use nym_sdk::mixnet;
use nym_sdk::mixnet::MixnetMessageSender;
// An example of creating a client relying on a testnet, in this case Sandbox.
#[tokio::main]
async fn main() -> anyhow::Result<()> {
nym_bin_common::logging::setup_logging();
// relative root is `sdk/rust/nym-sdk/` for fallback file path
let env_path =
std::env::var("NYM_ENV_PATH").unwrap_or_else(|_| "../../../envs/sandbox.env".to_string());
setup_env(Some(&env_path));
let sandbox_network = mixnet::NymNetworkDetails::new_from_env();
let mixnet_client = mixnet::MixnetClientBuilder::new_ephemeral()
.network_details(sandbox_network)
.build()?;
let mut client = mixnet_client.connect_to_mixnet().await?;
let our_address = client.nym_address();
// Send a message throughout the mixnet to ourselves
client
.send_plain_message(*our_address, "hello there")
.await?;
println!("Waiting for message");
if let Some(received) = client.next().await {
println!("Received: {}", String::from_utf8_lossy(&received.message));
} else {
eprintln!("Failed to receive message.");
}
client.disconnect().await;
Ok(())
}
```
@@ -1,10 +1,10 @@
# Message Helpers
## Handling incoming messages
As seen in the [Chain querier tutorial](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/) when listening out for a response to a sent message (e.g. if you have sent a request to a service, and are awaiting the response) you will want to await [non-empty messages (if you don't know why, read the info on this here)](troubleshooting.md#client-receives-empty-messages-when-listening-for-response). This can be done with something like the helper functions [here](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/src/lib.rs#L71):
When listening out for a response to a sent message (e.g. if you have sent a request to a service, and are awaiting the response) you will want to await [non-empty messages (if you don't know why, read the info on this here)](./troubleshooting#client-receives-empty-messages-when-listening-for-response). This can be done with something like the helper functions here:
```rust
use nym_sdk::mixnet::ReconstructedMessage;
use nym_sdk::mixnet::ReconstructedMessage;
pub async fn wait_for_non_empty_message(
client: &mut MixnetClient,
@@ -14,7 +14,7 @@ pub async fn wait_for_non_empty_message(
return Ok(new_message.pop().unwrap());
}
}
bail!("did not receive any non-empty message")
}
@@ -23,9 +23,9 @@ pub fn handle_response(message: ReconstructedMessage) -> anyhow::Result<Response
}
// Note here that the only difference between handling a request and a response
// is that a request will have a sender_tag to parse.
//
// This is used for anonymous replies with SURBs.
// is that a request will have a sender_tag to parse.
//
// This is used for anonymous replies with SURBs.
pub fn handle_request(
message: ReconstructedMessage,
) -> anyhow::Result<(RequestTypes, Option<AnonymousSenderTag>)> {
@@ -34,21 +34,19 @@ pub fn handle_request(
}
```
The above helper functions are used as such by the client in tutorial example: it sends a message to the service (what the message is isn't important - just that your client has sent a message _somewhere_ and you are awaiting a response), waits for a _non_empty_ message, then handles it (then logs it - but you can do whatever you want, parse it, etc):
The above helper functions are used as such by the client in tutorial example: it sends a message to the service (what the message is isn't important - just that your client has sent a message _somewhere_ and you are awaiting a response), waits for a _non_empty_ message, then handles it (then logs it - but you can do whatever you want, parse it, etc):
```rust
// [snip]
// Send serialised request to service via mixnet what is await-ed here is
// Send serialised request to service via mixnet what is await-ed here is
// placing the message in the client's message queue, NOT the sending itself.
let _ = client
.send_message(sp_address, message.serialize(), Default::default())
.await;
// Await a non-empty message
// Await a non-empty message
let received = wait_for_non_empty_message(client).await?;
// Handle the response received (the non-empty message awaited above)
// Handle the response received (the non-empty message awaited above)
let sp_response = handle_response(received)?;
// Match JSON -> ResponseType
@@ -58,13 +56,10 @@ let res = match sp_response {
response.balance
}
};
// [snip]
```
([repo code on Github here](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/src/client.rs#L19))
## Iterating over incoming messages
It is recommended to use `nym_client.next().await` over `nym_client.wait_for_messages().await` as the latter will return one message at a time which will probably be easier to deal with. See the [parallel send and receive example](https://github.com/nymtech/nym/blob/2993e85c7a17bd5b68171751a48b731b2394ee03/sdk/rust/nym-sdk/examples/parallel_sending_and_receiving.rs#L23-L25) for an example.
It is recommended to use `nym_client.next().await` over `nym_client.wait_for_messages().await` as the latter will return one message at a time which will probably be easier to deal with. See the [parallel send and receive example](./examples/split-send) for an example.
## Remember to disconnect your client
You should always **manually disconnect your client** with `client.disconnect().await` as seen in the code examples. This is important as your client is writing to a local DB and dealing with SURB storage.
You should always **manually disconnect your client** with `client.disconnect().await` as seen in the code examples. This is important as your client is writing to a local DB and dealing with SURB storage, so needs to gracefully shutdown.
@@ -0,0 +1,20 @@
# Message Types
There are several functions used to send outgoing messages through the Mixnet, each with a different level of customisation:
- `send(&self, message: InputMessage) -> Result<()>`
Sends a `InputMessage` to the mixnet. This is the most low-level sending function, for full customization. Called by `send_message()`.
- `send_message<M>(&self, address: Recipient, message: M, surbs: IncludedSurbs) -> Result<()>`
Sends bytes to the supplied Nym address. There is the option to specify the number of reply-SURBs to include. Called by `send_plain_message()`.
- `send_plain_message<M>(&self, address: Recipient, message: M) -> Result<()>`
Sends data to the supplied Nym address with the default surb behaviour.
> Note we specify *outgoing* messages above: this is because the SDK assumes that replies will be anonymous via [SURBs](../../../network/traffic/anonymous-replies).
Replies rely on the creation of an `AnonymousSenderTag` by parsing and storing the `sender_tag` from incoming messages, and using this to reply, instead of the `Receipient` type used by the functions outlined above:
`send_reply<M>(&self, recipient_tag: AnonymousSenderTag, message: M) -> Result<()>` will send the reply message to the supplied anonymous recipient.
> You can find all of the function definitions [here](https://github.com/nymtech/nym/blob/master/sdk/rust/nym-sdk/src/mixnet/traits.rs).
@@ -1,40 +1,39 @@
# Troubleshooting
Below are several common issues or questions you may have.
Below are several common issues or questions you may have.
If you come across something that isn't explained here, [PRs are welcome](https://github.com/nymtech/nym/issues/new/choose).
If you come across something that isn't explained here, [PRs are welcome](https://github.com/nymtech/nym/issues/new/choose).
## Verbose `task client is being dropped` logging
### On client shutdown (expected)
If this is happening at the end of your code when disconnecting your client, this is fine; we just have a verbose client! When calling `client.disconnect().await` this is simply informing you that the client is shutting down.
If this is happening at the end of your code when disconnecting your client, this is fine; we just have a verbose client! When calling `client.disconnect().await` this is simply informing you that the client is shutting down.
On client shutdown / disconnect this is to be expected - this can be seen in many of the code examples as well. We use the [`nym_bin_common::logging`](https://github.com/nymtech/nym/blob/develop/common/bin-common/src/logging/mod.rs) import to set logging in our example code. This defaults to `INFO` level.
On client shutdown / disconnect this is to be expected - this can be seen in many of the code examples as well. We use the [`nym_bin_common::logging`](https://github.com/nymtech/nym/blob/master/common/bin-common/src/logging/mod.rs) import to set logging in our example code. This defaults to `INFO` level.
If you wish to quickly lower the verbosity of your client process logs when developing you can prepend your command with `RUST_LOG=<LOGGING_LEVEL>`.
If you wish to quickly lower the verbosity of your client process logs when developing you can prepend your command with `RUST_LOG=<LOGGING_LEVEL>`.
If you want to run the `builder.rs` example with only `WARN` level logging and below:
```sh
cargo run --example builder
cargo run --example builder
```
Becomes:
```sh
RUST_LOG=warn cargo run --example builder
```sh
RUST_LOG=warn cargo run --example builder
```
You can also make the logging _more_ verbose with:
You can also make the logging _more_ verbose with:
```sh
RUST_LOG=debug cargo run --example builder
```
### Not on client shutdown (unexpected)
If this is happening unexpectedly then you might be shutting your client process down too early. See the [accidentally killing your client process](#accidentally-killing-your-client-process-too-early) below for possible explanations and how to fix this issue.
### Not on client shutdown (unexpected)
If this is happening unexpectedly then you might be shutting your client process down too early. See the [accidentally killing your client process](#accidentally-killing-your-client-process-too-early) below for possible explanations and how to fix this issue.
[//]: # (TODO note on poisson dance and not immediately killing client process)
## Accidentally killing your client process too early
If you are seeing either of the following errors when trying to run a client, specifically sending a message, then you may be accidentally killing your client process.
If you are seeing either of the following errors when trying to run a client, specifically sending a message, then you may be accidentally killing your client process.
```sh
2023-11-02T10:31:03.930Z INFO TaskClient-BaseNymClient-real_traffic_controller-ack_control-action_controller > the task client is getting dropped
@@ -59,7 +58,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
2023-11-02T11:22:08.477Z ERROR TaskClient-BaseNymClient-real_traffic_controller-ack_control-input_message_listener > Assuming this means we should shutdown...
```
Using the following piece of code as an example:
Using the following piece of code as an example:
```rust
use nym_sdk::mixnet::{MixnetClient, MixnetMessageSender, Recipient};
@@ -87,29 +86,29 @@ async fn main() {
}
```
This is a simplified snippet of code for sending a simple hardcoded message with the following command:
This is a simplified snippet of code for sending a simple hardcoded message with the following command:
```sh
cargo run client <RECIPIENT_NYM_ADDRESS>
```
You might assume that `send`-ing your message would _just work_ as `nym_client.send_plain_message()` is an async function; you might expect that the client will block until the message is actually sent into the mixnet, then shutdown.
You might assume that `send`-ing your message would _just work_ as `nym_client.send_plain_message()` is an async function; you might expect that the client will block until the message is actually sent into the mixnet, then shutdown.
However, this is not true.
However, this is not true.
**This will only block until the message is put into client's internal queue**. Therefore in the above example, the client is being shut down before the message is _actually sent to the mixnet_; after being placed in the client's internal queue, there is still work to be done under the hood, such as route encrypting the message and placing it amongst the stream of cover traffic.
**This will only block until the message is put into client's internal queue**. Therefore in the above example, the client is being shut down before the message is _actually sent to the mixnet_; after being placed in the client's internal queue, there is still work to be done under the hood, such as route encrypting the message and placing it amongst the stream of cover traffic.
The simple solution? Make sure the program/client stays active, either by calling `sleep`, or listening out for new messages. As sending a one-shot message without listening out for a response is likely not what you'll be doing, then you will be then awaiting a response (see the [message helpers page](message-helpers.md) for an example of this).
The simple solution? Make sure the program/client stays active, either by calling `sleep`, or listening out for new messages. As sending a one-shot message without listening out for a response is likely not what you'll be doing, then you will be then awaiting a response (see the [message helpers page](./message-helpers.md) for an example of this).
Furthermore, you should always **manually disconnect your client** with `client.disconnect().await` as seen in the code examples. This is important as your client is writing to a local DB and dealing with SURB storage.
Furthermore, you should always **manually disconnect your client** with `client.disconnect().await` as seen in the code examples. This is important as your client is writing to a local DB and dealing with SURB storage.
## Client receives empty messages when listening for response
If you are sending out a message, it makes sense for your client to then listen out for incoming messages; this would probably be the reply you get from the service you've sent a message to.
If you are sending out a message, it makes sense for your client to then listen out for incoming messages; this would probably be the reply you get from the service you've sent a message to.
You might however be receiving messages without data attached to them / empty payloads. This is most likely because your client is receiving a message containing a [SURB request](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs) - a SURB requesting more SURB packets to be sent to the service, in order for them to have enough packets (with a big enough overall payload) to split the entire response to your initial request across.
You might however be receiving messages without data attached to them / empty payloads. This is most likely because your client is receiving a message containing a [SURB request](../../../network/traffic/anonymous-replies) - a SURB requesting more SURB packets to be sent to the service, in order for them to have enough packets (with a big enough overall payload) to split the entire response to your initial request across.
Whether the `data` of a SURB request being empty is a feature or a bug is to be decided - there is some discussion surrounding whether we can use SURB requests to send additional data to streamline the process of sending large replies across the mixnet.
Whether the `data` of a SURB request being empty is a feature or a bug is to be decided - there is some discussion surrounding whether we can use SURB requests to send additional data to streamline the process of sending large replies across the mixnet.
You can find a few helper functions [here](message-helpers.md) to help deal with this issue in the meantime.
You can find a few helper functions [here](./message-helpers.md) to help deal with this issue in the meantime.
> If you can think of a more succinct or different way of handling this do reach out - we're happy to hear other opinions
> If you can think of a more succinct or different way of handling this do reach out - we're happy to hear other opinions
@@ -0,0 +1,5 @@
# TcpProxy Module
This module exposes the `TcpProxyClient` and the `TcpProxyServer` which can be used to proxy traffic through the Mixnet in a way that is more familiar to developers than the methods exposed by the [`Mixnet` module](./mixnet).
Both `Client` and `Server` are intended to be initialised and then run in a background thread, exposing a configurable `localhost` socket which developers can read/write/stream to without having to worry about the [message-based](../concepts/messages) nature of sending and receiving traffic to/from the Mixnet.
@@ -0,0 +1,4 @@
{
"architecture": "Architecture",
"examples": "Examples"
}
@@ -0,0 +1,208 @@
import { Callout } from 'nextra/components'
# Architecture
## Motivations
The motivation behind the creation of the `TcpProxy` module is to allow developers to interact with the Mixnet in a way that is far more familiar to them: simply setting up a connection with a transport, being returned a socket, and then being able to stream data to/from it, similar to something like the Tor [`arti`](https://gitlab.torproject.org/tpo/core/arti/-/tree/main/crates/arti-client) client.
<Callout type="info" emoji="️">
This is an initial version of the module which we are releasing to developers to experiment with. If you run into problems or any functionality that is missing, do reach out on Matrix and let us know.
Furthermore we will be working on optimisations to the module over time - most of this will occur under the hood (e.g. implementing a configurable connection pool for the `ProxyClient`), but all updates will occur according to SemVer, so don't worry about breaking changes!
</Callout>
## Clients
Each of the sub-modules exposed by the `TcpProxy` deal with Nym clients in a different way.
- the `NymProxyClient` creates an ephemeral client per new TCP connection, which is closed according to the configurable timeout: we map one ephemeral client per TCP connection. This is to deal with multiple simultaneous streams. In the future, this will be superceded by a connection pool in order to speed up new connections.
- the `NymProxyServer` has a single Nym client with a persistent identity.
## Framing
We are currently relying on the [`tokio::Bytecodec`](https://docs.rs/tokio-util/latest/tokio_util/codec/struct.BytesCodec.html) and [`framedRead`](https://docs.rs/tokio-util/latest/tokio_util/codec/struct.Framed.html) to frame bytes moving through the `NymProxyClient` and `NymProxyServer`.
> For those interested, under the hood the client uses our own [`NymCodec`](https://github.com/nymtech/nym/blob/27ac34522cf0f8bfe1ca265e0b57ee52f2ded0d2/common/nymsphinx/framing/src/codec.rs) to frame message bytes as Sphinx packet payloads.
## Sessions & Message Ordering
We have implemented session management and message ordering, where messages are wrapped in a session ID per connection, with individual messages being given an incrememting message ID. Once all the messages have been sent, the `NymProxyClient` then sends a `Close` message as the last outgoing message. This is to notify the `NymProxyServer` that there are no more outbound messages for this session, and that it can trigger the session timeout.
> Session management and message IDs are necessary since *the Mixnet guarantees message delivery but not message ordering*: in the case of trying to e.g. send gRPC protobuf through the Mixnet, ordering is required so that a buffer is not split across Sphinx packet payloads, and that the 2nd half of the frame is not passed upstream to the gRPC parser before the 1st half, even if it is received first.
Lets step through a full request/response path between a client process communicating with a remote host via the proxies:
### Outgoing Client Request
The `NymProxyClient` instance, once initialised and running, listens out for incoming TCP connections on its localhost port.
On receiving one, it will create a new session ID and packetise the incoming bytes into messages of the following structure:
```rust
pub struct ProxiedMessage {
message: Payload,
session_id: Uuid,
message_id: u16,
}
```
> This code can be found [here](https://github.com/nymtech/nym/blob/develop/sdk/rust/nym-sdk/src/tcp_proxy/utils.rs#L147C1-L152C2)
And then send these to the Nym address of the `NymProxyServer` instance. Not much to see here regarding message ordering, as the potential for reordering only starts once packets are travelling through the Mixnet.
```mermaid
---
config:
theme: neo-dark
layout: elk
---
sequenceDiagram
box Local Machine
participant Client Process
participant NymProxyClient
end
Client Process->>NymProxyClient: Request bytes
NymProxyClient->>NymProxyClient: New session
NymProxyClient->>EntryGateway: Sphinx Packets: Message 1
EntryGateway-->>NymProxyClient: Acks
NymProxyClient->>EntryGateway: Sphinx Packets: Message 2
EntryGateway-->>NymProxyClient: Acks
NymProxyClient->>EntryGateway: Sphinx Packets: Message 3
EntryGateway-->>NymProxyClient: Acks
NymProxyClient->>EntryGateway: Sphinx Packets: Close Message
NymProxyClient->>NymProxyClient: Start Client Close timeout
EntryGateway-->>NymProxyClient: Acks
```
### Server Receives Request & Responds
Here is a diagrammatic representation of a situation in which the request arrives out of order, and how the message buffer deals with this so as not to pass a malformed request upstream to the process running on the same remote host:
```mermaid
---
config:
theme: neo-dark
layout: elk
---
sequenceDiagram
Exit Gateway->>NymProxyServer: Sphinx Packets: Message 2
NymProxyServer-->>Exit Gateway: Acks
Exit Gateway->>NymProxyServer: Sphinx Packets: Message 3
NymProxyServer-->>Exit Gateway: Acks
loop Message Buffer
NymProxyServer->>NymProxyServer: Wait for Message 1
Exit Gateway->>NymProxyServer: Sphinx Packets: Message 1
NymProxyServer-->>Exit Gateway: Acks
NymProxyServer->>NymProxyServer: Message Received: trigger upstream send
end
Note right of NymProxyServer: Note this happens **per session**
NymProxyServer->>Upstream Process: Reconstructed request bytes
Upstream Process->>Upstream Process: Do something with request
Exit Gateway->>NymProxyServer: Sphinx Packets: Message Close
NymProxyServer-->>Exit Gateway: Acks
NymProxyServer->>NymProxyServer: Trigger Client timeout start for session
Upstream Process->>NymProxyServer: Response bytes
NymProxyServer->>NymProxyServer: Write to provided SURB payloads
NymProxyServer->>Exit Gateway: Anonymous replies
box Remote Host
participant NymProxyServer
participant Upstream Process
end
```
> Note that this is per-session, with a session mapped to a single TCP connection. Both the `NymProxyClient` and `Server` are able to handle multiple concurrent connections.
### Client Receives Response
The `ProxyClient` deals with incoming traffic in the same way as the `ProxyServer`, with a per-session message queue:
```mermaid
---
config:
theme: neo-dark
layout: elk
---
sequenceDiagram
box Local Machine
participant Client Process
participant NymProxyClient
end
Entry Gateway--xNymProxyClient: Sphinx Packets: Reply Message 1 dropped: No Ack!
Entry Gateway->>NymProxyClient: Sphinx Packets: Reply Message 2
NymProxyClient-->Entry Gateway: Ack
Entry Gateway->>NymProxyClient: Sphinx Packets: Reply Message 3
NymProxyClient-->Entry Gateway: Ack
Loop Message Buffer:
NymProxyClient->>NymProxyClient: Wait for Message 1
Entry Gateway->>NymProxyClient: Sphinx Packets: Message 1
NymProxyClient-->>Entry Gateway: Acks
NymProxyClient->>NymProxyClient: Message Received: trigger send
NymProxyClient->>Client Process: Response bytes
end
Note right of NymProxyClient: Note this happens **per session**
```
After receiving the packets, it can then forward the recoded bytes to the requesting process.
### Full Flow Diagram
```mermaid
---
config:
theme: neo-dark
layout: elk
---
sequenceDiagram
box Local Machine
participant Client Process
participant NymProxyClient
end
Client Process->>NymProxyClient: Request bytes
NymProxyClient->>NymProxyClient: New session
NymProxyClient->>Entry Gateway: Sphinx Packets: Message 1
Entry Gateway-->>NymProxyClient: Acks
NymProxyClient->>Entry Gateway: Sphinx Packets: Message 2
Entry Gateway-->>NymProxyClient: Acks
NymProxyClient->>Entry Gateway: Sphinx Packets: Message 3
Entry Gateway-->>NymProxyClient: Acks
NymProxyClient->>Entry Gateway: Sphinx Packets: Close Message
Entry Gateway-->>NymProxyClient: Acks
Entry Gateway-->>Mix Nodes: All Packets, Acks, etc
Note right of Mix Nodes: We are omitting the 3 hops etc for brevity here
Mix Nodes-->> Exit Gateway: All Packets, Acks, etc
Exit Gateway->>NymProxyServer: Sphinx Packets: Message 2
NymProxyServer-->>Exit Gateway: Acks
Exit Gateway->>NymProxyServer: Sphinx Packets: Message 3
NymProxyServer-->>Exit Gateway: Acks
loop Message Buffer
NymProxyServer->>NymProxyServer: Wait for Message 1
Exit Gateway->>NymProxyServer: Sphinx Packets: Message 1
NymProxyServer-->>Exit Gateway: Acks
NymProxyServer->>NymProxyServer: Message Received: trigger upstream send
end
Note right of NymProxyServer: Note this happens **per session**
NymProxyServer->>Upstream Process: Reconstructed request bytes
Upstream Process->>Upstream Process: Do something with request
Exit Gateway->>NymProxyServer: Sphinx Packets: Close Message
NymProxyServer-->>Exit Gateway: Acks
NymProxyServer->>NymProxyServer: Trigger Client timeout start for session
Upstream Process->>NymProxyServer: Response bytes
NymProxyServer->>NymProxyServer: Write to provided SURB payloads
NymProxyServer->>Exit Gateway: Anonymous replies
box Remote Host
participant NymProxyServer
participant Upstream Process
end
Entry Gateway--xNymProxyClient: Sphinx Packets: Reply Message 1 dropped: No Ack!
Entry Gateway->>NymProxyClient: Sphinx Packets: Reply Message 2
NymProxyClient-->Entry Gateway: Ack
Entry Gateway->>NymProxyClient: Sphinx Packets: Reply Message 3
NymProxyClient-->Entry Gateway: Ack
Loop Message Buffer:
NymProxyClient->>NymProxyClient: Wait for Message 1
Entry Gateway->>NymProxyClient: Sphinx Packets: Message 1
NymProxyClient-->>Entry Gateway: Acks
NymProxyClient->>NymProxyClient: Message Received: trigger send
NymProxyClient->>Client Process: Response bytes
end
Note right of NymProxyClient: Note this happens **per session**
```
@@ -0,0 +1,4 @@
{
"singleconn": "Single Connection",
"multiconn": "Multi Connection"
}
@@ -0,0 +1,154 @@
# Multi Connection Example
This example starts off several Tcp connections on a loop to a remote endpoint: in this case the `TcpListener` behind the `NymProxyServer` instance on the echo server found in
[`nym/tools/echo-server/`](https://github.com/nymtech/nym/tree/develop/tools/echo-server). It pipes a few messages to it, logs the replies, and keeps track of the number of replies received per connection.
> You can find this code [here](https://github.com/nymtech/nym/blob/develop/sdk/rust/nym-sdk/examples/tcp_proxy_multistream.rs)
```rust
use nym_sdk::mixnet::Recipient;
use nym_sdk::tcp_proxy;
use rand::rngs::SmallRng;
use rand::Rng;
use rand::SeedableRng;
use serde::{Deserialize, Serialize};
use std::env;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpStream;
use tokio::signal;
use tokio_stream::StreamExt;
use tokio_util::codec;
#[derive(Serialize, Deserialize, Debug)]
struct ExampleMessage {
message_id: i8,
message_bytes: Vec<u8>,
tcp_conn: i8,
}
// To run:
// - run the echo server with `cargo run`
// - run this example with `cargo run --example tcp_proxy_multistream -- <ECHO_SERVER_NYM_ADDRESS> <ENV_FILE_PATH> <CLIENT_PORT>` e.g.
// cargo run --example tcp_proxy_multistream -- DMHyxo8n6sKWHHTVvjRVDxDSMX8gYXRU1AQ6UpwsrWiB.6STYCWGWyRxqn2juWdgjMkAMsT9EaAzPpLWq5zkS68MB@CJG5zTcmoLijmDrtAiLV9PZHxNz8LQu6hmgA89V2RxxL ../../../envs/canary.env 8080
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let server_address = env::args().nth(1).expect("Server address not provided");
let server: Recipient =
Recipient::try_from_base58_string(&server_address).expect("Invalid server address");
// Comment this out to just see println! statements from this example.
// Nym client logging is very informative but quite verbose.
// The Message Decay related logging gives you an ideas of the internals of the proxy message ordering: you need to switch
// to DEBUG to see the contents of the msg buffer, sphinx packet chunking, etc.
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
.init();
let env_path = env::args().nth(2).expect("Env file not specified");
let env = env_path.to_string();
let listen_port = env::args().nth(3).expect("Port not specified");
// Within the TcpProxyClient, individual client shutdown is triggered by the timeout.
let proxy_client =
tcp_proxy::NymProxyClient::new(server, "127.0.0.1", &listen_port, 45, Some(env)).await?;
tokio::spawn(async move {
proxy_client.run().await?;
Ok::<(), anyhow::Error>(())
});
println!("waiting for everything to be set up..");
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
println!("done. sending bytes");
// In the info traces you will see the different session IDs being set up, one for each TcpStream.
for i in 0..4 {
let conn_id = i;
println!("Starting TCP connection {}", conn_id);
let local_tcp_addr = format!("127.0.0.1:{}", listen_port.clone());
tokio::spawn(async move {
// Now the client and server proxies are running we can create and pipe traffic to/from
// a socket on the same port as our ProxyClient instance as if we were just communicating
// between a client and host via a normal TcpStream - albeit with a decent amount of additional latency.
//
// The assumption regarding integration is that you know what you're sending, and will do proper
// framing before and after, know what data types you're expecting; the proxies are just piping bytes
// back and forth using tokio's `Bytecodec` under the hood.
let stream = TcpStream::connect(local_tcp_addr).await?;
let (read, mut write) = stream.into_split();
// Lets just send a bunch of messages to the server with variable delays between them, with a message and tcp connection ids to keep track of ordering on the server side (for illustrative purposes **only**; keeping track of anonymous replies is handled by the proxy under the hood with Single Use Reply Blocks (SURBs); for this illustration we want some kind of app-level message id, but irl most of the time you'll probably be parsing on e.g. the incoming response type instead)
tokio::spawn(async move {
for i in 0..4 {
let mut rng = SmallRng::from_entropy();
let delay: f64 = rng.gen_range(2.5..5.0);
tokio::time::sleep(tokio::time::Duration::from_secs_f64(delay)).await;
let random_bytes = gen_bytes_fixed(i as usize);
let msg = ExampleMessage {
message_id: i,
message_bytes: random_bytes,
tcp_conn: conn_id,
};
let serialised = bincode::serialize(&msg)?;
write
.write_all(&serialised)
.await
.expect("couldn't write to stream");
println!(
">> client sent {}: {} bytes on conn {}",
&i,
msg.message_bytes.len(),
&conn_id
);
}
Ok::<(), anyhow::Error>(())
});
tokio::spawn(async move {
let mut reply_counter = 0;
let codec = codec::BytesCodec::new();
let mut framed_read = codec::FramedRead::new(read, codec);
while let Some(Ok(bytes)) = framed_read.next().await {
match bincode::deserialize::<ExampleMessage>(&bytes) {
Ok(msg) => {
println!(
"<< client received {}: {} bytes on conn {}",
msg.message_id,
msg.message_bytes.len(),
msg.tcp_conn
);
reply_counter += 1;
println!(
"tcp connection {} replies received {}/4",
msg.tcp_conn, reply_counter
);
}
Err(e) => {
println!("<< client received something that wasn't an example message of {} bytes. error: {}", bytes.len(), e);
}
}
}
});
Ok::<(), anyhow::Error>(())
});
let mut rng = SmallRng::from_entropy();
let delay: f64 = rng.gen_range(4.5..7.0);
tokio::time::sleep(tokio::time::Duration::from_secs_f64(delay)).await;
}
// Once timeout is passed, you can either wait for graceful shutdown or just hard stop it.
signal::ctrl_c().await?;
println!("CTRL+C received, shutting down");
Ok(())
}
// emulate a series of small messages followed by a closing larger one
fn gen_bytes_fixed(i: usize) -> Vec<u8> {
let amounts = [10, 15, 50, 1000];
let len = amounts[i];
let mut rng = rand::thread_rng();
(0..len).map(|_| rng.gen::<u8>()).collect()
}
```
@@ -0,0 +1,195 @@
# Single Connection Example
This is a basic example which opens a single TCP connection and writes a bunch of messages between a client and some 'echo server' logic, so only uses a single session under the hood and doesn't really show off the message ordering capabilities; this is mainly just a quick introductory illustration on how:
- the mixnet does message ordering
- the NymProxyClient and NymProxyServer can be hooked into and used to communicate between two otherwise pretty vanilla TcpStreams
For a more irl example check the [multi connection example](./multiconn).
> You can find this code [here](https://github.com/nymtech/nym/blob/develop/sdk/rust/nym-sdk/examples/tcp_proxy_single_connection.rs)
```rust
use nym_sdk::tcp_proxy;
use rand::rngs::SmallRng;
use rand::{Rng, SeedableRng};
use serde::{Deserialize, Serialize};
use std::env;
use std::fs;
use std::sync::atomic::{AtomicU8, Ordering};
use tokio::io::AsyncWriteExt;
use tokio::net::{TcpListener, TcpStream};
use tokio::signal;
use tokio_stream::StreamExt;
use tokio_util::codec;
#[derive(Serialize, Deserialize, Debug)]
struct ExampleMessage {
message_id: i8,
message_bytes: Vec<u8>,
}
// Run this with:
// `cargo run --example tcp_proxy_single_connection <SERVER_LISTEN_PORT> <ENV_FILE_PATH> <CLIENT_LISTEN_PATH>` e.g.
// `cargo run --example tcp_proxy_single_connection 8081 ../../../envs/canary.env 8080 `
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Keep track of sent/received messages
let counter = AtomicU8::new(0);
// Comment this out to just see println! statements from this example, as Nym client logging is very informative but quite verbose.
// The Message Decay related logging gives you an ideas of the internals of the proxy message ordering. To see the contents of the msg buffer, sphinx packet chunking, etc change the tracing::Level to DEBUG.
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
.init();
let server_port = env::args()
.nth(1)
.expect("Server listen port not specified");
let upstream_tcp_addr = format!("127.0.0.1:{}", server_port);
// This dir gets cleaned up at the end: NOTE if you switch env between tests without letting the file do the automatic cleanup, make sure to manually remove this directory up before running again, otherwise your client will attempt to use these keys for the new env
let home_dir = dirs::home_dir().expect("Unable to get home directory");
let conf_path = format!("{}/tmp/nym-proxy-server-config", home_dir.display());
let env_path = env::args().nth(2).expect("Env file not specified");
let env = env_path.to_string();
let client_port = env::args().nth(3).expect("Port not specified");
let mut proxy_server =
tcp_proxy::NymProxyServer::new(&upstream_tcp_addr, &conf_path, Some(env_path.clone()))
.await?;
let proxy_nym_addr = proxy_server.nym_address();
// We'll run the instance with a long timeout since we're sending everything down the same Tcp connection, so should be using a single session.
// Within the TcpProxyClient, individual client shutdown is triggered by the timeout.
let proxy_client =
tcp_proxy::NymProxyClient::new(*proxy_nym_addr, "127.0.0.1", &client_port, 60, Some(env))
.await?;
tokio::spawn(async move {
proxy_server.run_with_shutdown().await?;
Ok::<(), anyhow::Error>(())
});
tokio::spawn(async move {
proxy_client.run().await?;
Ok::<(), anyhow::Error>(())
});
// 'Server side' thread: echo back incoming as response to the messages sent in the 'client side' thread below
tokio::spawn(async move {
let listener = TcpListener::bind(upstream_tcp_addr).await?;
loop {
let (socket, _) = listener.accept().await.unwrap();
let (read, mut write) = socket.into_split();
let codec = codec::BytesCodec::new();
let mut framed_read = codec::FramedRead::new(read, codec);
while let Some(Ok(bytes)) = framed_read.next().await {
match bincode::deserialize::<ExampleMessage>(&bytes) {
Ok(msg) => {
println!(
"<< server received {}: {} bytes",
msg.message_id,
msg.message_bytes.len()
);
let msg = ExampleMessage {
message_id: msg.message_id,
message_bytes: msg.message_bytes,
};
let serialised = bincode::serialize(&msg)?;
write
.write_all(&serialised)
.await
.expect("couldnt send reply");
println!(
">> server sent {}: {} bytes",
msg.message_id,
msg.message_bytes.len()
);
}
Err(e) => {
println!("<< server received something that wasn't an example message of {} bytes. error: {}", bytes.len(), e);
}
}
}
}
#[allow(unreachable_code)]
Ok::<(), anyhow::Error>(())
});
// Just wait for Nym clients to connect, TCP clients to bind, etc.
println!("waiting for everything to be set up..");
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
println!("done. sending bytes");
// Now the client and server proxies are running we can create and pipe traffic to/from
// a socket on the same port as our ProxyClient instance as if we were just communicating
// between a client and host via a normal TcpStream - albeit with a decent amount of additional latency.
//
// The assumption regarding integration is that you know what you're sending, and will do proper
// framing before and after, know what data types you're expecting, etc; the proxies are just piping bytes
// back and forth using tokio's `Bytecodec` under the hood.
let local_tcp_addr = format!("127.0.0.1:{}", client_port);
let stream = TcpStream::connect(local_tcp_addr).await?;
let (read, mut write) = stream.into_split();
// 'Client side' thread; lets just send a bunch of messages to the server with variable delays between them, with an id to keep track of ordering in the printlns; the mixnet only guarantees message delivery, not ordering. You might not be necessarily streaming traffic in this manner IRL, but this example is a good illustration of how messages travel through the mixnet.
// - On the level of individual messages broken into multiple packets, the Proxy abstraction deals with making sure that everything is sent between the sockets in the corrent order.
// - On the level of different messages, this is not enforced: you might see in the logs that message 1 arrives at the server and is reconstructed after message 2.
tokio::spawn(async move {
let mut rng = SmallRng::from_entropy();
for i in 0..10 {
let random_bytes = gen_bytes_fixed(i as usize);
let msg = ExampleMessage {
message_id: i,
message_bytes: random_bytes,
};
let serialised = bincode::serialize(&msg)?;
write
.write_all(&serialised)
.await
.expect("couldn't write to stream");
println!(">> client sent {}: {} bytes", &i, msg.message_bytes.len());
let delay = rng.gen_range(3.0..7.0);
tokio::time::sleep(tokio::time::Duration::from_secs_f64(delay)).await;
}
Ok::<(), anyhow::Error>(())
});
let codec = codec::BytesCodec::new();
let mut framed_read = codec::FramedRead::new(read, codec);
while let Some(Ok(bytes)) = framed_read.next().await {
match bincode::deserialize::<ExampleMessage>(&bytes) {
Ok(msg) => {
println!(
"<< client received {}: {} bytes",
msg.message_id,
msg.message_bytes.len()
);
counter.fetch_add(1, Ordering::SeqCst);
println!(
":: messages received back: {:?}/10",
counter.load(Ordering::SeqCst)
);
}
Err(e) => {
println!("<< client received something that wasn't an example message of {} bytes. error: {}", bytes.len(), e);
}
}
}
// Once timeout is passed, you can either wait for graceful shutdown or just hard stop it.
signal::ctrl_c().await?;
println!(":: CTRL+C received, shutting down + cleanup up proxy server config files");
fs::remove_dir_all(conf_path)?;
Ok(())
}
fn gen_bytes_fixed(i: usize) -> Vec<u8> {
let amounts = vec![1, 10, 50, 100, 150, 200, 350, 500, 750, 1000];
let len = amounts[i];
let mut rng = rand::thread_rng();
(0..len).map(|_| rng.gen::<u8>()).collect()
}
```
@@ -1,5 +1,5 @@
# Tools
There are a few tools available to developers for chain interaction: the `nym-cli` tool, which operates as an easier-to-use wrapper around `nyxd`, and the CLI wallet, to allow operators to script interactions with their infrastructure (and those who prefer CLI tools ;) ).
There are a few tools available to developers for chain interaction: the `nym-cli` tool, which operates as an easier-to-use wrapper around `nyxd`, to allow operators to script interactions with their infrastructure (and those who prefer CLI tools ;) ).
There is also a basic echo server tool which app developers can use as a quick endpoint for traffic testing. This will be deployed onto a persistent public server in the future so devs dont have to run it themselves.
@@ -1,5 +1,10 @@
<<<<<<< HEAD:documentation/docs/pages/developers/tools/_meta.js
module.exports = {
"nym-cli": "NYM-CLI tool",
"cli-wallet": "CLI wallet",
=======
{
"nym-cli": "Nym-cli",
>>>>>>> max/new-docs-framework:documentation/docs/pages/developers/tools/_meta.json
"echo-server": "Echo Server"
};
@@ -1,8 +0,0 @@
# CLI Wallet
If you have already read our validator setup and maintenance [documentation](https://nymtech.net/operators/nodes/validator-setup.html) you will have seen that we compile and use the `nyxd` binary primarily for our validators. This binary can however be used for many other tasks, such as creating and using keypairs for wallets, or automated setups that require the signing and broadcasting of transactions.
### Using `nyxd` binary as a CLI wallet
You can use the `nyxd` as a minimal CLI wallet if you want to set up an account (or multiple accounts). Just compile the binary as per the documentation, **stopping after** the [building your validator](https://nymtech.net/operators/nodes/validator-setup.html#building-your-validator) step is complete. You can then run `nyxd keys --help` to see how you can set up and store different keypairs with which to interact with the Nyx blockchain.
For more on interacting with the chain, see the [Interacting with Nyx Chain and Smart Contracts](../nyx/interacting-with-chain.md) page.
@@ -0,0 +1,25 @@
# Echo Server
There is an initial version of a simple echo server located at [`nym/tools/echo-server`](https://github.com/nymtech/nym/tree/develop/tools/echo-server).
This is an initial minimal implementation of an echo server built using the [`NymProxyServer`](../rust/tcpproxy) Rust SDK abstraction that, aside from the initialisation and running of a `NymProxyServer` instance in the background, is essentially a vanilla TCP echo server written with `tokio`.
This server was initially built for the `TcpProxy` tests, but can be useful for developers to need a constant endpoint to ping when developing. In the future this will be deployed to a remote server so developers don't have to run their own.
## Build
Run `cargo build --release` from `nym/tools/echo-server`. The binary will be in the main workspace `target/release` dir.
## Run
All the server requires is a port to connect the TCP listener to. If no `<PATH_TO_ENV>` is supplied then the server defaults to using mainnet.
```sh
echo-server <PORT> <PATH_TO_ENV_FILE>
# e.g. ../../target/release/echo-server 9000 ../../envs/canary.env
```
## Logging
Every 10 seconds, the server logs:
- the total number of bytes received since startup
- the total number of bytes sent since startup
- the current number of concurrent connections it has
- the total number of concurrent connections it has
@@ -11,315 +11,10 @@ It provides a convenient wrapper around the `nymd` client, and has similar funct
## Building
The `nym-cli` binary can be built by running `cargo build --release` in the `nym/tools/nym-cli` directory.
### Usage
You can see all available commands with:
## Usage
See the [commands](./nym-cli/commands.mdx) page for an overview of all command options.
```
./nym-cli --help
```
~~~admonish example collapsible=true title="Console output"
```
nym-cli
A client for interacting with Nym smart contracts and the Nyx blockchain
USAGE:
nym-cli [OPTIONS] <subcommand>
OPTIONS:
--config-env-file <CONFIG_ENV_FILE>
Overrides configuration as a file of environment variables. Note: individual env vars
take precedence over this file.
-h, --help
Print help information
--mixnet-contract-address <MIXNET_CONTRACT_ADDRESS>
Overrides the mixnet contract address provided either as an environment variable or in a
config file
--mnemonic <MNEMONIC>
Provide the mnemonic for your account. You can also provide this is an env var called
MNEMONIC.
--nymd-url <NYMD_URL>
Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a
config file
--validator-api-url <VALIDATOR_API_URL>
Overrides the validator API URL provided either as an environment variable API_VALIDATOR
or in a config file
--vesting-contract-address <VESTING_CONTRACT_ADDRESS>
Overrides the vesting contract address provided either as an environment variable or in
a config file
subcommands:
account Query and manage Nyx blockchain accounts
block Query chain blocks
cosmwasm Manage and execute WASM smart contracts
generate-fig Generates shell completion
help Print this message or the help of the given subcommand(s)
mixnet Manage your mixnet infrastructure, delegate stake or query the directory
signature Sign and verify messages
tx Query for transactions
vesting-schedule Create and query for a vesting schedule
```
~~~
## Example Usage
Below we have listed some example commands for some of the features listed above.
If ever in doubt what you need to type, or if you want to see alternative parameters for a command, use the `nym-cli <subcommand_name> --help` to view all available options.
```
./nym-cli account create --help
```
~~~admonish example collapsible=true title="Console output"
```
Create a new mnemonic - note, this account does not appear on the chain until the account id is used in a transaction
USAGE:
nym-cli account create [OPTIONS]
OPTIONS:
--config-env-file <CONFIG_ENV_FILE>
Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.
-h, --help
Print help information
--mixnet-contract-address <MIXNET_CONTRACT_ADDRESS>
Overrides the mixnet contract address provided either as an environment variable or in a
config file
--mnemonic <MNEMONIC>
Provide the mnemonic for your account. You can also provide this is an env var called
MNEMONIC.
--nymd-url <NYMD_URL>
Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a
config file
--validator-api-url <VALIDATOR_API_URL>
Overrides the validator API URL provided either as an environment variable API_VALIDATOR
or in a config file
--vesting-contract-address <VESTING_CONTRACT_ADDRESS>
Overrides the vesting contract address provided either as an environment variable or in
a config file
--word-count <WORD_COUNT>
```
~~~
### Create account
Creates an account with a random Mnemonic and a new address.
```
./nym-cli account create
# Result:
# 1. Mnemonic
assist jungle spoil domain saddle energy box carpet toy resist castle faith talent note outdoor inform cage lecture syrup trigger dress oppose slender museum
# 2. Address
n132tpw4kkfas7ah0vmq78dwurhxljf2f869tlf5
```
> NEVER share your mnemonic with anyone. Keep it stored in a safe and secure location.
### Check the current balance of an account
Queries the existing balance of an account.
```
# Using adddress below for example purposes.
./nym-cli account balance n1hzn28p2c6pzr98r85jp3h53fy8mju5w7ndd5vh
# Result:
2022-11-10T10:28:54.009Z INFO nym_cli_commands::validator::account::balance > Getting balance for n1hzn28p2c6pzr98r85jp3h53fy8mju5w7ndd5vh...
# Balance for each token will be listed here
0.264 nym
1921.995 nyx
```
You can also query an accounts balance by using its mnemonic:
```
./nym-cli account balance --mnemonic <mnemonic>
```
### Send tokens to an account
Sends tokens to an account using an address.
```
./nym-cli account send <ADDRESS> <AMOUNT>
```
### Get the current block height
Queries the specified blockchain (Nyx chain by default) for the current block height.
```
./nym-cli block current-height --mnemonic <mnemonic>
# Result:
Current block height:
<BLOCK_HEIGHT>
```
### Query for a mix node
Query a mix node on the mixnet.
```
./nym-cli mixnet query mixnodes --mnemonic <mnemonic>
```
### Bond a mix node
Bonding a mix node is a process that takes a few steps due to the need to sign a transaction with your nym address for replay attack protection.
* generate a signature payload:
```
./nym-cli mixnet operators mixnode create-mixnode-bonding-sign-payload
# returns something like
97GEhgMrPTmQVZgHqJeqWmgQ154GLKqy8xNGtLkV8xy5xc1SuwsEnqjhtZVshBYK74n53fFkKbSrS6kxkBE3vUikbU76JZmLMFmfR7aaU2NdBnfTPPHP2nwb2hJiEueq4SvvtDtQckxv7ZJzdxyXHxUeDPhzbprxTff78U3NGNk4cg6Q2K4EFqishdaqToedsXAPvVCWNbC1iWVjEq8nJ95Eb3NJyi3KmXcNDy4i8ZXgZHu4v8F4htXq2vZUdBSbizdkNr1NRvEg6PGVQdTseyuN8JxD3yuvrqprPY2kvJaT2YiYLPgWxoQtbfwcpkX4PP1PvwuMg4W8EXhitMpM2WHqLDP5vgfDGxdDCmRS44pM8ya4hcQ4g3McHWxduGWdbCzNNEsX6oQw4LVFcWn4mhbXSgqHwNQMm2TQW6LatYZSwCczdhEwV2CXe36UGCUzozmm4nj9qfUtXqDzMrHAAS8kjbKaVNaVaRRKgauQrHnK7QGg1QpVnnaxCs14wvUb62sio8XZmMzP2SjVaRJFCyJB3UwZ6L4oXMGMXSRsiKe8ZNTaa6iX69tx54CAAHBHoiReiq7E5T2VuR5v
```
* sign this payload:
```
./nym-mixnode sign --id upgrade_test --contract-msg 97GEhgMrPTmQVZgHqJeqWmgQ154GLKqy8xNGtLkV8xy5xc1SuwsEnqjhtZVshBYK74n53fFkKbSrS6kxkBE3vUikbU76JZmLMFmfR7aaU2NdBnfTPPHP2nwb2hJiEueq4SvvtDtQckxv7ZJzdxyXHxUeDPhzbprxTff78U3NGNk4cg6Q2K4EFqishdaqToedsXAPvVCWNbC1iWVjEq8nJ95Eb3NJyi3KmXcNDy4i8ZXgZHu4v8F4htXq2vZUdBSbizdkNr1NRvEg6PGVQdTseyuN8JxD3yuvrqprPY2kvJaT2YiYLPgWxoQtbfwcpkX4PP1PvwuMg4W8EXhitMpM2WHqLDP5vgfDGxdDCmRS44pM8ya4hcQ4g3McHWxduGWdbCzNNEsX6oQw4LVFcWn4mhbXSgqHwNQMm2TQW6LatYZSwCczdhEwV2CXe36UGCUzozmm4nj9qfUtXqDzMrHAAS8kjbKaVNaVaRRKgauQrHnK7QGg1QpVnnaxCs14wvUb62sio8XZmMzP2SjVaRJFCyJB3UwZ6L4oXMGMXSRsiKe8ZNTaa6iX69tx54CAAHBHoiReiq7E5T2VuR5v
```
* bond the node using the signature:
```
./nym-cli --mnemonic <mnemonic> mixnet operators mixnode bond --amount 100000000 --mix-port 1789 --version "1.1.13" --host "85.163.111.99" --identity-key "B6pWscxYb8sPAdKTci8zPy5AgMzn5Zx8KpWwQNCyUSU7" --location "nym-town" --sphinx-key "o6MmKHzRewpNzVwaV37ZX9G3BfK4AmfYvsQfyoyAFRk" --signature "2TujBZfer8r5QM639Yb8coD9xH6f5eXzjAT5dD7wMom9fH8D1u36d7UpPdVaaZrWsCynmYpobwMWqiMKr5kM6CprD"
```
### Bond a gateway
Bonding a mix node is a process that takes a few steps due to the need to sign a transaction with your nym address for replay attack protection.
* generate a signature payload:
```
./nym-cli mixnet operators gateway create-gateway-bonding-sign-payload
# returns something like
97GEhgMrPTmQVZgHqJeqWmgQ154GLKqy8xNGtLkV8xy5xc1SuwsEnqjhtZVshBYK74n53fFkKbSrS6kxkBE3vUikbU76JZmLMFmfR7aaU2NdBnfTPPHP2nwb2hJiEueq4SvvtDtQckxv7ZJzdxyXHxUeDPhzbprxTff78U3NGNk4cg6Q2K4EFqishdaqToedsXAPvVCWNbC1iWVjEq8nJ95Eb3NJyi3KmXcNDy4i8ZXgZHu4v8F4htXq2vZUdBSbizdkNr1NRvEg6PGVQdTseyuN8JxD3yuvrqprPY2kvJaT2YiYLPgWxoQtbfwcpkX4PP1PvwuMg4W8EXhitMpM2WHqLDP5vgfDGxdDCmRS44pM8ya4hcQ4g3McHWxduGWdbCzNNEsX6oQw4LVFcWn4mhbXSgqHwNQMm2TQW6LatYZSwCczdhEwV2CXe36UGCUzozmm4nj9qfUtXqDzMrHAAS8kjbKaVNaVaRRKgauQrHnK7QGg1QpVnnaxCs14wvUb62sio8XZmMzP2SjVaRJFCyJB3UwZ6L4oXMGMXSRsiKe8ZNTaa6iX69tx54CAAHBHoiReiq7E5T2VuR5v
```
* sign this payload:
```
./nym-gateway sign --id upgrade_test --contract-msg 97GEhgMrPTmQVZgHqJeqWmgQ154GLKqy8xNGtLkV8xy5xc1SuwsEnqjhtZVshBYK74n53fFkKbSrS6kxkBE3vUikbU76JZmLMFmfR7aaU2NdBnfTPPHP2nwb2hJiEueq4SvvtDtQckxv7ZJzdxyXHxUeDPhzbprxTff78U3NGNk4cg6Q2K4EFqishdaqToedsXAPvVCWNbC1iWVjEq8nJ95Eb3NJyi3KmXcNDy4i8ZXgZHu4v8F4htXq2vZUdBSbizdkNr1NRvEg6PGVQdTseyuN8JxD3yuvrqprPY2kvJaT2YiYLPgWxoQtbfwcpkX4PP1PvwuMg4W8EXhitMpM2WHqLDP5vgfDGxdDCmRS44pM8ya4hcQ4g3McHWxduGWdbCzNNEsX6oQw4LVFcWn4mhbXSgqHwNQMm2TQW6LatYZSwCczdhEwV2CXe36UGCUzozmm4nj9qfUtXqDzMrHAAS8kjbKaVNaVaRRKgauQrHnK7QGg1QpVnnaxCs14wvUb62sio8XZmMzP2SjVaRJFCyJB3UwZ6L4oXMGMXSRsiKe8ZNTaa6iX69tx54CAAHBHoiReiq7E5T2VuR5v
```
* bond the node using this signature:
```
./nym-cli --mnemonic <mnemonic> mixnet operators gateway bond --amount 100000000 --mix-port 1789 --version "1.1.13" --host "85.163.111.99" --identity-key "B6pWscxYb8sPAdKTci8zPy5AgMzn5Zx8KpWwQNCyUSU7" --location "nym-town" --sphinx-key "o6MmKHzRewpNzVwaV37ZX9G3BfK4AmfYvsQfyoyAFRk" --signature "2TujBZfer8r5QM639Yb8coD9xH6f5eXzjAT5dD7wMom9fH8D1u36d7UpPdVaaZrWsCynmYpobwMWqiMKr5kM6CprD"
```
### Un-bond a node
Un-bond a mix node or gateway.
```
./nym-cli mixnet operators gateway unbound --mnemonic <mnemonic>
```
> The same command can be applied with a mix node. Just replace `gateway` with `mixnode`.
### Upgrade a mix node
Upgrade your node config.
```
./nym-cli mixnet operators mixnode settings update-config --version <new_version>
```
### Claim a vesting reward for a mixnode
Claim rewards for a mix node bonded with locked tokens.
```
./nym-cli mixnet operators mixnode rewards vesting-claim --mnemonic <mnemonic>
```
### Claim rewards
```
./nym-cli mixnet operators mixnode rewards --mnemonic <mnemonic>
```
### Manage Mix node Settings
Manage your mix node settings stored in the directory.
```
./nym-cli mixnet operators mixnode settings update-config --version <VERSION_NUMBER>
```
### Delegate Stake
Delegate to a mix node.
```
./nym-cli mixnet delegators delegate --amount <AMOUNT> mix-id <MIX_ID> --mnemonic <mnemonic>
```
### Un-delegate Stake
Remove stake from a mix node.
```
./nym-cli mixnet delegators undelegate --mix-id <MIX-ID> --mnemonic <mnemonic>
```
### Query a reward for a delegator
Claim rewards accumulated during the delegation of unlocked tokens.
```
./nym-cli mixnet delegators rewards claim --mix-id <MIX-ID> --mnemonic <mnemonic>
```
### Signature Generation: Sign a message
Sign a message.
```
./nym-cli signature sign --mnemonic <mnemonic> <MESSAGE>
# Result:
{"account_id":<ACCOUNT_ID>,"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":<PUBLIC_KEY>},"signature":"<OUTPUT_SIGNATURE>"}
```
### Signature Generation: Verify a signature
Verify a signature.
```
./nym-cli signature verify --mnemonic <mnemonic> <PUBLIC_KEY_OR_ADDRESS> <SIGNATURE_AS_HEX> <MESSAGE>
```
### Create a Vesting Schedule
Creates a vesting schedule for an account in the [vesting smart contract](../nyx/vesting-contract.md).
```
./nym-cli vesting-schedule create --mnemonic <mnemonic> --address <ADDRESS> --amount <AMOUNT>
```
### Query a Vesting Schedule
Query for vesting schedule in the [vesting smart contract](../nyx/vesting-contract.md).
```
./nym-cli vesting-schedule query --mnemonic <mnemonic>
```
## Staking on someone's behalf (for custodians)
### Staking on someone's behalf (for custodians)
There is a limitation the staking address can only perform the following actions (and are visible via the Nym Wallet:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,5 @@
# Introduction
Welcome to the documentation for Nym's TypeScript SDK!
This comprehensive guide contains information about the various TypeScript SDK modules that facilitate interaction with different components of the Nym stack, including the Nym mixnet, the Nyx blockchain, and Coconut credentials.
@@ -0,0 +1,22 @@
# TS SDK FAQ
## Why and when does the mixnet client complain about insufficient topology?
It will in one of the following cases:
- There are empty mix layers - although this is rare;
- The gateway you've registered with does not appear in the network topology -> it is either unbonded or was blacklisted;
- The gateway you want to send packets to does not appear in the network topology -> it is either unbonded or was blacklisted;
To avoid the last two, you need to make sure the gateway you are calling is bonded and whitelisted.
## How can I check whether the gateway I am connecting to is bonded and not blacklisted?
The easiest way of checking what gateway you're registered with is to look at your client address.
Client addresses are in the format of:
`client-id . client-dh @ gateway-id. `
To illustrate this: `DpB3cHAchJiNBQi5FrZx2csXb1mrHkpYh9Wzf8Rjsuko.ANNWrvHqMYuertHGHUrZdBntQhpzfbWekB39qez9U2Vx@2BuMSfMW3zpeAjKXyKLhmY4QW1DXurrtSPEJ6CjX3SEh `
- `DpB3cHAchJiNBQi5FrZx2csXb1mrHkpYh9Wzf8Rjsuko`: is the client's identity key;
- `ANNWrvHqMYuertHGHUrZdBntQhpzfbWekB39qez9U2Vx`: is the client's Diffie Hellman key;
- `2BuMSfMW3zpeAjKXyKLhmY4QW1DXurrtSPEJ6CjX3SEh`: is the gateway's identity, which is what you'll need to check the state of the gateway in the [Nym Explorer](https://explorer.nymtech.net/network-components/gateways).
@@ -1,74 +0,0 @@
# Welcome to the TS SDK FAQ!
## How can I interact with Nym?
#### For existing projects:
If you would like to integrate parts of the Nym stack to your existing app, please check out the dedicated [integrations page](../FAQ/integrations).
#### For builders:
###### SDKs
If youre looking to build or Nymify existing solutions, read on: For developing in Rust or TS/JS, then the Nym SDKs are your go-to. Please visit the [Rust SDK documentation](https://nymtech.net/developers/tutorials/rust-sdk.html) for more Rust-related information and tutorials.
Stay on this page, the [TS SDK handbook](../) (you are here) for using the TypeScript SDK.
These SDKs abstract away much of the messaging and core logic from your app, and allow you to run a Nym client as part of your application process, instead of having to run them separately. In short, they simplify building Nym clients into your project.
###### Standalone Nym clients: Websocket, WebAssembly, SOCKS5
Alternatively, you can also use one of the three standalone Nym clients to connect your application to the mixnet.
These clients do the majority of the heavy-lifting with regards to cryptographic operations and routing under the hood.
Essentially, they all do the same thing: create a connection to a gateway, encrypt and decrypt packets sent to and received from the mixnet, and send cover traffic to hide the flow of actual app traffic from observers. You can learn more about the Nym clients in this [Nym integration page](https://nymtech.net/developers/integrations/mixnet-integration.html).
###### Network requesters:
Network requesters are a type of Service Provider that essentially act as a kind of proxy, somewhat similarly to a Tor exit node. If you have access to a server, you can run a Network Requester, which will perform the following functions:
- Send outbound requests from the local machine through the mixnet to a server;
- The Network Requester then makes a request on the users behalf, shielding the user and their metadata from the untrusted and unknown infrastructure, for example with email or instant messaging client servers;
By default the Network Requester is not an open proxy but rather uses a local and global [allow list](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to whitelist host access.
## Which Service Provider to run?
In order to ensure uptime and reliability, it is recommended that you run some pieces of mixnet infrastructure. This infrastructure varies depending on the architecture of your application, as well as the endpoints that it needs to hit:
- No Service Provider (Network Requester) needed: If youre running a purely P2P application, then just integrating clients and having some method of sharing addresses should be enough to route your traffic through the mixnet;
- Network Requester needed (existing or own): If youre wanting to place the mixnet between your users application instances and a server-based backend, you will need a Network Requester. In this case, if your app supports SOCKS5, you could either use an existing NR or, if your app supports SOCKS5 but needs more extensive whitelisting, you could use the [network requester service provider binary](https://nymtech.net/operators/nodes/network-requester-setup.html) to proxy these requests to your application backend yourself, with the mixnet between the user and your service, in order to prevent metadata leakage being broadcast to the internet.
- Running your own Service Provider: If your usecase is more complex, youre wanting to route RPC requests through the mixnet to a blockchain for example, you will need to look into setting up some sort of Service that does the transaction broadcasting for you. You can find examples of such projects on the [community applications page](https://nymtech.net/developers/community-resources/community-applications-and-guides.html).
## Why gateways?
Nym apps have a stable, potentially long-lasting relation to a gateway node. A client will establish a symmetric key share with a gateway that can be verified on subsequent connection attempts.
Gateways serve a few different functions:
- They act as an end-to-end encrypted message store in case your app goes offline;
- They send encrypted [surb-acks](https://nymtech.net/docs/architecture/traffic-flow.html) for potentially offline recipients, to ensure reliable message delivery;
- They offer a stable addressing location for apps, although the IP may change frequently;
If you want to learn more about gateways, you can check the [mixnet integration page](https://nymtech.net/developers/integrations/mixnet-integration.html).
## Why and when does the mixnet client complain about insufficient topology?
It will in one of the following cases:
- There are empty mix layers - although this is rare;
- The gateway you've registered with does not appear in the network topology -> it is either unbonded or was blacklisted;
- The gateway you want to send packets to does not appear in the network topology -> it is either unbonded or was blacklisted;
To avoid the last two, you need to make sure the gateway you are calling is bonded and whitelisted.
## How can I check whether the gateway I am connecting to is bonded and not blacklisted?
The easiest way of checking what gateway you're registered with is to look at your client address.
Client addresses are in the format of:
`client-id . client-dh @ gateway-id. `
To illustrate this: `DpB3cHAchJiNBQi5FrZx2csXb1mrHkpYh9Wzf8Rjsuko.ANNWrvHqMYuertHGHUrZdBntQhpzfbWekB39qez9U2Vx@2BuMSfMW3zpeAjKXyKLhmY4QW1DXurrtSPEJ6CjX3SEh `
- `DpB3cHAchJiNBQi5FrZx2csXb1mrHkpYh9Wzf8Rjsuko`: is the client's identity key;
- `ANNWrvHqMYuertHGHUrZdBntQhpzfbWekB39qez9U2Vx`: is the client's Diffie Hellman key;
- `2BuMSfMW3zpeAjKXyKLhmY4QW1DXurrtSPEJ6CjX3SEh`: is the gateway's identity, which is what you'll need to check the state of the gateway in the [Nym Explorer](https://explorer.nymtech.net/network-components/gateways).
## How can I get my service host whitelisted?
Currently, the different options are:
- You can get it added to the local list of an existing Network Requester;
- You can ask the Nym team to add it to the global [allow list](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) if it's not already there;
- You can run your own Network Requester and locally configure it to allow the hosts you need to connect to;
If you'd like to learn more about Network Requesters and the global allow list, you can visit the [network requester set-up page](https://nymtech.net/operators/nodes/network-requester-setup.html).
@@ -1,7 +1,10 @@
<<<<<<< HEAD:documentation/docs/pages/developers/typescript/_meta.js
module.exports = {
"index": "Introduction",
=======
{
>>>>>>> max/new-docs-framework:documentation/docs/pages/developers/typescript/_meta.json
"overview": "SDK overview",
"integrations": "Nym integrations",
"installation": "Installation",
"start": "Getting started",
"examples": "Step-by-step examples",
@@ -7,15 +7,15 @@ An easy way to secure parts or all of your web app is to replace calls to [`fetc
MixFetch works the same as vanilla `fetch` as it's a proxied wrapper around the original function.
Sounds great, are there any catches? Well, there are a few (for now):
1. Currently, the operators of Network Requesters that make the final request at the egress part of the Nym mixnet to the internet use a [standard allow list](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) in combination with their own configuration. If you are trying to access something that is not on the allow list, please check the FAQ page.
- CA certificates in `mixFetch` are periodically updated, so if you get a certificate error, the root certificate you need might not be valid. If that's the case, [send a PR](https://github.com/nymtech/nym/pulls) if you need changes to the Certificates.
2. CA certificates in `mixFetch` are periodically updated, so if you get a certificate error, the root certificate you need might not be valid. If that's the case, [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 to avoid getting a [mixed content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) error.
3. If you are using `mixFetch` in a web app with HTTPS you will need to use a gateway that has Secure Websockets to avoid getting a [mixed content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) error.
- For now, `mixfetch` doesn't work with SURBS, although this will change in the future.
4. For now, mixfetch doesn't work with SURBS, altough this may change in the future.
- For now, `mixFetch` cannot deal with concurrent requests with the same base URL.
Read [this article](https://blog.nymtech.net/mixfetch-like-the-fetch-api-but-via-the-mixnet-82acfd435c62) to learn more about mixFetch.
Read [this article](https://blog.nymtech.net/mixfetch-like-the-fetch-api-but-via-the-mixnet-82acfd435c62) to learn more.
<Callout type="info" emoji="️">
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.
@@ -20,14 +20,14 @@ npm create vite@latest
During the environment setup, choose React and subsequently opt for Typescript if you want your application to function smoothly following this tutorial. Next, navigate to your application directory and run the following commands:
```bash
cd < YOUR_APP >
npm i
npm i
npm run dev
```
##### Installation
Install the required package:
```bash
npm install @nymproject/sdk-full-fat
npm install @nymproject/sdk-full-fat
```
##### Imports
@@ -41,7 +41,7 @@ import { createNymMixnetClient, NymMixnetClient, Payload } from "@nymproject/sdk
##### Example: using the SDK's Mixnet Client to send and receive messages over the Nym mixnet
By pasting the below code example, you should be able to send and receive messages through the mixnet through an unstyled mixnet app template!
<Callout type="warning" emoji="️">
For this example, we will be using the `full-fat` version of the ESM SDK. If you'd like to use the unbundled version of the ESM one, make sure your [bundler configuration](../../bundling/bundling) copies the WebAssembly (WASM) and web worker files to the output bundle.
For this example, we will be using the `full-fat` version of the ESM SDK. If you'd like to use the unbundled version of the ESM one, make sure your [bundler configuration](../bundling/bundling) copies the WebAssembly (WASM) and web worker files to the output bundle.
</Callout>
```ts
@@ -52,33 +52,33 @@ import {
NymMixnetClient,
Payload,
} from "@nymproject/sdk-full-fat";
const nymApiUrl = "https://validator.nymtech.net/api";
export function MixnetClient() {
const [nym, setNym] = useState<NymMixnetClient>();
const [selfAddress, setSelfAddress] = useState<string>();
const [recipient, setRecipient] = useState<string>();
const [payload, setPayload] = useState<Payload>();
const [receivedMessage, setReceivedMessage] = useState<string>();
const init = async () => {
const client = await createNymMixnetClient();
setNym(client);
// Start the client and connect to a gateway
await client?.client.start({
clientId: crypto.randomUUID(),
nymApiUrl,
forceTls: true, // force WSS
});
// Check when is connected and set the self address
client?.events.subscribeToConnected((e) => {
const { address } = e.args;
setSelfAddress(address);
});
// Show whether the client is ready or not
client?.events.subscribeToLoaded((e) => {
console.log("Client ready: ", e.args);
@@ -100,19 +100,19 @@ export function MixnetClient() {
if (!nym || !payload || !recipient) return
nym.client.send({ payload, recipient });
}
useEffect(() => {
init();
return () => {
stop();
};
}, []);
if (!nym) return <div>Waiting for the mixnet client...</div>;
if (!selfAddress) return <div>Connecting...</div>;
return (
<div>
<h1>Send messages through the Nym mixnet</h1>
@@ -137,7 +137,7 @@ export function MixnetClient() {
</div>
);
};
export default function App () {
return (
<>

Some files were not shown because too many files have changed in this diff Show More