Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0bb71399ee | |||
| 1f144690da | |||
| eec1895acc | |||
| 99864cb7a9 | |||
| 3155728119 | |||
| 65a1d6d91e | |||
| 44cf9b054b | |||
| 39e2473ef3 | |||
| 93a108863c | |||
| 0905593123 | |||
| ed9223d5a3 | |||
| 962684ff56 | |||
| 7b3804c078 | |||
| 170f1823e1 | |||
| dc2020559a | |||
| 2b9444cce3 | |||
| 68c1c068ac | |||
| 3d0b70a237 | |||
| 65a6edc78c | |||
| 2ec8349897 | |||
| 38a2d94f80 | |||
| c7fa910516 | |||
| 2fe08274dd | |||
| be89d848dc | |||
| a230a9b8b9 | |||
| 72eae7cdf3 | |||
| 7cae195370 | |||
| dfb16e385c | |||
| 660e1cad0a | |||
| 7c1aa57a7e | |||
| a06e496f78 | |||
| 70599b97b9 | |||
| 02b194bde0 | |||
| 20ec049db5 | |||
| ebac4e8564 | |||
| da81664729 | |||
| fec3d46b33 | |||
| a4eb3a7dbf | |||
| 28d15f2c4f | |||
| c6f93e38f5 | |||
| 2159f71888 | |||
| a9abea3446 | |||
| 8e2713c9ba | |||
| 2ba0ef0e35 | |||
| d3713cbc79 | |||
| 4d3fb2b585 | |||
| ebfb9c4bc1 | |||
| 8e7918cc45 | |||
| c465eb3efc | |||
| b90136ac4e | |||
| ae5373168d | |||
| 6f3942f6b7 | |||
| 13f38343aa | |||
| f75b4843e8 | |||
| b43844bd7a | |||
| cd89feb57e | |||
| 17553d606e | |||
| b6d9ed960b | |||
| 1d89a887fb |
@@ -104,8 +104,6 @@ jobs:
|
||||
name: nym-binaries-artifacts
|
||||
path: |
|
||||
target/release/nym-client
|
||||
target/release/nym-gateway
|
||||
target/release/nym-mixnode
|
||||
target/release/nym-socks5-client
|
||||
target/release/nym-api
|
||||
target/release/nym-network-requester
|
||||
@@ -123,8 +121,6 @@ jobs:
|
||||
OUTPUT_DIR: ci-builds/${{ github.ref_name }}
|
||||
run: |
|
||||
cp target/release/nym-client $OUTPUT_DIR
|
||||
cp target/release/nym-gateway $OUTPUT_DIR
|
||||
cp target/release/nym-mixnode $OUTPUT_DIR
|
||||
cp target/release/nym-socks5-client $OUTPUT_DIR
|
||||
cp target/release/nym-api $OUTPUT_DIR
|
||||
cp target/release/nym-network-requester $OUTPUT_DIR
|
||||
|
||||
@@ -4,6 +4,38 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2024.7-doubledecker] (2024-07-04)
|
||||
|
||||
- Add an early return in `parse_raw_str_logs` for empty raw log strings. ([#4686])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /wasm/mix-fetch/internal-dev ([#4672])
|
||||
- add expiry returned on import ([#4670])
|
||||
- [bugfix] missing rustls feature ([#4666])
|
||||
- Bump ws from 8.13.0 to 8.17.1 in /wasm/client/internal-dev-node ([#4665])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /clients/native/examples/js-examples/websocket ([#4663])
|
||||
- Bump ws from 8.14.2 to 8.17.1 in /sdk/typescript/packages/nodejs-client ([#4662])
|
||||
- Update setup.md ([#4661])
|
||||
- New clippy lints ([#4660])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /nym-api/tests ([#4659])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /docker/typescript_client/upload_contract ([#4658])
|
||||
- Update vps-setup.md ([#4656])
|
||||
- Update configuration.md ([#4655])
|
||||
- Remove old PR template ([#4639])
|
||||
|
||||
[#4686]: https://github.com/nymtech/nym/pull/4686
|
||||
[#4672]: https://github.com/nymtech/nym/pull/4672
|
||||
[#4670]: https://github.com/nymtech/nym/pull/4670
|
||||
[#4666]: https://github.com/nymtech/nym/pull/4666
|
||||
[#4665]: https://github.com/nymtech/nym/pull/4665
|
||||
[#4663]: https://github.com/nymtech/nym/pull/4663
|
||||
[#4662]: https://github.com/nymtech/nym/pull/4662
|
||||
[#4661]: https://github.com/nymtech/nym/pull/4661
|
||||
[#4660]: https://github.com/nymtech/nym/pull/4660
|
||||
[#4659]: https://github.com/nymtech/nym/pull/4659
|
||||
[#4658]: https://github.com/nymtech/nym/pull/4658
|
||||
[#4656]: https://github.com/nymtech/nym/pull/4656
|
||||
[#4655]: https://github.com/nymtech/nym/pull/4655
|
||||
[#4639]: https://github.com/nymtech/nym/pull/4639
|
||||
|
||||
## [2024.6-chomp] (2024-06-25)
|
||||
|
||||
- Remove additional code as part of Ephemera Purge and SP and contracts ([#4650])
|
||||
|
||||
Generated
+75
-8
@@ -2093,7 +2093,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||
|
||||
[[package]]
|
||||
name = "explorer-api"
|
||||
version = "1.1.35"
|
||||
version = "1.1.36"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap 4.5.4",
|
||||
@@ -3849,7 +3849,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-api"
|
||||
version = "1.1.39"
|
||||
version = "1.1.40"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3950,6 +3950,54 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-authenticator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"bs58 0.5.1",
|
||||
"bytes",
|
||||
"clap 4.5.4",
|
||||
"fastrand 2.1.0",
|
||||
"futures",
|
||||
"ipnetwork 0.16.0",
|
||||
"log",
|
||||
"nym-authenticator-requests",
|
||||
"nym-bin-common",
|
||||
"nym-client-core",
|
||||
"nym-config",
|
||||
"nym-crypto",
|
||||
"nym-id",
|
||||
"nym-network-defaults",
|
||||
"nym-sdk",
|
||||
"nym-service-providers-common",
|
||||
"nym-sphinx",
|
||||
"nym-task",
|
||||
"nym-types",
|
||||
"nym-wireguard",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-authenticator-requests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"nym-sphinx",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-bandwidth-controller"
|
||||
version = "0.1.0"
|
||||
@@ -4009,7 +4057,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-cli"
|
||||
version = "1.1.37"
|
||||
version = "1.1.38"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.13.1",
|
||||
@@ -4088,7 +4136,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-client"
|
||||
version = "1.1.36"
|
||||
version = "1.1.37"
|
||||
dependencies = [
|
||||
"bs58 0.5.1",
|
||||
"clap 4.5.4",
|
||||
@@ -4514,6 +4562,7 @@ dependencies = [
|
||||
"ipnetwork 0.16.0",
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
"nym-authenticator",
|
||||
"nym-bin-common",
|
||||
"nym-config",
|
||||
"nym-credentials",
|
||||
@@ -4901,7 +4950,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-requester"
|
||||
version = "1.1.37"
|
||||
version = "1.1.38"
|
||||
dependencies = [
|
||||
"addr",
|
||||
"anyhow",
|
||||
@@ -4950,9 +4999,26 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-statistics"
|
||||
version = "1.1.34"
|
||||
dependencies = [
|
||||
"dirs 4.0.0",
|
||||
"log",
|
||||
"nym-bin-common",
|
||||
"nym-statistics-common",
|
||||
"nym-task",
|
||||
"pretty_env_logger",
|
||||
"rocket",
|
||||
"serde",
|
||||
"sqlx",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-node"
|
||||
version = "1.1.3"
|
||||
version = "1.1.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bip39",
|
||||
@@ -4964,6 +5030,7 @@ dependencies = [
|
||||
"cupid",
|
||||
"humantime-serde",
|
||||
"ipnetwork 0.16.0",
|
||||
"nym-authenticator",
|
||||
"nym-bin-common",
|
||||
"nym-client-core-config-types",
|
||||
"nym-config",
|
||||
@@ -5214,7 +5281,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.36"
|
||||
version = "1.1.37"
|
||||
dependencies = [
|
||||
"bs58 0.5.1",
|
||||
"clap 4.5.4",
|
||||
@@ -5727,7 +5794,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nymvisor"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
||||
@@ -20,6 +20,7 @@ members = [
|
||||
"clients/native",
|
||||
"clients/native/websocket-requests",
|
||||
"clients/socks5",
|
||||
"common/authenticator-requests",
|
||||
"common/async-file-watcher",
|
||||
"common/bandwidth-controller",
|
||||
"common/bin-common",
|
||||
@@ -95,6 +96,7 @@ members = [
|
||||
"mixnode",
|
||||
"sdk/lib/socks5-listener",
|
||||
"sdk/rust/nym-sdk",
|
||||
"service-providers/authenticator",
|
||||
"service-providers/common",
|
||||
"service-providers/ip-packet-router",
|
||||
"service-providers/network-requester",
|
||||
|
||||
@@ -52,7 +52,7 @@ References for developers:
|
||||
|
||||
You can chat to us in two places:
|
||||
* The #dev channel on [Matrix](https://matrix.to/#/#dev:nymtech.chat)
|
||||
* The various developer channels on [Discord](discord.gg/nymproject)
|
||||
* The various developer channels on [Discord](https://discord.gg/nym)
|
||||
|
||||
### Tokenomics & Rewards
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.36"
|
||||
version = "1.1.37"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.36"
|
||||
version = "1.1.37"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "nym-authenticator-requests"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
bincode = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
nym-wireguard-types = { path = "../wireguard-types" }
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod v1;
|
||||
|
||||
pub const CURRENT_VERSION: u8 = 1;
|
||||
|
||||
fn make_bincode_serializer() -> impl bincode::Options {
|
||||
use bincode::Options;
|
||||
bincode::DefaultOptions::new()
|
||||
.with_big_endian()
|
||||
.with_varint_encoding()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
|
||||
const VERSION: u8 = 1;
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_wireguard_types::{GatewayClient, InitMessage};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::make_bincode_serializer;
|
||||
|
||||
use super::VERSION;
|
||||
|
||||
fn generate_random() -> u64 {
|
||||
use rand::RngCore;
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
rng.next_u64()
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthenticatorRequest {
|
||||
pub version: u8,
|
||||
pub data: AuthenticatorRequestData,
|
||||
pub reply_to: Recipient,
|
||||
pub request_id: u64,
|
||||
}
|
||||
|
||||
impl AuthenticatorRequest {
|
||||
pub fn from_reconstructed_message(
|
||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
||||
) -> Result<Self, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().deserialize(&message.message)
|
||||
}
|
||||
|
||||
pub fn new_initial_request(init_message: InitMessage, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorRequestData::Initial(init_message),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_final_request(gateway_client: GatewayClient, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorRequestData::Final(gateway_client),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().serialize(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum AuthenticatorRequestData {
|
||||
Initial(InitMessage),
|
||||
Final(GatewayClient),
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_wireguard_types::registration::RegistrationData;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::make_bincode_serializer;
|
||||
|
||||
use super::VERSION;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthenticatorResponse {
|
||||
pub version: u8,
|
||||
pub data: AuthenticatorResponseData,
|
||||
pub reply_to: Recipient,
|
||||
}
|
||||
|
||||
impl AuthenticatorResponse {
|
||||
pub fn new_pending_registration_success(
|
||||
registration_data: RegistrationData,
|
||||
request_id: u64,
|
||||
reply_to: Recipient,
|
||||
) -> Self {
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
|
||||
reply: registration_data,
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_registered(reply_to: Recipient, request_id: u64) -> Self {
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorResponseData::Registered(RegisteredResponse {
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recipient(&self) -> Recipient {
|
||||
self.reply_to
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().serialize(self)
|
||||
}
|
||||
|
||||
pub fn from_reconstructed_message(
|
||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
||||
) -> Result<Self, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().deserialize(&message.message)
|
||||
}
|
||||
|
||||
pub fn id(&self) -> Option<u64> {
|
||||
match &self.data {
|
||||
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
|
||||
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum AuthenticatorResponseData {
|
||||
PendingRegistration(PendingRegistrationResponse),
|
||||
Registered(RegisteredResponse),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct PendingRegistrationResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
pub reply: RegistrationData,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RegisteredResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// See other comments for other TaskStatus message enumds about abusing the Error trait when we
|
||||
// should have a new trait for TaskStatus messages
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum BandwidthStatusMessage {
|
||||
#[error("remaining bandwidth: {0}")]
|
||||
RemainingBandwidth(i64),
|
||||
|
||||
#[error("no bandwidth left")]
|
||||
NoBandwidth,
|
||||
}
|
||||
@@ -14,8 +14,11 @@ use nym_validator_client::coconut::all_coconut_api_clients;
|
||||
use nym_validator_client::nym_api::EpochId;
|
||||
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
||||
|
||||
pub use event::BandwidthStatusMessage;
|
||||
|
||||
pub mod acquire;
|
||||
pub mod error;
|
||||
mod event;
|
||||
mod utils;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::traits::GatewayPacketRouter;
|
||||
use crate::{cleanup_socket_message, try_decrypt_binary_message};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use log::*;
|
||||
use nym_bandwidth_controller::BandwidthController;
|
||||
use nym_bandwidth_controller::{BandwidthController, BandwidthStatusMessage};
|
||||
use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
|
||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||
use nym_credentials::CredentialSpendingData;
|
||||
@@ -105,8 +105,8 @@ pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
|
||||
// currently unused (but populated)
|
||||
negotiated_protocol: Option<u8>,
|
||||
|
||||
/// Listen to shutdown messages.
|
||||
shutdown: TaskClient,
|
||||
/// Listen to shutdown messages and send notifications back to the task manager
|
||||
task_client: TaskClient,
|
||||
}
|
||||
|
||||
impl<C, St> GatewayClient<C, St> {
|
||||
@@ -117,7 +117,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
shared_key: Option<Arc<SharedKeys>>,
|
||||
packet_router: PacketRouter,
|
||||
bandwidth_controller: Option<BandwidthController<C, St>>,
|
||||
shutdown: TaskClient,
|
||||
task_client: TaskClient,
|
||||
) -> Self {
|
||||
GatewayClient {
|
||||
authenticated: false,
|
||||
@@ -135,7 +135,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS,
|
||||
reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF,
|
||||
negotiated_protocol: None,
|
||||
shutdown,
|
||||
task_client,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = self.shutdown.recv() => {
|
||||
_ = self.task_client.recv() => {
|
||||
log::trace!("GatewayClient control response: Received shutdown");
|
||||
log::debug!("GatewayClient control response: Exiting");
|
||||
break Err(GatewayClientError::ConnectionClosedGatewayShutdown);
|
||||
@@ -540,6 +540,9 @@ impl<C, St> GatewayClient<C, St> {
|
||||
self.bandwidth_remaining = bandwidth_remaining;
|
||||
self.negotiated_protocol = protocol_version;
|
||||
log::debug!("authenticated: {status}, bandwidth remaining: {bandwidth_remaining}");
|
||||
self.task_client.send_status_msg(Box::new(
|
||||
BandwidthStatusMessage::RemainingBandwidth(bandwidth_remaining),
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
ServerResponse::Error { message } => Err(GatewayClientError::GatewayError(message)),
|
||||
@@ -805,7 +808,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
.as_ref()
|
||||
.expect("no shared key present even though we're authenticated!"),
|
||||
),
|
||||
self.shutdown.clone(),
|
||||
self.task_client.clone(),
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@@ -879,8 +882,8 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
// perfectly fine here, because it's not meant to be used
|
||||
let (ack_tx, _) = mpsc::unbounded();
|
||||
let (mix_tx, _) = mpsc::unbounded();
|
||||
let shutdown = TaskClient::dummy();
|
||||
let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone());
|
||||
let task_client = TaskClient::dummy();
|
||||
let packet_router = PacketRouter::new(ack_tx, mix_tx, task_client.clone());
|
||||
|
||||
GatewayClient {
|
||||
authenticated: false,
|
||||
@@ -898,7 +901,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS,
|
||||
reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF,
|
||||
negotiated_protocol: None,
|
||||
shutdown,
|
||||
task_client,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -906,7 +909,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
self,
|
||||
packet_router: PacketRouter,
|
||||
bandwidth_controller: Option<BandwidthController<C, St>>,
|
||||
shutdown: TaskClient,
|
||||
task_client: TaskClient,
|
||||
) -> GatewayClient<C, St> {
|
||||
// invariants that can't be broken
|
||||
// (unless somebody decided to expose some field that wasn't meant to be exposed)
|
||||
@@ -930,7 +933,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
reconnection_attempts: self.reconnection_attempts,
|
||||
reconnection_backoff: self.reconnection_backoff,
|
||||
negotiated_protocol: self.negotiated_protocol,
|
||||
shutdown,
|
||||
task_client,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-3
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::nyxd::cosmwasm_client::client_traits::CosmWasmClient;
|
||||
use crate::nyxd::cosmwasm_client::helpers::{compress_wasm_code, CheckResponse};
|
||||
use crate::nyxd::cosmwasm_client::logs::{self, parse_raw_logs};
|
||||
use crate::nyxd::cosmwasm_client::logs::parse_raw_logs;
|
||||
use crate::nyxd::cosmwasm_client::types::*;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER};
|
||||
@@ -19,6 +19,7 @@ use cosmrs::feegrant::{
|
||||
};
|
||||
use cosmrs::proto::cosmos::tx::signing::v1beta1::SignMode;
|
||||
use cosmrs::staking::{MsgDelegate, MsgUndelegate};
|
||||
use cosmrs::tendermint::abci::{Event, EventAttribute};
|
||||
use cosmrs::tx::{self, Msg};
|
||||
use cosmrs::{cosmwasm, AccountId, Any, Tx};
|
||||
use log::debug;
|
||||
@@ -51,6 +52,20 @@ fn single_unspecified_signer_auth(
|
||||
}
|
||||
.auth_info(empty_fee())
|
||||
}
|
||||
// Searches in events for an event of the given event type which contains an
|
||||
// attribute for with the given key.
|
||||
fn find_attribute<'a>(
|
||||
events: &'a [Event],
|
||||
event_type: &str,
|
||||
attr_key: &str,
|
||||
) -> Option<&'a EventAttribute> {
|
||||
events
|
||||
.iter()
|
||||
.find(|attr| attr.kind == event_type)?
|
||||
.attributes
|
||||
.iter()
|
||||
.find(|attr| attr.key == attr_key)
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
@@ -118,6 +133,7 @@ where
|
||||
.check_response()?;
|
||||
|
||||
let logs = parse_raw_logs(tx_res.tx_result.log)?;
|
||||
let events = tx_res.tx_result.events;
|
||||
let gas_info = GasInfo {
|
||||
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
|
||||
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
|
||||
@@ -127,7 +143,7 @@ where
|
||||
// the reason I think unwrap here is fine is that if the transaction succeeded and those
|
||||
// fields do not exist or code_id is not a number, there's no way we can recover, we're probably connected
|
||||
// to wrong validator or something
|
||||
let code_id = logs::find_attribute(&logs, "store_code", "code_id")
|
||||
let code_id = find_attribute(&events, "store_code", "code_id")
|
||||
.unwrap()
|
||||
.value
|
||||
.parse()
|
||||
@@ -140,6 +156,7 @@ where
|
||||
compressed_checksum,
|
||||
code_id,
|
||||
logs,
|
||||
events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -182,6 +199,7 @@ where
|
||||
.check_response()?;
|
||||
|
||||
let logs = parse_raw_logs(tx_res.tx_result.log)?;
|
||||
let events = tx_res.tx_result.events;
|
||||
let gas_info = GasInfo {
|
||||
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
|
||||
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
|
||||
@@ -190,7 +208,7 @@ where
|
||||
// the reason I think unwrap here is fine is that if the transaction succeeded and those
|
||||
// fields do not exist or address is malformed, there's no way we can recover, we're probably connected
|
||||
// to wrong validator or something
|
||||
let contract_address = logs::find_attribute(&logs, "instantiate", "_contract_address")
|
||||
let contract_address = find_attribute(&events, "instantiate", "_contract_address")
|
||||
.unwrap()
|
||||
.value
|
||||
.parse()
|
||||
@@ -199,6 +217,7 @@ where
|
||||
Ok(InstantiateResult {
|
||||
contract_address,
|
||||
logs,
|
||||
events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -231,6 +250,7 @@ where
|
||||
};
|
||||
Ok(ChangeAdminResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -261,6 +281,7 @@ where
|
||||
};
|
||||
Ok(ChangeAdminResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -298,6 +319,7 @@ where
|
||||
};
|
||||
Ok(MigrateResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -335,6 +357,7 @@ where
|
||||
};
|
||||
Ok(ExecuteResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
data: tx_res.tx_result.data.into(),
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
@@ -378,6 +401,7 @@ where
|
||||
};
|
||||
Ok(ExecuteResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
data: tx_res.tx_result.data.into(),
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
|
||||
@@ -9,16 +9,12 @@ pub use nym_coconut_bandwidth_contract_common::event_attributes::*;
|
||||
pub use nym_coconut_dkg_common::event_attributes::*;
|
||||
|
||||
// it seems that currently validators just emit stringified events (which are also returned as part of deliverTx response)
|
||||
// as theirs logs
|
||||
// as their logs
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Log {
|
||||
#[serde(default)]
|
||||
// weird thing is that the first msg_index seems to always be undefined on the raw logs
|
||||
pub msg_index: usize,
|
||||
// unless I'm missing something obvious, the "log" type in cosmjs is always an empty string
|
||||
// and launchpad cosmos validator was setting it to what essentially is just the raw version of what
|
||||
// we received (and we don't care about launchpad, we, as the time of writing this, work on the stargate)
|
||||
// log: String,
|
||||
pub events: Vec<cosmwasm_std::Event>,
|
||||
}
|
||||
|
||||
@@ -37,8 +33,13 @@ pub fn find_attribute<'a>(
|
||||
.find(|attr| attr.key == attribute_key)
|
||||
}
|
||||
|
||||
// those two functions were separated so that the internal logic could actually be tested
|
||||
// these two functions were separated so that the internal logic could actually be tested
|
||||
fn parse_raw_str_logs(raw: &str) -> Result<Vec<Log>, NyxdError> {
|
||||
// From Cosmos SDK > 0.50 onwards, log field is not populated
|
||||
if raw.is_empty() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
let logs: Vec<Log> = serde_json::from_str(raw).map_err(|_| NyxdError::MalformedLogString)?;
|
||||
if logs.len() != logs.iter().unique_by(|log| log.msg_index).count() {
|
||||
// this check is only here because I don't yet fully understand raw log string generation and
|
||||
|
||||
@@ -232,6 +232,8 @@ pub struct UploadResult {
|
||||
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -269,6 +271,8 @@ pub struct InstantiateResult {
|
||||
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -279,6 +283,8 @@ pub struct InstantiateResult {
|
||||
pub struct ChangeAdminResult {
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -289,6 +295,8 @@ pub struct ChangeAdminResult {
|
||||
pub struct MigrateResult {
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -301,6 +309,8 @@ pub struct ExecuteResult {
|
||||
|
||||
pub data: Vec<u8>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ bytes = { workspace = true }
|
||||
nym-bin-common = { path = "../bin-common" }
|
||||
nym-crypto = { path = "../crypto" }
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
rand = "0.8.5"
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
time = { workspace = true }
|
||||
|
||||
@@ -10,8 +10,7 @@ pub use config::Config;
|
||||
pub use error::Error;
|
||||
pub use public_key::PeerPublicKey;
|
||||
pub use registration::{
|
||||
ClientMac, ClientMessage, ClientRegistrationResponse, GatewayClient, GatewayClientRegistry,
|
||||
InitMessage, Nonce,
|
||||
ClientMac, ClientMessage, GatewayClient, GatewayClientRegistry, InitMessage, Nonce,
|
||||
};
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
|
||||
@@ -7,6 +7,7 @@ use base64::{engine::general_purpose, Engine};
|
||||
use dashmap::DashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::net::IpAddr;
|
||||
use std::time::SystemTime;
|
||||
use std::{fmt, ops::Deref, str::FromStr};
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
@@ -18,13 +19,13 @@ use sha2::Sha256;
|
||||
|
||||
pub type GatewayClientRegistry = DashMap<PeerPublicKey, GatewayClient>;
|
||||
pub type PendingRegistrations = DashMap<PeerPublicKey, RegistrationData>;
|
||||
pub type PrivateIPs = DashMap<IpAddr, Free>;
|
||||
pub type PrivateIPs = DashMap<IpAddr, Taken>;
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
pub type HmacSha256 = Hmac<Sha256>;
|
||||
|
||||
pub type Nonce = u64;
|
||||
pub type Free = bool;
|
||||
pub type Taken = Option<SystemTime>;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
@@ -53,15 +54,6 @@ impl InitMessage {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub enum ClientRegistrationResponse {
|
||||
PendingRegistration(RegistrationData),
|
||||
Registered,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub struct RegistrationData {
|
||||
pub nonce: u64,
|
||||
pub gateway_data: GatewayClient,
|
||||
|
||||
@@ -3,7 +3,7 @@ title = "Nym Docs"
|
||||
authors = ["Max Hampshire, Serinko, Alexia Lorenza Martinel"]
|
||||
description = "Nym technical documentation"
|
||||
language = "en"
|
||||
multilingual = false # for the moment - ideally work on chinese, brazillian ,portugese spanish next
|
||||
multilingual = false # for the moment - ideally work on chinese, brazillian ,portugese spanish next
|
||||
src = "src"
|
||||
|
||||
[rust]
|
||||
@@ -14,17 +14,19 @@ edition = "2018"
|
||||
#################
|
||||
|
||||
[preprocessor.theme]
|
||||
sidebar-width = "280px"
|
||||
content-max-width = "70%"
|
||||
content-main-margin-left = "5%"
|
||||
content-main-margin-right = "5%"
|
||||
root-font-size = "70%"
|
||||
# DO NOT CHANGE or you might overwrite the custom hbs file
|
||||
turn-off = false
|
||||
pagetoc = true
|
||||
sidebar-width = "280px"
|
||||
content-max-width = "80%"
|
||||
root-font-size = "70%"
|
||||
# if you need to change anything in the index.hbs file you need to turn this to `false`, rebuild the book,
|
||||
# probably remove the additional `comment` that gets appended to the header, and then change this back to `true`.
|
||||
# this is because of a bug in the `mdbook-theme` plugin
|
||||
turn-off = true
|
||||
|
||||
|
||||
[preprocessor.admonish]
|
||||
command = "mdbook-admonish"
|
||||
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
|
||||
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
|
||||
|
||||
# https://gitlab.com/tglman/mdbook-variables/
|
||||
[preprocessor.variables.variables]
|
||||
@@ -53,52 +55,56 @@ renderer = ["html"]
|
||||
#########
|
||||
|
||||
[build]
|
||||
build-dir = "book" # the directory where the output is placed
|
||||
create-missing = true # whether or not to create missing pages
|
||||
use-default-preprocessors = true # use the default preprocessors
|
||||
extra-watch-dirs = [] # directories to watch for triggering builds
|
||||
build-dir = "book" # the directory where the output is placed
|
||||
create-missing = true # whether or not to create missing pages
|
||||
use-default-preprocessors = true # use the default preprocessors
|
||||
extra-watch-dirs = [] # directories to watch for triggering builds
|
||||
|
||||
##########
|
||||
# OUTPUT #
|
||||
##########
|
||||
|
||||
[output.html]
|
||||
theme = "nym_themes"
|
||||
theme = "themes"
|
||||
default-theme = "coal"
|
||||
preferred-dark-theme = "coal"
|
||||
curly-quotes = true
|
||||
copy-fonts = true
|
||||
no-section-label = false
|
||||
additional-css = ["./nym_themes/custom.css", "./nym_themes/mdbook-admonish.css", "./nym_themes/pagetoc.css"]
|
||||
additional-js = ["./nym_themes/pagetoc.js"]
|
||||
additional-css = [
|
||||
"./themes/custom.css",
|
||||
"./themes/mdbook-admonish.css",
|
||||
"./themes/pagetoc.css",
|
||||
]
|
||||
additional-js = ["./themes/pagetoc.js"]
|
||||
git-repository-url = "https://github.com/nymtech/nym"
|
||||
git-repository-icon = "fa-github"
|
||||
input-404 = "not-found.md"
|
||||
|
||||
[output.html.fold]
|
||||
enable = true # whether or not to enable section folding
|
||||
level = 0 # the depth to start folding
|
||||
enable = true # whether or not to enable section folding
|
||||
level = 0 # the depth to start folding
|
||||
|
||||
# controlling rust sample code blocks
|
||||
[output.html.playground]
|
||||
editable = false # allows editing the source code
|
||||
copyable = true # include the copy button for copying code snippets
|
||||
copy-js = true # includes the JavaScript for the code editor
|
||||
line-numbers = true # displays line numbers for editable code
|
||||
runnable = true # displays a run button for rust code
|
||||
editable = false # allows editing the source code
|
||||
copyable = true # include the copy button for copying code snippets
|
||||
copy-js = true # includes the JavaScript for the code editor
|
||||
line-numbers = true # displays line numbers for editable code
|
||||
runnable = true # displays a run button for rust code
|
||||
|
||||
# options for the built in text search
|
||||
[output.html.search]
|
||||
enable = true # enables the search feature
|
||||
limit-results = 30 # maximum number of search results
|
||||
teaser-word-count = 30 # number of words used for a search result teaser
|
||||
use-boolean-and = true # multiple search terms must all match
|
||||
boost-title = 2 # ranking boost factor for matches in headers
|
||||
boost-hierarchy = 1 # ranking boost factor for matches in page names
|
||||
boost-paragraph = 1 # ranking boost factor for matches in text
|
||||
expand = true # partial words will match longer terms
|
||||
heading-split-level = 3 # link results to heading levels
|
||||
copy-js = true # include Javascript code for search
|
||||
enable = true # enables the search feature
|
||||
limit-results = 30 # maximum number of search results
|
||||
teaser-word-count = 30 # number of words used for a search result teaser
|
||||
use-boolean-and = true # multiple search terms must all match
|
||||
boost-title = 2 # ranking boost factor for matches in headers
|
||||
boost-hierarchy = 1 # ranking boost factor for matches in page names
|
||||
boost-paragraph = 1 # ranking boost factor for matches in text
|
||||
expand = true # partial words will match longer terms
|
||||
heading-split-level = 3 # link results to heading levels
|
||||
copy-js = true # include Javascript code for search
|
||||
|
||||
[output.linkcheck]
|
||||
warning-policy = "warn"
|
||||
|
||||
@@ -1,94 +1,59 @@
|
||||
#
|
||||
# Summary
|
||||
|
||||
- [Introduction](introduction.md)
|
||||
- [Clients Overview - Start Here!](clients-overview.md)
|
||||
|
||||
# Infrastructure
|
||||
# SDKs
|
||||
- [Rust SDK](sdk/rust/rust.md)
|
||||
- [Message Types](sdk/rust/message-types.md)
|
||||
- [Message Helpers](sdk/rust/message-helpers.md)
|
||||
- [Troubleshooting](sdk/rust/troubleshooting.md)
|
||||
- [Examples](sdk/rust/examples.md)
|
||||
- [Simple Send](sdk/rust/examples/simple.md)
|
||||
- [Create and Store Keys](sdk/rust/examples/keys.md)
|
||||
- [Manual Storage](sdk/rust/examples/storage.md)
|
||||
- [Anonymous Replies](sdk/rust/examples/surbs.md)
|
||||
- [Use Custom Network Topology](sdk/rust/examples/custom-network.md)
|
||||
- [Socks Proxy](sdk/rust/examples/socks.md)
|
||||
- [Split Send and Receive](sdk/rust/examples/split-send.md)
|
||||
- [Testnet Bandwidth Cred](sdk/rust/examples/credential.md)
|
||||
- [Example Cargo file](sdk/rust/examples/cargo.md)
|
||||
- [Typescript SDK](sdk/typescript.md)
|
||||
|
||||
- [What is Nym?](infrastructure/nym.md)
|
||||
- [Nym vs Other Systems](infrastructure/nym-vs-others.md)
|
||||
- [Node Types](infrastructure/node-types.md)
|
||||
# Binaries
|
||||
- [Pre-built Binaries](binaries/pre-built-binaries.md)
|
||||
- [Building from Source](binaries/building-nym.md)
|
||||
|
||||
# Quickstart
|
||||
# Standalone Clients
|
||||
- [Websocket Client](clients/websocket-client.md)
|
||||
- [Setup & Run](clients/websocket/setup.md)
|
||||
- [Configuration](clients/websocket/config.md)
|
||||
- [Using Your Client](clients/websocket/usage.md)
|
||||
- [Examples](clients/websocket/examples.md)
|
||||
- [Socks5 Client](clients/socks5-client.md)
|
||||
- [Setup & Run](clients/socks5/setup.md)
|
||||
- [Using Your Client](clients/socks5/usage.md)
|
||||
- [Webassembly Client](clients/webassembly-client.md)
|
||||
|
||||
- [Overview](quickstart/overview.md)
|
||||
- [Chat demo (webapp)](quickstart/chat-demo.md)
|
||||
- [Coconut Credential Playground (webapp)](quickstart/cred-playground.md)
|
||||
- [SOCKS Proxy (CLI)](quickstart/socks-proxy.md)
|
||||
|
||||
# User Manuals
|
||||
|
||||
- [NymVPN alpha](nymvpn/intro.md)
|
||||
- [CLI](nymvpn/cli.md)
|
||||
|
||||
<!-- OUTDATED STUFF:
|
||||
- [NymConnect X Monero](tutorials/monero.md)
|
||||
- [NymConnect X Matrix](tutorials/matrix.md)
|
||||
- [NymConnect X Telegram](tutorials/telegram.md)
|
||||
- [NymConnect X Electrum](tutorials/electrum.md)
|
||||
- [NymConnect X Firo wallet](tutorials/firo.md)
|
||||
-->
|
||||
# Tutorials
|
||||
- [Stub: Updates Coming Soon!](./tutorials/coming-soon.md)
|
||||
|
||||
# Code Examples
|
||||
|
||||
- [Custom Service Providers](examples/custom-services.md)
|
||||
- [Apps Using Network Requesters](examples/using-nrs.md)
|
||||
- [Browser only](examples/browser-only.md)
|
||||
- [Monorepo examples](examples/monorepo-examples.md)
|
||||
|
||||
# Integrations
|
||||
|
||||
- [Integration Options](integrations/integration-options.md)
|
||||
[//]: # (- [Mixnet Integration](integrations/mixnet-integration.md))
|
||||
- [Payment Integration](integrations/payment-integration.md)
|
||||
|
||||
# Tutorials
|
||||
|
||||
- [Rust SDK](tutorials/rust-sdk.md)
|
||||
- [Blockchain Service pt1](tutorials/cosmos-service/intro.md)
|
||||
- [Tutorial Overview](tutorials/cosmos-service/overview.md)
|
||||
- [Preparing Your Environment](tutorials/cosmos-service/preparing-env.md)
|
||||
- [Preparing Your Lib](tutorials/cosmos-service/lib.md)
|
||||
- [Preparing Your Client](tutorials/cosmos-service/client.md)
|
||||
- [Preparing Your Client pt2](tutorials/cosmos-service/client-src.md)
|
||||
- [Preparing Your Service](tutorials/cosmos-service/service.md)
|
||||
- [Preparing Your Service pt2](tutorials/cosmos-service/service-src.md)
|
||||
- [Querying the Chain](tutorials/cosmos-service/querying.md)
|
||||
|
||||
- [Typescript](tutorials/typescript.md)
|
||||
- [Simple Service Provider](tutorials/simple-service-provider/simple-service-provider.md)
|
||||
- [Tutorial Overview](tutorials/simple-service-provider/overview.md)
|
||||
- [Preparing Your User Client Environment](tutorials/simple-service-provider/preparating-env.md)
|
||||
- [Building Your User Client](tutorials/simple-service-provider/user-client.md)
|
||||
- [Preparing Your Service Provider Environment](tutorials/simple-service-provider/preparating-env2.md)
|
||||
- [Building Your Service Provider](tutorials/simple-service-provider/service-provider.md)
|
||||
- [Sending a Message Through the Mixnet](tutorials/simple-service-provider/sending-message.md)
|
||||
|
||||
[//]: # (TODO make generic )
|
||||
[//]: # (# Shipyard Builders Hackathon 2023 )
|
||||
[//]: # (- [General Info & Resources](shipyard/general.md))
|
||||
[//]: # (- [Hackathon Challenges](shipyard/challenges-overview.md))
|
||||
[//]: # (- [A Note on Infrastructure](shipyard/infra.md))
|
||||
[//]: # (- [Submission Guidelines](shipyard/guidelines.md))
|
||||
|
||||
<!-- Commenting out as a lot of the stuff is deprecated, can be purged as a part of the large overhaul
|
||||
# Events
|
||||
|
||||
- [Web3Privacy Now](./events/web3-privacy.md)
|
||||
- [HCPP23-serinko](./events/hcpp23-serinko.md)
|
||||
- [HCPP23-max](./events/hcpp23-max.md)
|
||||
-->
|
||||
|
||||
# FAQ
|
||||
- [General](faq/general-faq.md)
|
||||
- [Integrations](faq/integrations-faq.md)
|
||||
- [Rewards & Token](faq/rewards-faq.md)
|
||||
|
||||
# Community Resources
|
||||
|
||||
- [Nym DevRel AMAs](community-resources/ama.md)
|
||||
- [Community Applications and Guides](community-resources/community-applications-and-guides.md)
|
||||
- [Change Service Grantee Information](info-request.md)
|
||||
# User Manuals
|
||||
- [NymVPN alpha](nymvpn/intro.md)
|
||||
- [CLI](nymvpn/cli.md)
|
||||
|
||||
---
|
||||
# Misc.
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# 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.
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
Quite a bit of stuff gets built. The key working parts for devs are the Client binaries and the CLI tool:
|
||||
|
||||
* [websocket client](../clients/websocket-client.md): `nym-client`
|
||||
* [socks5 client](../clients/socks5-client.md): `nym-socks5-client`
|
||||
* [nym-cli tool](https://nymtech.net/docs/tools/nym-cli.md): `nym-cli`
|
||||
|
||||
> 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.
|
||||
@@ -0,0 +1,6 @@
|
||||
# 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.
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# Clients Overview
|
||||
|
||||
A large proportion of the Nym mixnet's functionality is implemented client-side.
|
||||
|
||||
Clients perform the following actions on behalf of users:
|
||||
|
||||
* determine network topology - what mixnodes exist, what their keys are, etc.
|
||||
* register with a gateway
|
||||
* authenticate with a gateway
|
||||
* receive and decrypt messages from the gateway
|
||||
* create layer-encrypted Sphinx packets
|
||||
* send Sphinx packets with real messages
|
||||
* send Sphinx packet _cover traffic_ when no real messages are being sent
|
||||
* retransmit un-acknowledged packet sends - if a client sends 100 packets to a gateway, but only receives an acknowledgement ('ack') for 95 of them, it will resend those 5 packets to the gateway again, to make sure that all packets are received.
|
||||
|
||||
> As a developer, you'll want to use a Nym client to send your application network traffic through the mixnet; whether that is an RPC call, a TCP connection request, or treating it like a UDP pipe, you need to send whatever bytes your app needs to send through it. However, unlike (e.g.) a TCP Socket, Nym client communication is message-based, so you cannot (yet) simply plug-and-play using the mixnet as a seamless drop-in replacement. We are currently working on stream-like abstractions for ease of integration with the Rust SDK.
|
||||
|
||||
## Types of Nym clients
|
||||
At present, there are three Nym clients:
|
||||
|
||||
- the websocket (native) client
|
||||
- the SOCKS5 client
|
||||
- the wasm (webassembly) client
|
||||
|
||||
You need to choose which one you want incorporate into your app. Which one you use will depend largely on your preferred programming style and the purpose of your app.
|
||||
|
||||
### The websocket client
|
||||
Your first option is the native websocket client (`nym-client`). This is a compiled program that can run on Linux, Mac OS X, and Windows machines. It can be run as a persistent process on a desktop or server machine. You can connect to it with **any language that supports websockets**.
|
||||
|
||||
> Rust developers can import websocket client functionality into their code via the [Rust SDK](sdk/rust/rust.md).
|
||||
|
||||
### The webassembly client
|
||||
If you're working in JavaScript or Typescript in the browser, or building an [edge computing](https://en.wikipedia.org/wiki/Edge_computing) app, you'll likely want to choose the webassembly client.
|
||||
|
||||
It's packaged and [available on the npm registry](https://www.npmjs.com/package/@nymproject/nym-client-wasm), so you can `npm install` it into your JavaScript or TypeScript application.
|
||||
|
||||
> The webassembly client is most easily used via the [Typescript SDK](sdk/typescript.md). Typescript developers who wish to send API requests through the mixnet can can also check the [`mixfetch`]() package.
|
||||
|
||||
### The SOCKS5 client
|
||||
The `nym-socks5-client` is useful for allowing existing applications to use the Nym mixnet without any code changes. All that's necessary is that they can use one of the SOCKS5, SOCKS4a, or SOCKS4 proxy protocols (which many applications can - crypto wallets, browsers, chat applications etc).
|
||||
|
||||
When used as a standalone client, it's less flexible as a way of writing custom applications than the other clients, but able to be used to proxy application traffic through the mixnet without having to make any code changes.
|
||||
|
||||
> Rust developers can import socks client functionality into their code via the [Rust SDK](sdk/rust/rust.md).
|
||||
|
||||
## Commonalities between clients
|
||||
All Nym client packages present basically the same capabilities to the privacy application developer. They need to run as a persistent process in order to stay connected and ready to receive any incoming messages from their gateway nodes. They register and authenticate to gateways, and encrypt Sphinx packets.
|
||||
|
||||
|
||||
+2
-2
@@ -25,14 +25,14 @@ You need to choose which one you want incorporate into your app. Which one you u
|
||||
### The websocket client
|
||||
Your first option is the native websocket client (`nym-client`). This is a compiled program that can run on Linux, Mac OS X, and Windows machines. It can be run as a persistent process on a desktop or server machine. You can connect to it with **any language that supports websockets**.
|
||||
|
||||
_Rust developers can import websocket client functionality into their code via the [Rust SDK](../sdk/rust/rust.md)_.
|
||||
> Rust developers can import websocket client functionality into their code via the [Rust SDK](../sdk/rust/rust.md).
|
||||
|
||||
### The webassembly client
|
||||
If you're working in JavaScript or Typescript in the browser, or building an [edge computing](https://en.wikipedia.org/wiki/Edge_computing) app, you'll likely want to choose the webassembly client.
|
||||
|
||||
It's packaged and [available on the npm registry](https://www.npmjs.com/package/@nymproject/nym-client-wasm), so you can `npm install` it into your JavaScript or TypeScript application.
|
||||
|
||||
_The webassembly client is most easily used via the [Typescript SDK](../sdk/typescript.md)_.
|
||||
> The webassembly client is most easily used via the [Typescript SDK](../sdk/typescript.md). Typescript developers who wish to send API requests through the mixnet can can also check the [`mixfetch`]() package.
|
||||
|
||||
### The SOCKS5 client
|
||||
The `nym-socks5-client` is useful for allowing existing applications to use the Nym mixnet without any code changes. All that's necessary is that they can use one of the SOCKS5, SOCKS4a, or SOCKS4 proxy protocols (which many applications can - crypto wallets, browsers, chat applications etc).
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
# Socks5 Client
|
||||
|
||||
> 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.
|
||||
> 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
|
||||
```
|
||||
@@ -60,7 +60,7 @@ There are 2 pieces of software that work together to send SOCKS traffic through
|
||||
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 mixnet to a [network requester](../nodes/network-requester.md). Packets are shuffled and mixed as they transit the mixnet.
|
||||
* Send the Sphinx packets through the mixnet to a [network requester](https://nymtech.net/operators/nodes/network-requester.md). 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!
|
||||
|
||||
@@ -100,11 +100,11 @@ Before you can use the client, you need to initalise a new instance of it, which
|
||||
|
||||
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](../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](../nodes/network-requester.md).
|
||||
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 `--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](../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 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/).
|
||||
|
||||
Since the nodes on this list are the infrastructure for [Nymconnect](https://nymtech.net/developers/quickstart/nymconnect-gui.html) they will support all apps on the [default whitelist](../nodes/network-requester.md#network-requester-whitelist): Keybase, Telegram, Electrum, Blockstream Green, and Helios.
|
||||
Since the nodes on this list are the infrastructure for [Nymconnect](https://nymtech.net/developers/quickstart/nymconnect-gui.html) they will support all apps on the [default whitelist](https://nymtech.net/operators/nodes/network-requester.md#network-requester-whitelist): Keybase, Telegram, Electrum, Blockstream Green, and Helios.
|
||||
|
||||
#### Choosing a Gateway
|
||||
By default - as in the example above - your client will choose a random gateway to connect to.
|
||||
+1
-30
@@ -1,4 +1,4 @@
|
||||
# SOCKS Proxy (CLI)
|
||||
# Setup
|
||||
|
||||
> `nym-socks5-client` now also supports SOCKS4 and SOCKS4A protocols as well as SOCKS5.
|
||||
|
||||
@@ -39,33 +39,4 @@ Now your client is initialised, start it with the following:
|
||||
./nym-socks5-client run --id <ID>
|
||||
```
|
||||
|
||||
## 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:
|
||||
|
||||

|
||||
|
||||
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
|
||||
- ircd chat
|
||||
- Blockstream Green
|
||||
|
||||
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).
|
||||
@@ -0,0 +1,33 @@
|
||||
# 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:
|
||||
|
||||

|
||||
|
||||
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).
|
||||
+2
-2
@@ -11,7 +11,7 @@ There are a number of message types that you can send up the websocket as define
|
||||
```
|
||||
|
||||
## 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 - see [here](../addressing-system.md) for more on Nym's addressing scheme). 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:
|
||||
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 - see [here](https://nymtech.net/docs/architecture/addressing-system.md) for more on Nym's addressing scheme). 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
|
||||
{
|
||||
@@ -58,7 +58,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](../../architecture/traffic-flow.md#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](https://nymtech.net/docs/architecture/traffic-flow.md#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**.
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# DevRel AMAs
|
||||
|
||||
The Nym Technology Developer Relations AMA (Ask Me Anything) is an event organised by the Nym team to engage and connect with the developer community as well as answer any questions that they may have.
|
||||
|
||||
> ⚠️ Hosted every fortnight on Wednesday @ 4pm UTC
|
||||
|
||||
Archives of these calls can be found [here](https://www.youtube.com/watch?v=0kVXR7aNOyg&list=PLoc3wV2YJYwohgwzf5IinyebV4GGYsa9K).
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
# Community Applications
|
||||
|
||||
If you would like to share your application here, please submit a pull request to the `main` branch of the `nymtech/dev-portal` [repository](https://github.com/nymtech/dev-portal).
|
||||
|
||||
## <img src='../images/profile_picture/pastenym_ntv_pp.png' style="float: right; width: 75px; height: 75px;">Pastenym
|
||||
|
||||
>A [pastebin](https://pastebin.com) inspired project, offer a solution for sharing text with Nym products to offer full anonymity, even on metadata level.
|
||||
|
||||
* [Github](https://github.com/notrustverify/pastenym)
|
||||
* [Deployed App](https://pastenym.ch)
|
||||
|
||||
|
||||
|
||||
|
||||
## <img src='../images/profile_picture/pineappleproxy_pp.png' style="float: right; width: 75px; height: 75px;">Nostr-Nym
|
||||
|
||||
> [Nostr-nym](https://github.com/notrustverify/nostr-nym) offer a solution to use [Nostr](https://nostr.how/en/what-is-nostr) protocol by giving the possibility to run a relay on mixnet. By using a nostr client compatible with the mixnet, users can protect their privacy to be able to use Nostr has the want, without being observed.
|
||||
|
||||
* [Github](https://github.com/notrustverify/nostr-nym)
|
||||
* [Deployed App](https://nostrnym.pnproxy.org/)
|
||||
* [Documentation](https://blog.notrustverify.ch/nostr-relay-on-nym)
|
||||
|
||||
|
||||
|
||||
|
||||
## <img src='../images/profile_picture/ethereum_rpc_spook_pp.png' style="float: right; width: 75px; height: 75px;"> Spook
|
||||
|
||||
> Ethereum RPC request mixer uses the Nym network mixing service to anonymize RPC requests to the Ethereum network without revealing sensitive data and metadata.
|
||||
* [Github](https://github.com/EdenBlockVC/spook)
|
||||
|
||||
|
||||
|
||||
|
||||
## <img src='../images/profile_picture/ethereum_transaction_broadcaster_root_pp.png' style="float: right; width: 75px; height: 75px;"> Ethereum Transaction Broadcaster
|
||||
|
||||
> Ethereum Transaction Broadcaster that uses the Nym Mixnet to provide privacy and anonymity for transactions on the Ethereum network command-line interface.
|
||||
|
||||
* [Github](https://github.com/noot/nym-ethtx)
|
||||
|
||||
|
||||
|
||||
|
||||
## <img src='../images/profile_picture/nymdrive_saleel_pp.png' style="float: right; width: 75px; height: 75px;">NymDrive
|
||||
|
||||
> An open-source, decentralized, E2E encrypted, privacy friendly alternative to Google Drive/Dropbox, allowing for file encryption and decryption using the Nym Mixnet.
|
||||
* [Github](https://github.com/saleel/nymdrive)
|
||||
* [Demo](https://www.youtube.com/watch?v=5Rx73nw8NYI)
|
||||
* [Presentation](https://docs.google.com/presentation/d/1MpvIK32Mx9VKLVfMTcvbeyrsKHHUsTvDQ-3n31dR0NE/edit#slide=id.p)
|
||||
|
||||
|
||||
|
||||
|
||||
## <img src='../images/profile_picture/nym_dashboard_pp.svg' style="float: right; width: 75px; height: 75px;">Nym Dashboard
|
||||
|
||||
> Developed by No Trust Verify, this dashboard is a great tool to get information about the mixnet, gateways and mixnodes.
|
||||
* [Deployed App](https://status.notrustverify.ch/d/CW3L7dVVk/nym-mixnet?orgId=1)
|
||||
|
||||
|
||||
|
||||
|
||||
## <img src='../images/profile_picture/pastenym_ntv_pp.png' style="float: right; width: 75px; height: 75px;">Is Nym Up
|
||||
|
||||
> Explore whether we're up through IsNymUp, a tool that helps check the heath of the Nym network as well as some mixnet related statistics!
|
||||
* [Deployed App](https://isnymup.com/)
|
||||
|
||||
|
||||
|
||||
|
||||
## <img src='../images/profile_picture/darkfi_over_nym_pp.png' style="float: right; width: 75px; height: 75px;">DarkFi over Nym
|
||||
|
||||
> DarkFi leverages Nym's mixnet as a pluggable transport for IRCD, their p2p IRC variant. Users can anonymously connect to peers over the network, ensuring secure and private communication within the DarkFi ecosystem.
|
||||
* [Github](https://github.com/darkrenaissance/darkfi)
|
||||
* [Documentation](https://darkrenaissance.github.io/darkfi/clients/nym_outbound.html)
|
||||
|
||||
|
||||
|
||||
|
||||
## <img src='../images/profile_picture/nymstr_email_pp.png' style="float: right; width: 75px; height: 75px;">Nymstr email
|
||||
|
||||
> Experience secure and private email communication with ease using Nymstr email, which enables seamless transmission of emails over a SOCKS5 proxy and our NYM mixnet!
|
||||
* [Github](https://github.com/dial0ut/nymstr-email)
|
||||
|
||||
|
||||
|
||||
|
||||
## <img src='../images/profile_picture/minibolt_pp.png' style="float: right; width: 75px; height: 75px;">Minibolt
|
||||
|
||||
> Proxies the clearnet connections of a Bitcoin node and its associated tools using the NYM mixnet.
|
||||
* [Github](https://github.com/minibolt-guide/minibolt)
|
||||
* [Documentation](https://v2.minibolt.info/bonus-guides/system/nym-mixnet#proxying-bitcoin-core)
|
||||
|
||||
|
||||
|
||||
## <img src='../images/profile_picture/nymgraph_pp.png' style="float: right; width: 75px; height: 75px;">NymGraph
|
||||
|
||||
> NymGraph is a graphical chat client for Nym running on Ubuntu and Debian. Test it to chat over the Nym network!
|
||||
* [Github](https://github.com/Tyz3/nymgraph)
|
||||
|
||||
|
||||
|
||||
|
||||
<br/> <br/>
|
||||
|
||||
# Community Guides
|
||||
|
||||
We aren't the only ones writing documentation: the Nym developer community is also a great source of guides and resources, some of which we've included here.
|
||||
|
||||
## <img src='../images/profile_picture/pastenym_ntv_pp.png' style="float: right; width: 75px; height: 75px;"> No Trust Verify
|
||||
|
||||
>No Trust Verify is a project that aims to build open-source, privacy-enhancing technologies that make it easier to use the Internet securely and anonymously. Their focus is on providing tools and services that make it simple for developers to create decentralized applications (dApps) that respect users' privacy.
|
||||
|
||||
* [Awesome Nym list](https://notrustverify.github.io/awesome-nym/) ([GitHub](https://github.com/notrustverify/awesome-nym))
|
||||
* A lot of guides can be found on the [NTV Blog](https://blog.notrustverify.ch/)
|
||||
|
||||
|
||||
## <img src='../images/profile_picture/pineappleproxy_pp.png' style="float: right; width: 75px; height: 75px;">The Way of the NYMJA
|
||||
|
||||
by Pineapple Proxy🍍
|
||||
|
||||
>Born out of a study group from Nym's Shipyard Academy, Pineapple Proxy has emerged as a cluster of motivated and skilled individuals who see the new internet taking shape. With vibecare at the heart of their approach, this zesty collective is on a mission to make privacy convenient for everyone via content, new tools, events, and novel experiences. They believe in collective intelligence, empathy, and collaboration as the means by which privacy will become a meaningful reality.
|
||||
* [Website](https://pnproxy.org/welcome.html) ([GitHub](https://github.com/Pineapple-Proxy-DAO/web))
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# Forums
|
||||
|
||||
Welcome to our page dedicated to providing you with links to open forums discussing privacy-enhancing technologies, as well as general privacy topics. These forums are a great place to learn more about the latest developments in privacy technology, as well as to connect with other individuals who are passionate about protecting their online privacy. Whether you're new to the world of privacy or an experienced user, you're sure to find valuable information and resources on these forums.
|
||||
|
||||
|
||||
🚧 coming soon 🚧
|
||||
@@ -1,6 +1,9 @@
|
||||
# Browser only
|
||||
With the Typescript SDK you can run a Nym client in a webworker - meaning you can connect to the mixnet through the browser without having to worry about any other code than your web framework.
|
||||
|
||||
- Oreowallet have integrated `mixFetch` into their browser-extension wallet to run transactions through the mixnet.
|
||||
- [Codebase](https://github.com/oreoslabs/oreowallet-extension/tree/mixFetch)
|
||||
|
||||
- [NoTrustVerify](https://notrustverify.ch/) have set up an example application using [`mixFetch`](https://sdk.nymtech.net/examples/mix-fetch) to fetch crypto prices from CoinGecko over the mixnet.
|
||||
- [Website](https://notrustverify.github.io/mixfetch-examples/)
|
||||
- [Codebase](https://github.com/notrustverify/mixfetch-examples)
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
# Custom Services
|
||||
Custom services involve two pieces of code that communicate via the mixnet: a client, and a custom server/service. This custom service will most likely interact with the wider internet / a clearnet service on your behalf, with the mixnet between you and the service, acting as a privacy shield.
|
||||
|
||||
> The current model of relying on a Service Provider has some issues, such as additional complexity in deployment and maintenance, as well as creating potential chokepoints for app traffic. Work is going on (in the open in our [monorepo](https://github.com/nymtech/nym) ofc) to start removing this requirement as much as possible, by allowing for the creation of packet-contents in such a way that the existing Network Requester/Exit Gateway infrastructure can support network requests in a similar way to `mixFetch`. More on this as and when it is released.
|
||||
|
||||
- [Nym Zcash RPC demo](https://github.com/nymtech/nym-zcash-rpc-demo), although used to only pipe RPC traffic, is a proof of concept 'generic' mixnet piping example which exposes a TPC Socket on the client side for incoming traffic, pipes this through the mixnet, and then streams TCP packets 'out' the other side. A good example of non-app-specific traffic transport which developers could also quite easily use as a template for their own app-specific work.
|
||||
- [Codebase](https://github.com/nymtech/nym-zcash-rpc-demo)
|
||||
|
||||
- PasteNym is a private pastebin alternative. It involves a browser-based frontend utilising the Typescript SDK and a Python-based backend service communicating with a standalone Nym Websocket Client. **If you're a Python developer, start here!**.
|
||||
- [Frontend codebase](https://github.com/notrustverify/pastenym)
|
||||
- [Backend codebase](https://github.com/notrustverify/pastenym-frontend)
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
# Nym General FAQ
|
||||
|
||||
> If you have questions which are not answered below, please share them at our [DevRel AMAs](../community-resources/ama.md) or seek support in [Nym's community](https://nymtech.net/community)
|
||||
|
||||
### What is Nym?
|
||||
|
||||
Nym is a privacy platform that secures user data and protects against surveillance at the network level.
|
||||
|
||||
The platform does so by leveraging different technological components:
|
||||
|
||||
- **Nym Mixnet**, a type of overlay network that makes both content and metadata of transactions private through mixing, network-level obfuscation and incentivisation (using Sphinx);
|
||||
- A blockchain called **Nyx**, our Cosmos SDK blockchain, to allow for us to use payment tokens in the form of NYM, as well as smart contracts, in order to create a robust, decentralized, and secure environment incentives for the Mixnet;
|
||||
- **Coconut**, a zero-knowledge signature scheme, that creates an application-level private access control layer to power Zk-Nyms;
|
||||
- A utility token **NYM**, to pay for usage, measure reputation and serve as rewards for the privacy infrastructure.
|
||||
|
||||
Simply put, the [Nym network ("Nym")](https://www.feat-nym-update-nym-web.websites.dev.nymte.ch/nym-whitepaper.pdf) is a decentralized and incentivized infrastructure to provision privacy to a broad range of message-based applications and services. Think of it as a [*"Layer 0" privacy infrastructure*](https://blog.nymtech.net/nym-layer-0-privacy-infrastructure-for-the-whole-internet-e53238f9b8e7) for the entire internet.
|
||||
|
||||
**Related articles:**
|
||||
- [*Nym is not a blockchain, but is powered by one*](https://blog.nymtech.net/nym-is-not-a-blockchain-but-it-is-powered-by-one-4bb16ef16587)
|
||||
- [*Nym tokens*](https://blog.nymtech.net/nym-tokens-where-do-they-live-and-how-are-they-distributed-cross-chain-8d134bf9c41f)
|
||||
- [*A breakdown of the smart contracts that run the Nym token economics*](https://blog.nymtech.net/a-breakdown-of-the-smart-contracts-that-run-the-nym-token-economics-3a61b4139f95)
|
||||
- [*Zk-Nyms are here*](https://blog.nymtech.net/a-breakdown-of-the-smart-contracts-that-run-the-nym-token-economics-3a61b4139f95)
|
||||
- [*Sphinx: the anonymous data format that powers Nym*](https://blog.nymtech.net/sphinx-tl-dr-the-data-packet-that-can-anonymize-bitcoin-and-the-internet-18d152c6e4dc)
|
||||
|
||||
|
||||
### What's the difference between Nym and VPNs?
|
||||
|
||||
Nym is not an onion routing system, it is not a decentralized VPN - it’s much more than that. Nym is a mixnet meant to stop precisely the traffic analysis attacks that Tor and dVPNs are vulnerable to.
|
||||
|
||||
It is an orthogonal design that maintains better privacy and can support anonymity, although usually with a cost in terms of latency.
|
||||
It basically is an infrastructure on which privacy preserving apps can be built, leveraging the Mixnet and Coconut credentials, amongst others.
|
||||
The **Nym mixnet and VPNs differ** because VPNs do not mix nor do they protect metadata from an adversary who may be able to watch the entire network.
|
||||
|
||||
**Related articles:**
|
||||
- [*VPNs, Tor, I2P, how does Nym compare? *](https://blog.nymtech.net/vpns-tor-i2p-how-does-nym-compare-8576824617b8)
|
||||
|
||||
|
||||
### What is Nym’s VPN?
|
||||
|
||||
Since Q2 2023 the Nym core team has been working on launching the **first major consumer facing product** that runs on top of the Nym mixnet: a high speed, trustless and decentralized VPN, paid for via the NYM token - facilitating anonymous payments if wished.
|
||||
The product positions itself as a full-network protection service available across all of a user’s devices, **leveraging the Nym Mixnet** and other primitives to offer split tunneling and traffic obfuscation techniques to protect against censorship.
|
||||
|
||||
**Related articles:**
|
||||
- [*What does it take to build the most powerful VPN?*](https://blog.nymtech.net/what-does-it-take-to-build-the-worlds-most-powerful-vpn-d351a76ec4e6)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 364 KiB |
@@ -1,5 +1,5 @@
|
||||
# Integration Options
|
||||
If you've already gone through the different [Quick Start](../quickstart/overview.md) options and had a look at the tutorials, you have seen the possibilities available to you for quickly connecting existing application code to another Nym process.
|
||||
If you've already gone through the different options and had a look at the tutorials, you have seen the possibilities available to you for quickly connecting existing application code to another Nym process.
|
||||
|
||||
Below are a resources that will be useful for either beginning to integrate mixnet functionality into existing application code or build a new app using Nym.
|
||||
|
||||
@@ -7,8 +7,6 @@ Below are a resources that will be useful for either beginning to integrate mixn
|
||||
|
||||
- The [integrations FAQ](../faq/integrations-faq.md) has a list of common questions regarding integrating with Nym and Nyx, as well as commonly required links.
|
||||
|
||||
- To get an idea of what is possible / has already been built, check the [community applications and resources](../community-resources/community-applications-and-guides.md) page, as well as the [developer tutorials codebase](https://github.com/nymtech/developer-tutorials).
|
||||
|
||||
> If you wish to integrate with the Nyx blockchain to use `NYM` for payments, start with the [payment integration](./payment-integration.md) page.
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Chat demo (webapp)
|
||||
|
||||
You can find a browser-based 'hello world' chat app [here](https://chat-demo.nymtech.net).
|
||||
|
||||
Either open in two browser windows and send messages to yourself, or share with a friend and send messages to each other through the mixnet.
|
||||
@@ -1,5 +0,0 @@
|
||||
# Coconut Credential Playground (webapp)
|
||||
|
||||
There is a coconut-scheme based Credential Library playground [here](https://coco-demo.nymtech.net/). This is a WASM implementation of our Coconut libraries which generate raw Coconut credentials. Test it to create and re-randomize your own credentials.
|
||||
|
||||
For more information on what is happening here check out the [Coconut docs](https://nymtech.net/docs/coconut.html).
|
||||
@@ -1,22 +0,0 @@
|
||||
# NymConnect Beta (GUI)
|
||||
|
||||
NymConnect is a one-button GUI application that wraps around the `nym-socks5-client` for proxying application traffic through the Mixnet.
|
||||
|
||||
You can watch our video on getting started with NymConnect:
|
||||
|
||||
<iframe width="700" height="400" src="https://www.youtube.com/embed/quj8H2qeOwY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
|
||||
Install NymConnect and select an application that you want to privacy-enhance from the dropdown menu. For now, NymConnect can be used with Electrum Wallet, Keybase, desktop Telegram and Blockstream Green. Configure these to run via a SOCKS5 proxy and send their data through the Nym mixnet!
|
||||
|
||||
**Please note that NymConnect is currently released in beta. Please report bugs via Github**.
|
||||
|
||||
## Usage instuctions
|
||||
* [Download](https://github.com/nymtech/nym/releases/) and install NymConnect.
|
||||
* Select your service provider from the dropdown menu.
|
||||
* Click `connect` - NymConnect will connect to a service provider and its SOCKS Proxy (IP) and Port will be displayed.
|
||||
* Click on IP or Port to copy their values to the clipboard.
|
||||
* Go to your app settings and look for the network/proxy settings. Select `running via SOCKS5 proxy` and paste the IP and Port values given by NymConnect.
|
||||
|
||||
Your traffic from that application will now run through the mixnet for privacy and unlinkability!
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# Overview
|
||||
|
||||
There are multiple options to quickly connect to Nym and play with both the mixnet and credentials on the Sandbox testnet.
|
||||
|
||||
At most, these involve running Nym as a second process alongside an existing application in order to send traffic through the mixnet, most are either interact webpages or a standalone app.
|
||||
|
||||
If you've already covered the information in this section, or want to jump straight into integrating/ a Nym connection into an existing application, head to the [Integrations](../integrations/integration-options.md) section.
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
# Coconut credential generation
|
||||
The following code shows how you can use the SDK to create and use a [credential](../../../bandwidth-credentials.md) representing paid bandwidth on the Sandbox testnet.
|
||||
The following code shows how you can use the SDK to create and use a credential representing paid bandwidth on the Sandbox testnet.
|
||||
|
||||
```rust,noplayground
|
||||
{{#include ../../../../../../sdk/rust/nym-sdk/examples/bandwidth.rs}}
|
||||
```
|
||||
|
||||
You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](../../../coconut.md).
|
||||
You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](https://nymtech.net/docs/coconut.md).
|
||||
|
||||
+1
-7
@@ -1,13 +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.
|
||||
|
||||
The number of SURBs is set [here](https://github.com/nymtech/nym/blob/master/sdk/rust/nym-sdk/src/mixnet/client.rs#L33).
|
||||
|
||||
```rust,noplayground
|
||||
{{#include ../../../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:33}}
|
||||
```
|
||||
|
||||
You can read more about how SURBs function under the hood [here](../../../architecture/traffic-flow.md#private-replies-using-surbs).
|
||||
You can read more about how SURBs function under the hood [here](https://nymtech.net/docs/architecture/traffic-flow.md#private-replies-using-surbs).
|
||||
|
||||
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:
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Typescript SDK
|
||||
The Typescript SDK allows developers to start building browser-based mixnet applications quickly, by simply importing the SDK into their code via NPM as they would any other Typescript library.
|
||||
|
||||
> If you'd like to learn more, build apps or integrate Nym components using the TS SDK, please visit the **dedicated [TS SDK Handbook](https://sdk.nymtech.net/)** !
|
||||
If you'd like to learn more, build apps or integrate Nym components using the TS SDK, visit the dedicated [TS SDK Handbook](https://sdk.nymtech.net/).
|
||||
@@ -0,0 +1,11 @@
|
||||
# Stub: Updates Coming Soon!
|
||||
|
||||
There is a lot of development work ongoing with our clients; as such the old tutorials that were here got quite out of date.
|
||||
|
||||
However, you can still access the old [tutorial codebases](https://github.com/nymtech/developer-tutorials) as well as the markdown files in the `tutorial-archives/` directory in the [developer portal docs repo](https://github.com/nymtech/nym/tree/develop/documentation/dev-portal/src/tutorials) if you want.
|
||||
|
||||
More up to date tutorials will be coming soon for using RPC and gRPC, `mixfetch`, as well as using the [FFI libraries](https://github.com/nymtech/nym/tree/develop/sdk/ffi) for interacting with the Mixnet via C++ and Go.
|
||||
|
||||
> Developers who are searching for example code can use the following list as the current 'best practices':
|
||||
> * Generic traffic transport: the [`zcash-rpc-demo`](https://github.com/nymtech/nym-zcash-rpc-demo) repo, although here used to only pipe RPC traffic, is a proof of concept 'generic' mixnet piping example which exposes a TPC Socket on the client side for incoming traffic, pipes this through the mixnet, and then streams TCP packets 'out' the other side.
|
||||
> * In-browser usage: see the [browser examples](../examples/browser-only.md) page for examples using `mixFetch`.
|
||||
@@ -1,55 +0,0 @@
|
||||
# Preparing Your Client pt2
|
||||
|
||||
Open `src/client.rs`. This is where the logic of the command from the `match` statement in `bin/client.rs` is defined.
|
||||
|
||||
# Dependencies
|
||||
```rust
|
||||
use crate::{handle_response, wait_for_non_empty_message, RequestTypes, DEFAULT_VALIDATOR_RPC};
|
||||
use cosmrs::AccountId;
|
||||
use nym_sdk::mixnet::MixnetClient;
|
||||
use nym_sphinx_addressing::clients::Recipient;
|
||||
use nym_validator_client::nyxd::Coin;
|
||||
```
|
||||
|
||||
As well as importing message-handling functionality, request types, and the default RPC endpoint, this file relies on the `AccountId` type to construct blockchain addresses, the `MixnetClient` for interacting with the mixnet, the `Recipient` type to construct mixnet recipient addresses, and the `Coin` type for properly handling the returned balance of the account that will be queried.
|
||||
|
||||
# Querying via the Mixnet
|
||||
The following is used to construct a `BalanceRequest`, send this to the supplied `service` address, and then handle the response, matching it to a `ResponseType` (in this case the only expected response, a `BalanceResponse`).
|
||||
|
||||
The actual sending of the request is performed by `client.send_message`: sending the serialised `BalanceRequest` to the supplied Nym address (the `Recipient` imported from the `nym_sphinx_addressing` crate). It is sending the default number of SURBs along with the message as the third argument, defined [here](https://github.com/nymtech/nym/blob/develop/sdk/rust/nym-sdk/src/mixnet/client.rs#L34).
|
||||
|
||||
```rust
|
||||
pub async fn query_balance(
|
||||
account: AccountId,
|
||||
client: &mut MixnetClient,
|
||||
sp_address: Recipient,
|
||||
) -> anyhow::Result<Coin> {
|
||||
// construct balance request
|
||||
let message = RequestTypes::Balance(crate::BalanceRequest {
|
||||
validator: DEFAULT_VALIDATOR_RPC.to_owned(), // rpc endpoint for broadcaster to use
|
||||
account,
|
||||
});
|
||||
|
||||
// send serialised request to service via mixnet
|
||||
let _ = client
|
||||
.send_message(sp_address, message.serialize(), Default::default())
|
||||
.await;
|
||||
|
||||
let received = wait_for_non_empty_message(client).await?;
|
||||
|
||||
// listen for response from service
|
||||
let sp_response = handle_response(received)?;
|
||||
|
||||
// match JSON -> ResponseType
|
||||
let res = match sp_response {
|
||||
crate::ResponseTypes::Balance(response) => {
|
||||
println!("{:#?}", response);
|
||||
response.balance
|
||||
}
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
```
|
||||
|
||||
That is all the client code written: now to move on to the `service` that will be interacting with the blockchain on behalf of the `client`.
|
||||
@@ -1,79 +0,0 @@
|
||||
# Preparing Your Client
|
||||
|
||||
Start by creating the startup logic of your `client` in `bin/client.rs` - creating a Nym client and connecting to the mixnet (or just connecting if your client has been started before and config already exists for it), and defining and running commands.
|
||||
|
||||
## Dependencies
|
||||
Import the following dependencies:
|
||||
```rust
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
use chain_query::{client::query_balance, create_client};
|
||||
use nym_sdk::mixnet::Recipient;
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use nym_bin_common::logging::setup_logging;
|
||||
```
|
||||
|
||||
`clap` is used so different commands can be passed to the `client` (even though we're only defining one function in this first part of the tutorial, more will be added in subsequent chapters). `nym_sdk::mixnet::Recipient` is the type used to define the recipient of a mixnet message, `nym_bin_common::logging::setup_logging` is the logging setup for `client`'s Nym client, and `chain_query` imports the `create_client` and `query_balance` functions created on the previous page.
|
||||
|
||||
## CLI Command with Clap
|
||||
The following simply defines the commands that the client can perform. For the moment, there is only one: the `query_balance` function created in the previous section.
|
||||
|
||||
As with the data structures, this structure is being used for ease of adding future commands in subsequent tutorials.
|
||||
|
||||
```rust
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(name = "rust sdk demo - chain query service")]
|
||||
#[clap(about = "query the sandbox testnet blockchain via the mixnet... part 2 coming soon")]
|
||||
struct Cli {
|
||||
#[clap(subcommand)]
|
||||
command: Option<Commands>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
enum Commands {
|
||||
QueryBalance(QueryBalance),
|
||||
}
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
struct QueryBalance {
|
||||
/// the account we want to query
|
||||
account: AccountId,
|
||||
/// the address of the broadcaster service - this submits txs and queries the chain on our behalf
|
||||
sp_address: String,
|
||||
}
|
||||
```
|
||||
|
||||
## `main()`
|
||||
This is the root logic of the `client`. Using `[tokio](https://tokio.rs/)` for the async runtime, this function performs the following functions:
|
||||
* If not already existing, create a Nym client with config at `/tmp/client`. Otherwise load the already existing client from this config.
|
||||
* Matche the command from the CLI - in this instance, the `QueryBalance` function which will be defined in the next section. This creates a `BalanceRequest` and sends this to the `service`, before returning the response back to the main thread and print this to the console.
|
||||
* Perform a proper shutdown of the Nym client.
|
||||
|
||||
```rust
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
setup_logging();
|
||||
let cli = Cli::parse();
|
||||
let mut client = create_client("/tmp/client2".into()).await;
|
||||
let our_address = client.nym_address();
|
||||
println!("\nclient's nym address: {our_address}");
|
||||
|
||||
match cli.command {
|
||||
Some(Commands::QueryBalance(QueryBalance {
|
||||
account,
|
||||
sp_address,
|
||||
})) => {
|
||||
println!("\nsending bank balance request to service via mixnet");
|
||||
let sp_address = Recipient::try_from_base58_string(sp_address).unwrap();
|
||||
let returned_balance = query_balance(account, &mut client, sp_address).await?;
|
||||
println!("\nreturned balance is: {}", returned_balance);
|
||||
}
|
||||
None => {
|
||||
println!("\nno command specified - nothing to do")
|
||||
}
|
||||
}
|
||||
println!("\ndisconnecting client");
|
||||
client.disconnect().await;
|
||||
println!("client disconnected");
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
@@ -1,7 +0,0 @@
|
||||
# Interacting with a Cosmos SDK Blockchain via the Mixnet with the Rust SDK
|
||||
|
||||
This tutorial is for Rust developers wanting to interact with the Rust SDK and take a first step at building a service with which to interact with a Cosmos SDK blockchain.
|
||||
|
||||
The key here is to think of the service as a proxy: it interacts with the blockchain _on the client's behalf_, shielding the client from the Validator it interacts with, whilst also being shielded from the client by the mixnet.
|
||||
|
||||
> This service also nicely highlights the limitations of the mixnet - even though with this code your metadata is shielded from the Validator, and even the service does not know your Nym address, application-level information such as a blockchain address is not made private, in virtue of the fact that using the mixnet provides solely network-level privacy. For information on what application-level privacy Nym offers, check out the [coconut credential SDK example](https://nymtech.net/docs/sdk/rust.html#coconut-credential-generation).
|
||||
@@ -1,164 +0,0 @@
|
||||
# Preparing Your Lib
|
||||
|
||||
Now move on to preparing shared data structures and functions in `src/lib.rs`.
|
||||
|
||||
These include the request and response types the client and the service will be passing through the mixnet, as well as shared functions such as client creation, and message parsing.
|
||||
|
||||
## Dependencies
|
||||
The dependencies for the shared `lib` file are the following:
|
||||
```rust
|
||||
use anyhow::bail;
|
||||
use cosmrs::AccountId;
|
||||
use nym_sdk::mixnet::{
|
||||
AnonymousSenderTag, MixnetClient, MixnetClientBuilder, ReconstructedMessage, StoragePaths,
|
||||
};
|
||||
use nym_validator_client::nyxd::Coin;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub mod client;
|
||||
pub mod service;
|
||||
```
|
||||
|
||||
Since this is the file where client creation and message parsing are handled, the various `nym_sdk` imports, as well as `serde`'s (de)serialisation functionality, are required. `PathBuf` is for reading filepaths, `cosmrs` types are required for defining Nyx blockchain accounts, and the `Coin` type from the `nyxd_validator_client` is for our Coin balance request and response. `anyhow` is for easy error handing.
|
||||
|
||||
## Constants
|
||||
Below this are the chain-related `const` variables. These have been hardcoded for this demo.
|
||||
|
||||
```rust
|
||||
pub const DEFAULT_VALIDATOR_RPC: &str = "https://rpc.sandbox.nymtech.net";
|
||||
pub const DEFAULT_DENOM: &str = "unym";
|
||||
pub const DEFAULT_PREFIX: &str = "n";
|
||||
```
|
||||
|
||||
These define the RPC endpoint your service will use to interact with the blockchain - in this case the Sandbox testnet - as well as the expected coin denomination, and Bech32-prefix of addresses.
|
||||
|
||||
## Shared Data Structures
|
||||
Define the following structs for our different request and responses that will be serialised and sent through the mixnet between your client and service binaries:
|
||||
|
||||
```rust
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub struct BalanceRequest {
|
||||
pub validator: String,
|
||||
pub account: AccountId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub struct BalanceResponse {
|
||||
pub balance: Coin,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub enum RequestTypes {
|
||||
Balance(BalanceRequest),
|
||||
}
|
||||
|
||||
impl RequestTypes {
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
serde_json::to_vec(self).expect("serde failure")
|
||||
}
|
||||
|
||||
pub fn try_deserialize<M: AsRef<[u8]>>(raw: M) -> anyhow::Result<Self> {
|
||||
serde_json::from_slice(raw.as_ref()).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub enum ResponseTypes {
|
||||
Balance(BalanceResponse),
|
||||
}
|
||||
|
||||
impl ResponseTypes {
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
serde_json::to_vec(self).expect("serde failure")
|
||||
}
|
||||
|
||||
pub fn try_deserialize<M: AsRef<[u8]>>(raw: M) -> anyhow::Result<Self> {
|
||||
serde_json::from_slice(raw.as_ref()).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The above data types are pretty straightforward. Even though there are only one instance of a request type (sent from `client` -> mixnet -> `service`) and one of a response type (`service` -> mixnet -> `client`) so far, a pair of enums has been defined to contain additional response and request types that will be added in part 2 of this tutorial, when adding credential functionality.
|
||||
|
||||
`BalanceRequest` will be used when requesting the service to query the token balance of the supplied address on the client's behalf. You can see the information that will be returned from the chain to the service, and from the service to the client, in `BalanceResponse`.
|
||||
|
||||
Custom serialistion and deserialisation have been implemented for each enum for ease of future modification and testing.
|
||||
|
||||
## Shared Functions
|
||||
Now to define functions shared by the `client` and `service` binaries.
|
||||
|
||||
### Client Creation
|
||||
The following function is called on startup by each binary, with the `config_path` being a filepath for storing client config:
|
||||
|
||||
```rust
|
||||
// create our client with specified path for key storage
|
||||
pub async fn create_client(config_path: PathBuf) -> MixnetClient {
|
||||
let config_dir = config_path;
|
||||
let storage_paths = StoragePaths::new_from_dir(&config_dir).unwrap();
|
||||
let client = MixnetClientBuilder::new_with_default_storage(storage_paths)
|
||||
.await
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
client.connect_to_mixnet().await.unwrap()
|
||||
}
|
||||
```
|
||||
|
||||
If no config files exist at the location designated by `config_path` (in this case `/tmp/service`) then the following files are generated:
|
||||
|
||||
```sh
|
||||
service
|
||||
├── ack_key.pem
|
||||
├── db.sqlite
|
||||
├── db.sqlite-shm
|
||||
├── db.sqlite-wal
|
||||
├── gateway_details.json
|
||||
├── gateway_shared.pem
|
||||
├── persistent_reply_store.sqlite
|
||||
├── private_encryption.pem
|
||||
├── private_identity.pem
|
||||
├── public_encryption.pem
|
||||
└── public_identity.pem
|
||||
|
||||
1 directory, 11 files
|
||||
```
|
||||
|
||||
> If keys and config already exist at this location, re-running this function **will not** overwrite them.
|
||||
|
||||
### Listening for & Parsing Incoming messages
|
||||
Next to define two functions: one for listening _for_ messages from the mixnet (used by `service`), and one for handling a _response_ to a request (used by `client`).
|
||||
|
||||
Both functions attempt to deserialise the vec of `ReconstructedMessages` that are reconstructed by the client from delivered Sphinx packets after decryption.
|
||||
|
||||
`handle_request` performs one additional function - parsing the `sender_tag` from the incoming reconstructed message. This is the randomised alphanumeric string used to identify a bucket of _SURBs_ (Single Use Reply Blocks) that are sent along with any outgoing message by default. More information about them can be found [here](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs) but all that is necessary to know for now is that these are pre-addressed packets that clients send out with their messages. Any reply to their message that is to be sent back to them back be written to the payload of these packets, but without the replying party being able to see the destination that the reply is being sent to. This allows for services to **anonymously reply to clients without being able to doxx them by knowing their Nym address**.
|
||||
|
||||
```rust
|
||||
pub fn handle_response(message: ReconstructedMessage) -> anyhow::Result<ResponseTypes> {
|
||||
ResponseTypes::try_deserialize(message.message)
|
||||
}
|
||||
|
||||
pub fn handle_request(
|
||||
message: ReconstructedMessage,
|
||||
) -> anyhow::Result<(RequestTypes, Option<AnonymousSenderTag>)> {
|
||||
let request = RequestTypes::try_deserialize(message.message)?;
|
||||
Ok((request, message.sender_tag))
|
||||
}
|
||||
```
|
||||
|
||||
Before moving on to the `client` and `service` code, one more function is needed. This allows for both binaries to parse empty incoming messages that they might receive. This is necessary as incoming SURBs, as well as requests for more SURBs, contain empty data fields.
|
||||
|
||||
```rust
|
||||
pub async fn wait_for_non_empty_message(
|
||||
client: &mut MixnetClient,
|
||||
) -> anyhow::Result<ReconstructedMessage> {
|
||||
while let Some(mut new_message) = client.wait_for_messages().await {
|
||||
if !new_message.is_empty() {
|
||||
return Ok(new_message.pop().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
bail!("did not receive any non-empty message")
|
||||
}
|
||||
```
|
||||
@@ -1,29 +0,0 @@
|
||||
# Tutorial Overview
|
||||
|
||||
This tutorial involves writing two pieces of code in Rust:
|
||||
|
||||
- A client side binary used to construct a blockchain query and send this query to a service, which will query the Cosmos SDK blockchain and then pass the response back to the client (bear in mind this principle works for all blockchains - we're just utilising the `cosmrs` library to interact with the Sandbox testnet blockchain in this tutorial). This query will be to query the balance of an account, in preparation for spending these tokens on a [bandwidth credential](https://nymtech.net/docs/bandwidth-credentials.html) in a subsequent tutorial.
|
||||
- A service which will listen out for requests from the mixnet, act on those requests, and anonymously reply to the client sending the requests.
|
||||
|
||||
You will learn how to do the following with the Rust SDK:
|
||||
- Create clients with manual storage settings.
|
||||
- Parse incoming traffic from the mixnet and reply anonymously using [SURBs](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs).
|
||||
|
||||
> Services usually run on remote servers to assure reliable uptime and to unlink sender and receiver metadata. For demonstration purposes however, you will run both components on your local machine, looping messages through the mixnet to yourself.
|
||||
|
||||
You can find the code for these components [here](https://github.com/nymtech/developer-tutorials). You can use it as a reference while building or simply download it and follow along as you progress through the tutorial.
|
||||
|
||||
Notice that this tutorial attempts to use very few external libraries. This tutorial is not showing you how to build production-grade code, but **to understand how to connect and send messages to, as well as receive messages from, the mixnet.**
|
||||
|
||||
```admonish note title="Sidenote: What is a Service / Service Provider?"
|
||||
'Service' or 'Service Provider' are catchall names used to refer to any type of app that can communicate with the mixnet via a Nym client - in this case, one embedded in its app process via the Rust SDK.
|
||||
|
||||
The first SP to have been released is the [Network Requester](https://nymtech.net/docs/nodes/network-requester-setup.html) - a binary that receives a network request from the mixnet, performs that request (e.g. authenticating with a message server and receiving new messages for a user) and then passes the response back to the user who requested it anonymously, shielding their metadata from the message server.
|
||||
|
||||
The SP you will build in this tutorial is far more simple than this, showing you how to approach building something that can:
|
||||
* connect to the mixnet,
|
||||
* listen for messages, and
|
||||
* perform some action with them - in this case, query a Cosmos SDK blockchain.
|
||||
|
||||
However, once you see how easy it is to integrate with the mixnet for traffic transport, you will be able to build apps with real-world uses easily.
|
||||
```
|
||||
@@ -1,62 +0,0 @@
|
||||
# Preparing Your Environment
|
||||
|
||||
## Prerequisites
|
||||
* `Rust` & `cargo`
|
||||
|
||||
## Creating your Project Structure
|
||||
|
||||
* Make a new cargo project:
|
||||
```
|
||||
cargo new nym-cosmos-service
|
||||
```
|
||||
|
||||
* Create the following directory structure and files:
|
||||
```
|
||||
.
|
||||
├── Cargo.toml
|
||||
├── bin
|
||||
│ ├── client.rs
|
||||
│ └── service.rs
|
||||
└── src
|
||||
├── client.rs
|
||||
├── lib.rs
|
||||
└── service.rs
|
||||
|
||||
3 directories, 6 files
|
||||
```
|
||||
|
||||
* Add the following dependencies to your `Cargo.toml` file:
|
||||
```
|
||||
[dependencies]
|
||||
clap = { version = "4.0", features = ["derive"] }
|
||||
cosmrs = "=0.15.0"
|
||||
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
|
||||
serde = "1.0.152"
|
||||
serde_json = "1.0.91"
|
||||
anyhow = "1.0.72"
|
||||
```
|
||||
|
||||
These are non Nym-specific dependencies for the project. `clap` is for setting up the CLI commands, `cosmrs` for cosmos-specific types and functionality, `tokio` for the async/await environment, and `serde` for (de)serialisation. `anyhow` is for catch-all error handling.
|
||||
|
||||
* Next add Nym-specific dependencies. Since these libraries are not yet on [crates io](https://crates.io) then you need to import them from the Nym monorepo:
|
||||
```
|
||||
nym-sdk = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" }
|
||||
nym-sphinx-addressing = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" }
|
||||
nym-validator-client = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" }
|
||||
nym-bin-common = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" }
|
||||
nym-sphinx-anonymous-replies = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" }
|
||||
```
|
||||
|
||||
The `sphinx` dependencies are for packet- and address-related functionality, the `validator-client` for Nyx blockchain specific configs, `common` for client logging, and the `sdk` for SDK functionality: creating and managing client storage and connections, and sending and receiving messages to and from the mixnet.
|
||||
|
||||
* Finally add the following underneath your `[dependencies]`:
|
||||
```
|
||||
[[bin]]
|
||||
name = "client"
|
||||
path = "bin/client.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "service"
|
||||
path = "bin/service.rs"
|
||||
```
|
||||
This defines multiple binaries to run in a single cargo project, as outlined [here](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#binaries).
|
||||
@@ -1,43 +0,0 @@
|
||||
# Querying the Chain
|
||||
Now that all the code has been written, time to query the blockchain.
|
||||
|
||||
To test against the account operating one of the mix nodes on the testnet, use `n1lcutqz94k739s39u26rvexql40ehf42zd27fwe` in the following instructions:
|
||||
|
||||
```sh
|
||||
# build the binaries
|
||||
cargo build --release
|
||||
|
||||
# open two console windows. In one run the following
|
||||
./target/release/service
|
||||
|
||||
# copy the printed Nym address from the console - this is used by the client when running the chain query
|
||||
|
||||
# in the other run
|
||||
./target/release/client query-balance n1lcutqz94k739s39u26rvexql40ehf42zd27fwe <SERVICE_ADDRESS_FROM_CLIPBOARD>
|
||||
```
|
||||
|
||||
The following happens:
|
||||
* `client` and `service` both start their Nym clients and log the address. `service` is listening for incoming messages from the mixnet.
|
||||
* `client` sends a request to `service` using the supplied `n1...` address as the Nyx account to query the balance of, and the supplied Nym address to communicate with this instance of `service`.
|
||||
* `service` queries the Sandbox testnet blockchain using the `broadcaster` http client. It then serialises the response and returns it using SURBs to the `client`.
|
||||
|
||||
All in all, quite simple. By using the service as a proxy, the client never interacts with the blockchain, thus is not revealing metadata to the operator of the Validator nor any entities monitoring its incoming and outgoing traffic. Furthermore, the client doesn't even need to share its Nym address with the service, as the service is able to reply via SURBs.
|
||||
|
||||
## Creating Sandbox Account
|
||||
If you wish to create an account on Sandbox to use instead of the supplied account above, the easiest way is by building the `nym-cli` tool and using that to create one:
|
||||
|
||||
```sh
|
||||
# start from the root of the nym monorepo
|
||||
cd tools/nym-cli
|
||||
# build
|
||||
cargo build --release
|
||||
# create account using Sandbox testnet environment
|
||||
../../target/release/nym-cli --config-env-file ../../envs/sandbox.env account create
|
||||
```
|
||||
|
||||
However, since this account is fresh, it won't have any tokens. Querying the balance will still work obviously, it will just return `0`.
|
||||
|
||||
## Get Tokens
|
||||
We're working on getting the faucet up and running again in preparation for part 2 of this tutorial: using the tokens you have privately checked the balance of to generate a [bandwidth credential](https://nymtech.net/docs/bandwidth-credentials.html).
|
||||
|
||||
If you wish to get testnet tokens already then feel free to ask in the [Dev channel](https://matrix.to/#/#dev:nymtech.chat) on Matrix.
|
||||
@@ -1,45 +0,0 @@
|
||||
# Preparing Your Service pt2
|
||||
|
||||
Now to define the logic of creating the `broadcaster` for interacting with the blockchain, and querying it in `src/service.rs`.
|
||||
|
||||
## Dependencies
|
||||
The following dependencies are for creating a client to interact with the blockchain, and deal with the returned `Coin` type in `BalanceResponse`.
|
||||
|
||||
```rust
|
||||
use crate::{BalanceResponse, DEFAULT_DENOM, DEFAULT_VALIDATOR_RPC};
|
||||
use cosmrs::rpc::HttpClient;
|
||||
use cosmrs::AccountId;
|
||||
use nym_validator_client::nyxd::{Coin, CosmWasmClient};
|
||||
```
|
||||
|
||||
## Creating a `broadcaster`
|
||||
The `broadcaster` is an `HttpClient` taken from `cosmrs`, created with the `DEFAULT_VALIDATOR_RPC` as its default endpoint. The service will use this to query the Sandbox testnet chain.
|
||||
|
||||
```rust
|
||||
pub async fn create_broadcaster() -> anyhow::Result<HttpClient> {
|
||||
let broadcaster: HttpClient = HttpClient::new(DEFAULT_VALIDATOR_RPC)?;
|
||||
Ok(broadcaster)
|
||||
}
|
||||
```
|
||||
|
||||
## Querying the Chain
|
||||
Now to write the logic for querying the chain, using the `broadcaster` created in the previous step to query for the balance of the `account` that the client sent via the mixnet in the `BalanceRequest`. This function returns a `BalanceResponse` containing a `Coin` type, denoting the `balance` and `denom` returned by `get_balance()`.
|
||||
|
||||
```rust
|
||||
pub async fn get_balance(
|
||||
broadcaster: HttpClient,
|
||||
account: AccountId,
|
||||
) -> anyhow::Result<BalanceResponse> {
|
||||
let balance = broadcaster
|
||||
.get_balance(&account, DEFAULT_DENOM.to_string())
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
Ok(BalanceResponse {
|
||||
balance: Coin {
|
||||
amount: balance.amount,
|
||||
denom: balance.denom,
|
||||
},
|
||||
})
|
||||
}
|
||||
```
|
||||
@@ -1,72 +0,0 @@
|
||||
# Preparing Your Service
|
||||
In `bin/src.rs` define the startup and response logic of the `service`. Client connection / config reading happens as it does in `bin/client.rs`.
|
||||
|
||||
## Dependencies
|
||||
```rust
|
||||
use chain_query::{
|
||||
create_client, handle_request,
|
||||
service::{create_broadcaster, get_balance},
|
||||
BalanceResponse, RequestTypes, ResponseTypes,
|
||||
};
|
||||
use nym_sphinx_anonymous_replies::{self, requests::AnonymousSenderTag};
|
||||
use nym_bin_common::logging::setup_logging;
|
||||
use nym_sdk::mixnet::MixnetMessageSender;
|
||||
```
|
||||
|
||||
The imports from `chain_query` are most of the data types and functions defined in the previous sections of this tutorial.
|
||||
|
||||
The `AnonymousSenderTag` type is used for SURBs.
|
||||
|
||||
## main()
|
||||
Also using tokio for the async runtime, `main` does the following:
|
||||
* Create a Nym client with config at `/tmp/service`, or load the existing client from this config directory.
|
||||
* Create a `broadcaster` - this is used by the service to interact with the blockchain, using the consts defined in `src/lib.rs` as chain config.
|
||||
* Listen out for incoming messages, and in much the same way as the `client`, handle and match the incoming request.
|
||||
* Using the `sender_tag`, anonymously reply to the `client` with the response from the blockchain **without having to know the client's Nym address**.
|
||||
|
||||
```rust
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
setup_logging();
|
||||
let mut client = create_client("/tmp/service".into()).await;
|
||||
let our_address = client.nym_address();
|
||||
println!("\nservice's nym address: {our_address}");
|
||||
// the httpclient we will use to broadcast our query to the blockchain
|
||||
let broadcaster = create_broadcaster().await?;
|
||||
println!("listening for messages, press CTRL-C to exit");
|
||||
|
||||
while let Some(received) = client.wait_for_messages().await {
|
||||
for msg in received {
|
||||
let request = match handle_request(msg) {
|
||||
Ok(request) => request,
|
||||
Err(err) => {
|
||||
eprintln!("failed to handle received request: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let return_recipient: AnonymousSenderTag = request.1.expect("no sender tag received");
|
||||
match request.0 {
|
||||
RequestTypes::Balance(request) => {
|
||||
println!("\nincoming balance request for: {}\n", request.account);
|
||||
|
||||
let balance: BalanceResponse =
|
||||
get_balance(broadcaster.clone(), request.account).await?;
|
||||
|
||||
let response = ResponseTypes::Balance(balance);
|
||||
|
||||
println!("response from chain: {:#?}", response);
|
||||
|
||||
println!("\nreturn recipient surb bucket: {}", &return_recipient);
|
||||
println!("\nsending response to {}", &return_recipient);
|
||||
// send response back to anon requesting client via mixnet
|
||||
let _ = client
|
||||
.send_reply(return_recipient, &serde_json::to_string(&response)?)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
```
|
||||
@@ -1,36 +0,0 @@
|
||||
# Electrum Wallet NymConnect Integration
|
||||
|
||||
Electrum is one of the most favorite Bitcoin wallet for desktop users and it is used as a backend wallet for various crypto aplications in smart phones. Electrum was among the first integrations of Nym. This easy setup allows users to enhance privacy when managing the flagship of blochain cryptocurencies Bitcoin.
|
||||
|
||||
## How can I use Bitcoin over the Nym mixnet?
|
||||
|
||||
> Any syntax in `<>` brackets is a user’s unique variable. Exchange with a corresponding name without the `<>` brackets.
|
||||
|
||||
### NymConnect Installation
|
||||
|
||||
NymConnect application is for everyone who does not want to install and run `nym-socks5-client`. NymConnect is plug-and-play, fast and easy use. Electrum Bitcoin wallet, Monero wallet (desktop and CLI) and Matrix (Element app) connects through NymConnect automatically to the Mixnet.
|
||||
|
||||
1. [Download](https://nymtech.net/download/nymconnect) NymConnect
|
||||
2. On Linux and Mac, make executable by opening terminal in the same directory and run:
|
||||
|
||||
```sh
|
||||
chmod +x ./nym-connect_<VERSION>
|
||||
```
|
||||
|
||||
3. Start the application
|
||||
4. Click on `Connect` button to initialise the connection with the Mixnet
|
||||
5. Anytime you'll need to setup Host and Port in your applications, click on `IP` and `Port` to copy the values to clipboard
|
||||
6. In case you have problems such as `Gateway Issues`, try to reconnect or restart the application
|
||||
|
||||
### Electrum Bitcoin wallet via NymConnect
|
||||
|
||||
|
||||
To download Electrum visit the [official webpage](https://electrum.org/#download). To connect to the Mixnet follow these steps:
|
||||
|
||||
7. Start and connect [NymConnect](./electrum.md#nymconnect-installation) (or [`nym-socks5-client`](https://nymtech.net/docs/clients/socks5-client.html))
|
||||
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 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.
|
||||
|
||||

|
||||
@@ -1,36 +0,0 @@
|
||||
# Firo-Electrum Wallet NymConnect Integration
|
||||
|
||||
[Firo](https://github.com/firoorg/firo#firo) (formerly Zcoin) is a privacy focused, zk-proof based cryptocurrency. Now users can enjoy Firo with network privacy by Nym as Firo's fork of Electrum wallet was integrated to work behind the Mixnet. Read more about Firo on their [official webpage](https://firo.org/).
|
||||
|
||||
## How can I use Firo over the Nym Mixnet?
|
||||
|
||||
> Any syntax in `<>` brackets is a user’s unique variable. Exchange with a corresponding name without the `<>` brackets.
|
||||
|
||||
### NymConnect Installation
|
||||
|
||||
NymConnect application is for everyone who does not want to install and run `nym-socks5-client`. NymConnect is plug-and-play, fast and easy use. Electrum Bitcoin wallet, Monero wallet (desktop and CLI) and Matrix (Element app) connects through NymConnect automatically to the Mixnet.
|
||||
|
||||
1. [Download](https://nymtech.net/download/nymconnect) NymConnect
|
||||
2. On Linux and Mac, make executable by opening terminal in the same directory and run:
|
||||
|
||||
```sh
|
||||
chmod +x ./nym-connect_<VERSION>
|
||||
```
|
||||
|
||||
3. Start the application
|
||||
4. Click on `Connect` button to initialise the connection with the Mixnet
|
||||
5. Anytime you'll need to setup Host and Port in your applications, click on `IP` and `Port` to copy the values to clipboard
|
||||
6. In case you have problems such as `Gateway Issues`, try to reconnect or restart the application
|
||||
|
||||
### Firo Electrum wallet via NymConnect
|
||||
|
||||
|
||||
To download Firo Electrum wallet visit the [Firo's repository](https://github.com/firoorg/firo) or [Github release page](https://github.com/firoorg/electrum-firo/releases/tag/4.1.5.2). To connect to the Mixnet follow these steps:
|
||||
|
||||
7. Start and connect [NymConnect](./firo.md#nymconnect-installation) (or [`nym-socks5-client`](https://nymtech.net/docs/clients/socks5-client.html))
|
||||
8. Start your Firo Electrum wallet
|
||||
9. Go to: *Tools* -> *Network* -> *Proxy*
|
||||
10. Set *Use proxy* to ✅, choose `SOCKS5` from the drop-down and add the values from your NymConnect application
|
||||
11. Now your Firo Electrum wallet runs through the Mixnet and it will be connected only if your NymConnect or `nym-socks5-client` are connected.
|
||||
|
||||

|
||||
@@ -1,89 +0,0 @@
|
||||
# Matrix NymConnect Integration
|
||||
|
||||

|
||||
|
||||
Chat applications became an essential part of human communication. Matrix chat has end to end encryption on protocol level and Element app users can sort their communication into spaces and rooms. Now the Matrix communities can rely on network privacy as NymConnect supports Matrix chat protocol.
|
||||
|
||||
Currently there is no option in Matrix's Element client to set a Socks5 proxy. In order to use Element via NymConnect users have to start it from the command-line. The setup is simple, for convenience a keyboard shortcut setting or terminal alias can be easily done.
|
||||
|
||||
|
||||
## Setup & Run
|
||||
|
||||
Make sure you have installed and started **[NymConnect](https://nymtech.net/developers/quickstart/nymconnect-gui.html)** on your desktop.
|
||||
|
||||
To then start Matrix's Element client via a Socks5 proxy connected to NymConnect, open terminal and run:
|
||||
|
||||
**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
|
||||
```
|
||||
|
||||
## Optimise setup with a keybinding / alias
|
||||
|
||||
### Keybinding
|
||||
An eloquent solution to avoid entering a command every time is to setup your keybinding. Open your settings, navigate to `Keyboard Shortcuts` and choose to `Set Custom Shortcut`. `Name` and `Shortcut` fields are up to your preference, to the `Command` line add:
|
||||
|
||||
```sh
|
||||
element-desktop --proxy-server=socks5://127.0.0.1:1080
|
||||
```
|
||||
Make sure your `Shortcut` isn't already taken by something else in the menu.
|
||||
|
||||
An example can look like this.
|
||||
|
||||

|
||||
|
||||
Alternatively you can add a keybinding via the CLI, using whatever config files you edit for your given desktop environment / window manager.
|
||||
|
||||
### Create an alias
|
||||
If you prefer to simply shorten the length of the command (or all your keybindings are already taken) then you can simply create an alias for this long-winded command (this example aliases that command to the single word `element`, but you can replace it with whatever you like):
|
||||
|
||||
**Linux**
|
||||
|
||||
```sh
|
||||
alias element="element-desktop --proxy-server=socks5://127.0.0.1:1080"
|
||||
```
|
||||
|
||||
To make this alias persist, then add this to your `.bashrc` or `.zshrc` file (usually located in your `$HOME` directory) and `source` that file. This can be done by appending the alias command directly to the shell config file with one command.
|
||||
|
||||
For `bash` enter:
|
||||
|
||||
```sh
|
||||
alias element="element-desktop --proxy-server=socks5://127.0.0.1:1080" >> ~/.bashrc
|
||||
```
|
||||
|
||||
For `zsh` enter:
|
||||
|
||||
```sh
|
||||
alias element="element-desktop --proxy-server=socks5://127.0.0.1:1080" >> ~/.zshrc
|
||||
```
|
||||
|
||||
You can add the alias manually by opening your `$HOME` directory, enable hidden files (press `ctrl` + `h`) and open `.bashrc` or `.zshrc` file (based on your terminal setup) in a text editor, paste the string `alias element="element-desktop --proxy-server=socks5://127.0.0.1:1080"` to the the end, save and exit. Start a new terminal and run `element`.
|
||||
|
||||
**Mac**
|
||||
|
||||
```sh
|
||||
alias element="open -a Element --args --proxy-server=socks5://127.0.0.1:1080"
|
||||
|
||||
```
|
||||
|
||||
To make this alias persist, then add this to your `.zshrc` (or `.bashrc`/`.profile`) file (usually located in your `$HOME` directory) and `source` that file. This can be done by appending the alias command directly to the shell config file with one command.
|
||||
|
||||
For `zsh` enter:
|
||||
|
||||
```sh
|
||||
alias element="open -a Element --args --proxy-server=socks5://127.0.0.1:1080" >> ~/.zshrc
|
||||
```
|
||||
|
||||
For `.bashrc` or `.profile` just change the end of the command.
|
||||
|
||||
You can add the alias manually by opening your `$HOME` directory, enable hidden files (in Finder press `Shift` + `Command` + `.`) and open `.zshrc` file (or `.bashrc`/`.profile`) in a text editor, paste the string `alias element="open -a Element --args --proxy-server=socks5://127.0.0.1:1080"` to the the end, save and exit. Start a new terminal and run `element`.
|
||||
|
||||
|
||||
**Now you can run Element through the Nym Mixnet with a single-word command.**
|
||||
@@ -1,44 +0,0 @@
|
||||
# Monero NymConnect Integration
|
||||
|
||||
*New Nym mixnet integration launched for Monero desktop to secure the right to financial privacy and censorship-resistance*
|
||||
|
||||

|
||||
|
||||
Financial privacy is an important component of digital currencies and the use of Nym will provide users with the highest level of privacy at the infrastructure level. All users of digital currencies should be afforded equal rights to protection from financial surveillance.
|
||||
|
||||
A team made up of Monero community members have successfully set up a service provider to use Monero (using the Monero desktop wallet) over the Nym mixnet. This allows Monero users to easily use NymConnect to run Monero over the mixnet, thereby enhancing the privacy of Monero transactions.
|
||||
|
||||
## How can I use Monero over the Nym mixnet?
|
||||
|
||||
> Any syntax in `<>` brackets is a user's unique variable. Exchange with a corresponding name without the `<>` brackets.
|
||||
|
||||
The mainnet service provider to Monero over the Nym mixnet is now ready for use via [NymConnect](https://nymtech.net/download-nymconnect/).
|
||||
|
||||
* **Download** the latest version of [**NymConnect**](https://nymtech.net/download-nymconnect/).
|
||||
* Make sure your NymConnect is executable.
|
||||
```sh
|
||||
# in Linux open terminal in the same folder and run:
|
||||
chmod +x ./nym-connect_<YOUR_VERSION>.AppImage
|
||||
```
|
||||
* **Open NymConnect app**
|
||||
* **Turn it on** - Monero wallet is listed in the apps supported by default, no need for any setup
|
||||
* **Copy** the **Socks5 address** and **Port**
|
||||
|
||||
Then go to your Monero wallet (desktop or CLI) and change the settings to run over socks5 proxy:
|
||||
|
||||
**Monero desktop wallet:**
|
||||
|
||||
* Settings -> Interface -> Socks5 proxy -> Add values: IP address `127.0.0.1`, Port `1080` (the values copied from NymConnect)
|
||||
|
||||
<!---commenting the video as it has a redundant part about manual NR setup
|
||||
<iframe width="700" height="400" src="https://www.youtube.com/embed/oSHnk1BG_f0" title="Demo: Connect Your Monero Wallet to the Nym Mixnet via NymConnect" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
--->
|
||||
**CLI wallet**
|
||||
|
||||
* **Monerod:** add `--proxy 127.0.0.1:1080 --bootstrap-daemon-proxy 127.0.0.1:1080` to args
|
||||
|
||||
* **Monero-wallet-{rpc, cli}:** add `--proxy 127.0.0.1:1080 --daemon-ssl-allow-any-cert` to args
|
||||
|
||||
For those who want to try it out in testnet, a stagenet service provider is also available: [https://nymtech.net/.wellknown/connect/service-providers.json](https://nymtech.net/.wellknown/connect/service-providers.json)
|
||||
|
||||
Now your Monero traffic is protected by the network privacy of Nym Mixnet.
|
||||
@@ -1,5 +0,0 @@
|
||||
# Rust SDK
|
||||
|
||||
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 seperate process on their machine.
|
||||
|
||||
[Read the docs](https://nymtech.net/docs/sdk/rust/rust.html).
|
||||
@@ -1,70 +0,0 @@
|
||||
# Tutorial Overview
|
||||
|
||||
## Components Created in this Tutorial
|
||||
This tutorial involves writing two pieces of code in Typescript:
|
||||
|
||||
- A **User Client** (UC) with which you can access the mixnet through a browser on your local machine. You will use this to communicate with the second component outlined below.
|
||||
- A **Service Provider** (SP) which can communicate with the UC via the mixnet.
|
||||
|
||||
Additionally you will learn how to configure a pair of **Nym Websocket Clients** which both components use to connect to and communicate with the Mixnet.
|
||||
|
||||
> SPs usually run on remote servers to assure reliable uptime and to unlink sender and receiver metadata. For demonstration purposes however, you will run both components on your local machine, looping messages through the mixnet to yourself.
|
||||
|
||||
|
||||
|
||||
```
|
||||
+----------+ +----------+ +----------+
|
||||
| Mix Node |<-----------> | Mix Node |<----------->| Mix Node |
|
||||
| Layer 1 | | Layer 2 | | Layer 3 |
|
||||
+----------+ +----------+ +----------+
|
||||
^ ^
|
||||
| |
|
||||
|<--------------------------------------------------+
|
||||
|
|
||||
v
|
||||
+--------------+
|
||||
| Your gateway |
|
||||
+--------------+
|
||||
^
|
||||
|
|
||||
|
|
||||
v
|
||||
+-------------------------------------------+
|
||||
| |
|
||||
| +------------+ +------------+ |
|
||||
| | Nym Client | | Nym Client | |
|
||||
| +------------+ +------------+ |
|
||||
| ^ ^ |
|
||||
| | | |
|
||||
| | | |
|
||||
| v v |
|
||||
| +-------------+ +------------------+ |
|
||||
| | User Client | | Service Provider | |
|
||||
| +-------------+ +------------------+ |
|
||||
| |
|
||||
+-------------------------------------------+
|
||||
Your Local Machine
|
||||
```
|
||||
|
||||
## Aims of this Tutorial
|
||||
* Create a user-friendly experience for sending data through the mixnet via a simple form accessible through a web browser.
|
||||
* Configure and use a pair of Nym Websocket Clients.
|
||||
* Send a properly formatted message through the mixnet to the SP from a browser-based GUI.
|
||||
|
||||
You can find the code for these components [here](https://github.com/nymtech/developer-tutorials). You can use it as a reference while building or simply download it and follow along as you progress through the tutorial.
|
||||
|
||||
Notice that this tutorial attempts to use very few external libraries (the User Client codebase is basically vanilla Typescript!). This tutorial is not showing you how to build production-grade code, but **to understand how to connect and send messages to, as well as recieve messages from, the mixnet.**
|
||||
|
||||
```admonish note title="Sidenote: What is a Service Provider?"
|
||||
'Service Provider' is a catchall name used to refer to any type of app that can communicate with the mixnet via a Nym client.
|
||||
|
||||
The first SP to have been released is the [Network Requester](https://nymtech.net/docs/nodes/network-requester.html) - a binary that receives a network request from the mixnet, performs that request (e.g. authenticating with a message server and receiving new messages for a user) and then passes the response back to the user who requested it anonymously, shielding their metadata from the message server.
|
||||
|
||||
The SP you will build in this tutorial is far more simple than this. It is just to show you how to approach building something that can:
|
||||
* connect to the mixnet,
|
||||
* listen for messages, and
|
||||
* perform some action with them (in this case, log them in a console and reply to the original sender).
|
||||
|
||||
However, once you see how easy it is to integrate with the mixnet for traffic transport, you will be able to build apps with real-world uses easily.
|
||||
```
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
# Preparing Your User Client Environment
|
||||
|
||||
## Prerequisites
|
||||
* `NodeJS` & `npm`
|
||||
* `typescript`
|
||||
|
||||
## Preparing your TypeScript environment
|
||||
|
||||
* Make a new directory called `simple-service-provider-tutorial` containing a directory named `user-client`:
|
||||
|
||||
```
|
||||
mkdir -p simple-service-provider/user-client
|
||||
```
|
||||
|
||||
* Create a `package.json` and install dependencies:
|
||||
|
||||
```
|
||||
cd simple-service-provider/user-client
|
||||
npm init
|
||||
npm install typescript # allows you to write and use typescript
|
||||
npm install ts-node --save-dev # allows you to build a typescript application in a NodeJS environment
|
||||
```
|
||||
|
||||
* Create a `tsconfig.json` containing the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"esModuleInterop": true,
|
||||
"target": "es6",
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
"outDir": "dist"
|
||||
},
|
||||
"lib": ["es2015"]
|
||||
}
|
||||
```
|
||||
|
||||
## Preparing your Bundler
|
||||
* We will use the [`Parcel`](https://parceljs.org/getting-started/webapp/) bundler to build and run our app locally. `Parcel` also supports hot reloading, making for a nicer developer experience when working on our app. Install it with:
|
||||
|
||||
```
|
||||
npm install parcel-bundler
|
||||
```
|
||||
|
||||
* Create the file structure for our frontend code:
|
||||
|
||||
```
|
||||
mkdir src
|
||||
touch src/index.html src/index.ts
|
||||
```
|
||||
|
||||
~~~admonish note title=""
|
||||
At this point your directory should look like this (check yourself with `tree -L 2 simple-service-provider/`):
|
||||
```
|
||||
simple-service-provider/
|
||||
└── user-client
|
||||
├── node_modules
|
||||
├── package.json
|
||||
├── package-lock.json
|
||||
├── src
|
||||
└── tsconfig.json
|
||||
|
||||
4 directories, 3 files
|
||||
```
|
||||
|
||||
And `user-client/src/` should look like this:
|
||||
```
|
||||
user-client/src
|
||||
├── index.html
|
||||
└── index.ts
|
||||
|
||||
1 directory, 2 files
|
||||
```
|
||||
~~~
|
||||
|
||||
* Time to check everything is working. Paste the following into `src/index.html`:
|
||||
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>App Test</title>
|
||||
<meta charset="utf-8"/>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Test</h1>
|
||||
<div id="app"></div>
|
||||
<script src="index.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
* Paste the following into `src/index.ts`
|
||||
|
||||
```
|
||||
console.log('test log')
|
||||
```
|
||||
|
||||
* Add the following to `package.json` in the `"scripts"` array, above `"test"`:
|
||||
|
||||
```
|
||||
"start": "parcel src/index.html"
|
||||
```
|
||||
|
||||
* `npm start` should return:
|
||||
|
||||
```
|
||||
> user-client@1.0.0 start
|
||||
> parcel src/index.html
|
||||
|
||||
Server running at http://localhost:1234
|
||||
✨ Built in 1.57s.
|
||||
```
|
||||
|
||||
Open [localhost:1234](http://localhost:1234/) in your browser. Your web application should be up and running, with `Test` displayed in the browser window. Checking the `console.log` output is done by right-clicking on the browser and selecting _Inspect_, then navigating to the _Console_ section of the resulting panel. You should see the message `test log` displayed there.
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
# Preparing Your Service Provider Environment
|
||||
|
||||
* Now to move on to prepare our development environment for the Service Provider code. Create a directory for it:
|
||||
|
||||
```
|
||||
# run this from the root of `simple-service-provider/`
|
||||
mkdir service-provider
|
||||
cd service-provider
|
||||
```
|
||||
|
||||
* Create a `package.json`:
|
||||
|
||||
```
|
||||
npm init
|
||||
```
|
||||
|
||||
* Inside your newly generated `package.json`, paste in the following code:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "service-provider",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start:dev": "nodemon",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.14.0",
|
||||
"@types/ws": "^8.5.4",
|
||||
"nodemon": "^2.0.20",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.8.4"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"ws": "^8.12.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* install dependecies:
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
* create a `tsconfig.json` file containing the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"lib": [
|
||||
"es6"
|
||||
],
|
||||
"module": "Node16",
|
||||
"rootDir": "src",
|
||||
"resolveJsonModule": true,
|
||||
"allowJs": true,
|
||||
"outDir": "build",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* You will use [Nodemon](https://www.npmjs.com/package/nodemon) to reload your app on code changes. Create a `nodemon.json` file in the same directory which will act as our `nodemon` configuration. Paste in the following code inside that file:
|
||||
|
||||
```json
|
||||
{
|
||||
"watch": [
|
||||
"src"
|
||||
],
|
||||
"ext": ".ts,.js",
|
||||
"ignore": [],
|
||||
"exec": "ts-node ./src/index.ts"
|
||||
}
|
||||
```
|
||||
|
||||
* Finally, create a typescript file for our app logic:
|
||||
|
||||
```
|
||||
mkdir src
|
||||
touch src/index.ts
|
||||
```
|
||||
|
||||
~~~admonish note title=""
|
||||
At this point your directory should look like this (check yourself with `tree -L 2 simple-service-provider`):
|
||||
```
|
||||
simple-service-provider
|
||||
├── service-provider
|
||||
│ ├── node_modules
|
||||
│ ├── nodemon.json
|
||||
│ ├── package.json
|
||||
│ ├── package-lock.json
|
||||
│ ├── src
|
||||
│ └── tsconfig.json
|
||||
└── user-client
|
||||
├── node_modules
|
||||
├── package.json
|
||||
├── package-lock.json
|
||||
├── src
|
||||
└── tsconfig.json
|
||||
|
||||
7 directories, 7 files
|
||||
```
|
||||
|
||||
And `service-provider/src/` should look like this:
|
||||
```
|
||||
service-provider/src
|
||||
└── index.ts
|
||||
|
||||
1 directory, 1 file
|
||||
```
|
||||
~~~
|
||||
@@ -1,18 +0,0 @@
|
||||
# Sending a Message Through the Mixnet
|
||||
|
||||
You are now ready to send a message through the mixnet!
|
||||
|
||||
You should have the following set up:
|
||||
|
||||
* A __User Client__ Web App
|
||||
* A __Service Provider__ backend service
|
||||
* 2 Nym websocket clients, one for each component above
|
||||
|
||||
Simply fill in the fields in your browser and click `Send`. In your browser you will see the message sent to the SP, followed by the response from the SP. In your console you will see the logged incoming message from the UC, and the reply message to itfrom the SP.
|
||||
|
||||
<img src="../../images/tutorial_image_5.png"/>
|
||||
|
||||
This small project can be used as a template to start conceptualizing and developing more complex PEApps. Stay tuned for more soon, and if you're searching for inspiration check out the [community apps](../../community-resources/community-applications-and-guides.md) list!
|
||||
|
||||
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
# Building Your Service Provider
|
||||
|
||||
> Since a lot of logic you will write in this section is similar or the same to UC code you just written, this section will only focus on SP-specific functionality
|
||||
|
||||
* Paste the following code into `src/index.ts`
|
||||
|
||||
```typescript
|
||||
import WebSocket, { MessageEvent } from "ws";
|
||||
|
||||
var ourAddress: string;
|
||||
var websocketConnection: any;
|
||||
|
||||
async function main() {
|
||||
var port = '1978'
|
||||
var localClientUrl = "ws://127.0.0.1:" + port;
|
||||
|
||||
// Set up and handle websocket connection to our desktop client.
|
||||
websocketConnection = await connectWebsocket(localClientUrl).then(function (c) {
|
||||
return c;
|
||||
}).catch(function (err) {
|
||||
console.log("Websocket connection error. Is the client running with <pre>--connection-type WebSocket</pre> on port " + port + "?");
|
||||
console.log(err);
|
||||
})
|
||||
|
||||
websocketConnection.onmessage = function (e : any) {
|
||||
handleResponse(e);
|
||||
};
|
||||
|
||||
sendSelfAddressRequest();
|
||||
}
|
||||
|
||||
// Handle any messages that come back down the websocket.
|
||||
function handleResponse(responseMessageEvent : MessageEvent) {
|
||||
|
||||
try {
|
||||
let response = JSON.parse(responseMessageEvent.data.toString());
|
||||
if (response.type == "error") {
|
||||
console.log("\x1b[91mAn error occured: " + response.message + "\x1b[0m")
|
||||
} else if (response.type == "selfAddress") {
|
||||
ourAddress = response.address;
|
||||
console.log("\x1b[94mOur address is: " + ourAddress + "\x1b[0m")
|
||||
} else if (response.type == "received") {
|
||||
let messageContent = JSON.parse(response.message)
|
||||
|
||||
console.log('\x1b[93mRecieved : \x1b[0m');
|
||||
console.log('\x1b[92mName : ' + messageContent.name + '\x1b[0m');
|
||||
console.log('\x1b[92mService : ' + messageContent.service + '\x1b[0m');
|
||||
console.log('\x1b[92mComment : ' + messageContent.comment + '\x1b[0m');
|
||||
|
||||
console.log('\x1b[93mSending response back to client... \x1b[0m')
|
||||
|
||||
sendMessageToMixnet(response.senderTag)
|
||||
}
|
||||
} catch (_) {
|
||||
console.log('something went wrong in handleResponse')
|
||||
}
|
||||
}
|
||||
|
||||
function sendMessageToMixnet(senderTag: string) {
|
||||
|
||||
// Place each of the form values into a single object to be sent.
|
||||
const messageContentToSend = {
|
||||
text: 'We recieved your request - this reply sent to you anonymously with SURBs',
|
||||
fromAddress : ourAddress
|
||||
}
|
||||
|
||||
const message = {
|
||||
type: "reply",
|
||||
message: JSON.stringify(messageContentToSend),
|
||||
senderTag: senderTag
|
||||
}
|
||||
|
||||
// Send our message object via out via our websocket connection.
|
||||
websocketConnection.send(JSON.stringify(message));
|
||||
}
|
||||
|
||||
// Send a message to the mixnet client, asking what our own address is.
|
||||
function sendSelfAddressRequest() {
|
||||
var selfAddress = {
|
||||
type: "selfAddress"
|
||||
}
|
||||
websocketConnection.send(JSON.stringify(selfAddress));
|
||||
}
|
||||
|
||||
// Function that connects our application to the mixnet Websocket. We want to call this first in our main function.
|
||||
function connectWebsocket(url : string) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var server = new WebSocket(url);
|
||||
console.log('connecting to Mixnet Websocket (Nym Client)...')
|
||||
server.onopen = function () {
|
||||
resolve(server);
|
||||
};
|
||||
server.onerror = function (err) {
|
||||
reject(err);
|
||||
};
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
`main()` is still the function in charge of initializing and executing your application. Note that the SP's client is running on port `1978`. This is so we don't have a conflict with the client we have running for the UC part of our tutorial code!
|
||||
|
||||
`handleResponse()` works in a similar manner as the function with the same name in `simple-service-provider/user-client/src/index.ts`. This implementation logs to the console instead of passing messages to a UI.
|
||||
|
||||
The `\x1b` prefix you see in `console.log` adds colour to console ouput. The number that you see following the `[` and preceeding `m` is the colour code that can be compared [here](https://en.m.wikipedia.org/wiki/ANSI_escape_code#Colors). Its a nice and quick way of styling our terminal output.
|
||||
|
||||
When the SP receives a message from the mixnet, `sendMessageToMixnet()` sends a response back to notify the the user that the SP recieved their request successfully.
|
||||
|
||||
## Connecting to your Nym Client
|
||||
|
||||
* Follow instructions in the [Nym websocket client documentation](https://nymtech.net/docs/clients/websocket-client.html#initialising-your-client)to `init` and `run` a client.
|
||||
|
||||
```admonish caution title=""
|
||||
Remember to `init` and `run` this client using port `1978` to avoid port clashes.
|
||||
```
|
||||
|
||||
* Refresh your browser window. You should see a successful response, including a Nym address, in your console:
|
||||
|
||||
```
|
||||
> service-provider@1.0.0 start:dev
|
||||
> nodemon
|
||||
|
||||
[nodemon] 2.0.20
|
||||
[nodemon] to restart at any time, enter `rs`
|
||||
[nodemon] watching path(s): src/**/*
|
||||
[nodemon] watching extensions: ts,js
|
||||
[nodemon] starting `ts-node ./src/index.ts`
|
||||
connecting to Mixnet Websocket (Nym Client)...
|
||||
Our address is: 6V5eEguz4rUsfntVLKQuD2ymgdY5iDKCV2GY2EH3CxG4.AKdk22atwRaVkN2PLEDsWUKKDc3ieNm1avKqVGgmJx8s@FQon7UwF5knbUr2jf6jHhmNLbJnMreck1eUcVH59kxYE
|
||||
```
|
||||
|
||||
## Set Service Address in User Client
|
||||
The final step of this tutorial is to update our User Client code with the address of the now-running Service Provider so it can send it a message.
|
||||
|
||||
Copy the SP's Nym address from your console and set it as the value of the `targetAddress` variable on line 2 of `simple-service-provider/user-client/src/index.ts`.
|
||||
|
||||
```
|
||||
var targetAddress: string = '6V5eEguz4rUsfntVLKQuD2ymgdY5iDKCV2GY2EH3CxG4.AKdk22atwRaVkN2PLEDsWUKKDc3ieNm1avKqVGgmJx8s@FQon7UwF5knbUr2jf6jHhmNLbJnMreck1eUcVH59kxYE';
|
||||
```
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
# Building a Simple Service Provider
|
||||
|
||||
```admonish warning
|
||||
This tutorial was written before the creation of the [Typescript SDK](https://sdk.nymtech.net), and involves running a Nym Client alongside your application processes, instead of relying on the SDK to integrate the Client process into your application logic.
|
||||
|
||||
As such, although this tutorial is still a valid way of approaching building on Nym, it is a little less streamlined than it could be.
|
||||
|
||||
A more streamlined rewrite of this tutorial will be coming soon.
|
||||
```
|
||||
This tutorial is the best place to start for developers new to Nym. You will learn how to build a minimum viable privacy-enabled application (PEApp) able to send and receive traffic via the mixnet.
|
||||
|
||||
This tutorial is less about building an immediately useful application, and more about beginning to understand:
|
||||
* Sending messages through the mixnet to another Nym client
|
||||
* Receiving messages from the mixnet and handling them
|
||||
* Anonymous replies with Single Use Reply Blocks (SURBs)
|
||||
|
||||
That said, this tutorial will give you the skeleton of an application, onto which you can add more useful functionality.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,262 +0,0 @@
|
||||
# Building Your User Client
|
||||
|
||||
## Adding Core Functionality
|
||||
Most of the work here will be configuring and adding functionality to `src/index.ts` file, allowing you to establish and handle the websocket connection to your local Nym client, and create and send messages to the SP.
|
||||
|
||||
* Replace the existing content of `src/index.ts` with:
|
||||
|
||||
```typescript
|
||||
async function main() {}
|
||||
|
||||
function connectWebsocket(url) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var server = new WebSocket(url);
|
||||
console.log('connecting to Websocket Server (Nym Client)...')
|
||||
server.onopen = function () {
|
||||
resolve(server);
|
||||
};
|
||||
server.onerror = function (err) {
|
||||
reject(err);
|
||||
};
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
`main()` will the majority of the app's logic. It's best to declare it at the start of the file and call it at the end to run when launching the application.
|
||||
|
||||
`connectWebsocket(url)` returns a `Promise` that attempts to create a websocket connection to `url`. If the connection is successful, you will get a notification in your running application in the browser, as well as the connected Nym client. If it fails an error will be displayed in the browser.
|
||||
|
||||
* Now to implement the functions that will handle DOM (Document Object Model) manipulation. Add the following below `connectWebsocket()`:
|
||||
|
||||
```typescript
|
||||
function handleResponse(resp) {
|
||||
try {
|
||||
let response = JSON.parse(resp.data);
|
||||
if (response.type == "error") {
|
||||
displayJsonResponse("Server responded with error: " + response.message);
|
||||
} else if (response.type == "selfAddress") {
|
||||
ourAddress = response.address;
|
||||
displayClientMessage("Our address is: " + ourAddress + ", we will now send messages to ourself.");
|
||||
} else if (response.type == "received") {
|
||||
handleReceivedTextMessage(response)
|
||||
}
|
||||
} catch (_) {
|
||||
displayJsonResponse(resp.data)
|
||||
}
|
||||
}
|
||||
|
||||
function handleReceivedTextMessage(message) {
|
||||
const text = JSON.parse(message.message);
|
||||
displayJsonResponse(text);
|
||||
}
|
||||
|
||||
// Display websocket responses in the Activity Log.
|
||||
function displayJsonResponse(message) {
|
||||
let receivedDiv = document.createElement("div")
|
||||
let paragraph = document.createElement("p")
|
||||
paragraph.setAttribute('style', 'color: orange')
|
||||
let textNode = document.createTextNode("received >>> " + message.text)
|
||||
paragraph.appendChild(textNode)
|
||||
|
||||
receivedDiv.appendChild(paragraph)
|
||||
document.getElementById("output").appendChild(receivedDiv)
|
||||
}
|
||||
|
||||
function displayClientMessage(message) {
|
||||
document.getElementById("output").innerHTML += "<p>" + message + "</p >";
|
||||
}
|
||||
```
|
||||
|
||||
`handleResponse()` parses the type of any messages received from the websocket, and handles forwarding the message on to the appropriate function depending on this `type`. You can find documentation on these types [here](https://nymtech.net/docs/clients/websocket-client.html#message-types).
|
||||
|
||||
`handleReceivedTextMessage()` ensures that data is `json` data before displaying on the UI.
|
||||
|
||||
`displayJsonResponse()` is responsible for displaying received messages on the UI, creating a new `<p>` HTML element for each message that needs to be displayed on screen.
|
||||
|
||||
`displayClientMessage()` displays the address of the connected Nym client.
|
||||
|
||||
* Declare the following variables above `main()`
|
||||
|
||||
```typescript
|
||||
var ourAddress: string;
|
||||
var targetAddress: string;
|
||||
var websocketConnection: any;
|
||||
```
|
||||
|
||||
`ourAddress` takes the value of the connected Nym client address.
|
||||
|
||||
`targetAddress` will be the Nym address of the SP.
|
||||
|
||||
`websocketConnection` populated upon a successful response from `connectWebsocket()`.
|
||||
|
||||
* Add the following to `main()`:
|
||||
|
||||
```typescript
|
||||
async function main() {
|
||||
var port = '1977' // Nym Websocket Client listens on 1977 by default.
|
||||
var localClientUrl = "ws://127.0.0.1:" + port;
|
||||
|
||||
// Set up and handle websocket connection to our desktop client.
|
||||
websocketConnection = await connectWebsocket(localClientUrl).then(function (c) {
|
||||
return c;
|
||||
}).catch(function (err) {
|
||||
displayClientMessage("Websocket connection error. Is the client running with <pre>--connection-type WebSocket</pre> on port " + port + "?");
|
||||
})
|
||||
|
||||
websocketConnection.onmessage = function (e) {
|
||||
handleResponse(e);
|
||||
};
|
||||
|
||||
sendSelfAddressRequest();
|
||||
|
||||
// Set up the send button
|
||||
const sendButton = document.querySelector('#send-button');
|
||||
|
||||
sendButton?.addEventListener('click', function handleClick(event) {
|
||||
sendMessageToMixnet();
|
||||
});
|
||||
```
|
||||
|
||||
And between `main()` and `displayClientMessage()`:
|
||||
|
||||
```typescript
|
||||
function sendSelfAddressRequest() {
|
||||
var selfAddress = {
|
||||
type: "selfAddress"
|
||||
}
|
||||
displayJsonSend(selfAddress);
|
||||
websocketConnection.send(JSON.stringify(selfAddress));
|
||||
}
|
||||
```
|
||||
|
||||
`sendSelfAddressRequest()` sends a `selfAddress` message to the connected websocket client, passing the response to `displayJsonSend()` to be displayed on your UI.
|
||||
|
||||
`main()` now contains logic for: connecting to a local Nym client, getting its address with a `selfAddress` message, and displaying it on the UI. Now your app can display its connection status, letting you know whether it is(n't) connected to a running client!
|
||||
|
||||
* Underneath `sendSelfAddressRequest()` implement a function to send messages down the websocket connection to the SP:
|
||||
|
||||
```typescript
|
||||
function sendMessageToMixnet() {
|
||||
|
||||
var nameInput = (<HTMLInputElement>document.getElementById("nameInput")).value;
|
||||
var textInput = (<HTMLInputElement>document.getElementById("textInput")).value;
|
||||
|
||||
const messageContentToSend = {
|
||||
name : nameInput,
|
||||
comment : textInput,
|
||||
}
|
||||
|
||||
const message = {
|
||||
type: "sendAnonymous",
|
||||
message: JSON.stringify(messageContentToSend),
|
||||
recipient: targetAddress,
|
||||
replySurbs: 5
|
||||
}
|
||||
|
||||
displayJsonSend(message);
|
||||
websocketConnection.send(JSON.stringify(message));
|
||||
}
|
||||
```
|
||||
|
||||
Nym clients accept messages in either binary or JSON formats. Since you are sending JSON data, you need to `stringify` any `message`s you wish to send through the mixnet.
|
||||
|
||||
You are sending [replySURBs](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs) along with the message to the SP. This allows the SP to reply to you without you having to doxx yourself and supply a 'return address' in a readable form to it. TLDR; SURBs allow for anonymous replies from mixnet services!
|
||||
|
||||
* Below `sendMessageToMixnet()`, add the following:
|
||||
|
||||
```typescript
|
||||
function displayJsonSend(message) {
|
||||
let sendDiv = document.createElement("div")
|
||||
let paragraph = document.createElement("p")
|
||||
paragraph.setAttribute('style', 'color: #36d481')
|
||||
let paragraphContent = document.createTextNode("sent >>> " + JSON.stringify(message))
|
||||
paragraph.appendChild(paragraphContent)
|
||||
|
||||
sendDiv.appendChild(paragraph)
|
||||
document.getElementById("output").appendChild(sendDiv)
|
||||
}
|
||||
```
|
||||
|
||||
`displayJsonSend()` displays sent messages in the "Activity Log" section of the UI.
|
||||
|
||||
* Replace the contents of `src/index.html` with the following:
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Mixnet Websocket Starter Client</title>
|
||||
<link rel="stylesheet" href="../assets/styles.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content" role="main">
|
||||
<div class="toolbar">
|
||||
<h3>Mixnet Websocket Starter User Client</h3>
|
||||
</div>
|
||||
|
||||
<div class="section-container">
|
||||
|
||||
<label for="nameInput" class="form-field-label">Moniker</label>
|
||||
<input id="nameInput" type="text" value="An0n" name="nameInput">
|
||||
|
||||
<label for="textInput" class="form-field-label">Comment</label>
|
||||
<input id="textInput" type="text" value="I would like to use your private service" name="textInput">
|
||||
|
||||
<div id="send-button">
|
||||
<label for="send-button" class="submit-button">Send</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="" style="margin-left:20px;max-width: fit-content;">
|
||||
<div style="color: white;margin-bottom: 2rem;">
|
||||
<h4>How it works</h4>
|
||||
<p>Once you have started your Nym Websocket client, you can fill out the form and send data to the Service Provider via mixnet using the <b>"Send"</b> button.</p>
|
||||
<p>Below, you can see the activity log. <b style='color: #36d481;'>Sent</b> messages will display in <b style='color: #36d481;'>green</b> while <b style='color: orange;'>received</b> messages will display in <b style='color: orange;'>orange</b>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 style="margin-left:10px">Activity Log</h3>
|
||||
|
||||
<p class="output-container">
|
||||
<span id="output"></div>
|
||||
</p>
|
||||
<script src="index.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Lets add the finishing touches to the UI by adding in the stylesheet which we specified at the top of `index.html`:
|
||||
|
||||
```
|
||||
mkdir -p assets
|
||||
touch assets/styles.css
|
||||
|
||||
# grab the stylesheet from the remote repo and save it to the newly created css file
|
||||
curl https://raw.githubusercontent.com/nymtech/developer-tutorials/main/simple-service-provider-tutorial/user-client/assets/styles.css -o assets/styles.css
|
||||
```
|
||||
|
||||
* Return back to your terminal and run:
|
||||
|
||||
```
|
||||
npm start
|
||||
```
|
||||
|
||||
Return to [localhost:1234](http://localhost:1234/)) and you should see an updated UI.
|
||||
|
||||
<img src="../../images/tutorial_image_2.png"/>
|
||||
|
||||
## Connecting to your Nym Client
|
||||
|
||||
Follow instructions in the [Nym websocket client documentation](https://nymtech.net/docs/clients/websocket-client.html#initialising-your-client)to `init` and `run` a client then refresh your browser window. You should see a successful response, including a Nym address, in the 'Activity Log' of the UI
|
||||
|
||||
Your User Client application code is connected to a Nym websocket client, and ready to send messages through the mixnet!
|
||||
|
||||
<img src="../../images/tutorial_image_1.png"/>
|
||||
|
||||
In the next section, you will build the Service application you will send these messages to.
|
||||
|
||||
@@ -39,5 +39,5 @@ Follow this [video](https://youtu.be/quj8H2qeOwY?t=97) to see the steps on Teleg
|
||||
|
||||
**Now your Telegram runs over NymConnect.**
|
||||
|
||||
NymConnect is currently available for several applications and service providers. Support for more apps is on the way. For any bug reports or feedback please reach out to us on Telegram or our [Discord](http://discord.gg/nym) server.
|
||||
NymConnect is currently available for several applications and service providers. Support for more apps is on the way. For any bug reports or feedback please reach out to us on Telegram or our [Discord](http://discord.gg/FaTJb8q8) server.
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
# Preparing Your Client pt2
|
||||
@@ -0,0 +1 @@
|
||||
# Preparing Your Client
|
||||
@@ -0,0 +1 @@
|
||||
# Blockchain Service pt1
|
||||
@@ -0,0 +1 @@
|
||||
# Preparing Your Lib
|
||||
@@ -0,0 +1 @@
|
||||
# Tutorial Overview
|
||||
+1
@@ -0,0 +1 @@
|
||||
# Preparing Your Environment
|
||||
@@ -0,0 +1 @@
|
||||
# Querying the Chain
|
||||
@@ -0,0 +1 @@
|
||||
# Preparing Your Service pt2
|
||||
@@ -0,0 +1 @@
|
||||
# Preparing Your Service
|
||||
+1
@@ -0,0 +1 @@
|
||||
# Tutorial Overview
|
||||
+1
@@ -0,0 +1 @@
|
||||
# Preparing Your User Client Environment
|
||||
+1
@@ -0,0 +1 @@
|
||||
# Preparing Your Service Provider Environment
|
||||
+1
@@ -0,0 +1 @@
|
||||
# Sending a Message Through the Mixnet
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user