Skip to content

Typescript SDK support for zk-nyms #4704

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Draft
wants to merge 6 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,6 @@ foxyfox.env

.next
ppa-private-key.b64
ppa-private-key.asc
ppa-private-key.asc

yarn-error.log
34 changes: 32 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ members = [
# "wasm/full-nym-wasm", # If we uncomment this again, remember to also uncomment the profile settings below
"wasm/mix-fetch",
"wasm/node-tester",
"wasm/zknym-lib",
"wasm/zk-nym-lib",
"wasm/zk-nym-faucet-lib",
"tools/internal/testnet-manager",
"tools/internal/testnet-manager/dkg-bypass-contract",
]
Expand Down
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ sdk-wasm-build:
$(MAKE) -C wasm/client
$(MAKE) -C wasm/node-tester
$(MAKE) -C wasm/mix-fetch
$(MAKE) -C wasm/zknym-lib
$(MAKE) -C wasm/zk-nym-lib
$(MAKE) -C wasm/zk-nym-faucet-lib
#$(MAKE) -C wasm/full-nym-wasm

# run this from npm/yarn to ensure tools are in the path, e.g. yarn build:sdk from root of repo
Expand All @@ -115,7 +116,7 @@ sdk-typescript-build:
yarn --cwd sdk/typescript/codegen/contract-clients build

# NOTE: These targets are part of the main workspace (but not as wasm32-unknown-unknown)
WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm zknym-lib
WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm zk-nym-lib

sdk-wasm-test:
#cargo test $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings
Expand Down
10 changes: 10 additions & 0 deletions common/client-core/src/client/packet_statistics_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{
time::{Duration, Instant},
};

#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
use nym_metrics::{inc, inc_by};
use si_scale::helpers::bibytes2;

Expand Down Expand Up @@ -72,6 +73,14 @@ struct PacketStatistics {
}

impl PacketStatistics {
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
fn handle_event(
&mut self,
_event: crate::client::packet_statistics_control::PacketStatisticsEvent,
) {
}

#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
fn handle_event(&mut self, event: PacketStatisticsEvent) {
match event {
PacketStatisticsEvent::RealPacketSent(packet_size) => {
Expand Down Expand Up @@ -330,6 +339,7 @@ impl PacketRates {
}
}

#[allow(unused_variables, dead_code)]
#[derive(Debug)]
pub(crate) enum PacketStatisticsEvent {
// The real packets sent. Recall that acks are sent by the gateway, so it's not included here.
Expand Down
16 changes: 8 additions & 8 deletions common/client-libs/validator-client/src/nyxd/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub enum NyxdError {
#[error("{0} is not a valid tx hash")]
InvalidTxHash(String),

#[error("Tendermint RPC request failed - {0}")]
#[error("Tendermint RPC request failed: {0}")]
TendermintErrorRpc(#[from] TendermintRpcError),

#[error("tendermint library failure: {0}")]
Expand All @@ -62,22 +62,22 @@ pub enum NyxdError {
#[error("Failed when attempting to deserialize data ({0})")]
DeserializationError(String),

#[error("Failed when attempting to encode our protobuf data - {0}")]
#[error("Failed when attempting to encode our protobuf data: {0}")]
ProtobufEncodingError(#[from] prost::EncodeError),

#[error("Failed to decode our protobuf data - {0}")]
#[error("Failed to decode our protobuf data: {0}")]
ProtobufDecodingError(#[from] prost::DecodeError),

#[error("Account {0} does not exist on the chain")]
#[error("Account '{0}' does not exist on the chain")]
NonExistentAccountError(AccountId),

#[error("Failed on json serialization/deserialization - {0}")]
#[error("Failed on json serialization/deserialization: {0}")]
SerdeJsonError(#[from] serde_json::Error),

#[error("Account {0} is not a valid account address")]
#[error("Account '{0}' is not a valid account address")]
MalformedAccountAddress(String),

#[error("Account {0} has an invalid associated public key")]
#[error("Account '{0}' has an invalid associated public key")]
InvalidPublicKey(AccountId),

#[error("Queried contract (code_id: {0}) did not have any code information attached")]
Expand All @@ -92,7 +92,7 @@ pub enum NyxdError {
#[error("Block has an invalid height (either negative or larger than i64::MAX")]
InvalidHeight,

#[error("Failed to compress provided wasm code - {0}")]
#[error("Failed to compress provided wasm code: {0}")]
WasmCompressionError(io::Error),

#[error("Logs returned from the validator were malformed")]
Expand Down
3 changes: 2 additions & 1 deletion common/client-libs/validator-client/src/rpc/reqwest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ trait TendermintRpcErrorMap {

impl TendermintRpcErrorMap for reqwest::Error {
fn into_rpc_err(self) -> Error {
todo!()
// that's not the best error converion, but it's better than a panic
Error::client_internal(self.to_string())
}
}

Expand Down
8 changes: 4 additions & 4 deletions common/credential-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ license.workspace = true
[dependencies]
log = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true }
tokio = { workspace = true, features = ["sync", "time"] }
time.workspace = true

nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
nym-credentials = { path = "../../common/credentials" }
nym-credentials-interface = { path = "../../common/credentials-interface" }
nym-credential-storage = { path = "../../common/credential-storage", features = ["persistent-storage"] }
nym-validator-client = { path = "../../common/client-libs/validator-client" }
nym-validator-client = { path = "../../common/client-libs/validator-client", default-features = false }
nym-config = { path = "../../common/config" }
nym-client-core = { path = "../../common/client-core" }
nym-ecash-time = { path = "../../common/ecash-time" }
nym-client-core = { path = "../../common/client-core", features = ["wasm"] }
nym-ecash-time = { path = "../../common/ecash-time" }
5 changes: 5 additions & 0 deletions common/credential-utils/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ use log::*;
use nym_bandwidth_controller::acquire::{
get_ticket_book, query_and_persist_required_global_signatures,
};
#[cfg(not(target_arch = "wasm32"))]
use nym_client_core::config::disk_persistence::CommonClientPaths;
#[cfg(not(target_arch = "wasm32"))]
use nym_config::DEFAULT_DATA_DIR;
#[cfg(not(target_arch = "wasm32"))]
use nym_credential_storage::persistent_storage::PersistentStorage;
use nym_credential_storage::storage::Storage;
use nym_credentials_interface::TicketType;
Expand All @@ -16,6 +19,7 @@ use nym_validator_client::coconut::all_ecash_api_clients;
use nym_validator_client::nyxd::contract_traits::{
dkg_query_client::EpochState, DkgQueryClient, EcashQueryClient, EcashSigningClient,
};
#[cfg(not(target_arch = "wasm32"))]
use std::path::PathBuf;
use std::time::Duration;
use time::OffsetDateTime;
Expand Down Expand Up @@ -80,6 +84,7 @@ where
Ok(())
}

#[cfg(not(target_arch = "wasm32"))]
pub async fn setup_persistent_storage(client_home_directory: PathBuf) -> PersistentStorage {
let data_dir = client_home_directory.join(DEFAULT_DATA_DIR);
let paths = CommonClientPaths::new_base(data_dir);
Expand Down
9 changes: 9 additions & 0 deletions common/credentials-interface/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ strum = { workspace = true, features = ["derive"] }
time = { workspace = true, features = ["serde"] }
rand = { workspace = true }

# 'wasm-serde-types' feature
wasm-utils = { path = "../wasm/utils", default-features = false, optional = true }
tsify = { workspace = true, features = ["js"], optional = true }
wasm-bindgen = { workspace = true, optional = true }

nym-compact-ecash = { path = "../nym_offline_compact_ecash" }
nym-ecash-time = { path = "../ecash-time" }
nym-network-defaults = { path = "../network-defaults" }

[features]
default = []
wasm-serde-types = ["tsify", "wasm-bindgen", "wasm-utils"]
8 changes: 8 additions & 0 deletions common/credentials-interface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ pub use nym_compact_ecash::{
};
use nym_ecash_time::{ecash_today, EcashTime};

#[cfg(feature = "wasm-serde-types")]
use tsify::Tsify;

#[cfg(feature = "wasm-serde-types")]
use wasm_bindgen::prelude::wasm_bindgen;

#[derive(Debug, Clone)]
pub struct CredentialSigningData {
pub withdrawal_request: WithdrawalRequest,
Expand Down Expand Up @@ -233,6 +239,8 @@ impl From<PayInfo> for NymPayInfo {
)]
#[serde(rename_all = "kebab-case")]
#[strum(serialize_all = "kebab-case")]
#[cfg_attr(feature = "wasm-serde-types", derive(Tsify))]
#[cfg_attr(feature = "wasm-serde-types", tsify(into_wasm_abi, from_wasm_abi))]
pub enum TicketType {
#[default]
V1MixnetEntry,
Expand Down
6 changes: 4 additions & 2 deletions common/network-defaults/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ schemars = { workspace = true, features = ["preserve_order"], optional = true }
serde = { workspace = true, features = ["derive"], optional = true }
url = { workspace = true, optional = true }

# please be extremely careful when adding new dependencies because this crate is imported by the ecash contract,
# so if anything new is added, consider feature-locking it and then just adding it to default feature
# 'wasm-serde-types' feature
tsify = { workspace = true, features = ["js"], optional = true }
wasm-bindgen = { workspace = true, optional = true }

[features]
wasm-serde-types = ["tsify", "wasm-bindgen"]
default = ["env", "network"]
env = ["dotenvy", "log"]
network = ["schemars", "serde", "url"]
2 changes: 1 addition & 1 deletion common/wasm/client-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ wasm-storage = { path = "../storage" }
console_error_panic_hook = { workspace = true, optional = true }

[features]
default = ["console_error_panic_hook"]
default = ["wasm-utils/console_error_panic_hook"]
4 changes: 4 additions & 0 deletions common/wasm/utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ gloo-utils = { workspace = true }
gloo-net = { workspace = true, features = ["websocket"], optional = true }
#gloo-net = { path = "../../../../gloo/crates/net", features = ["websocket"], optional = true }

# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { workspace = true, optional = true }

# we don't want entire tokio-tungstenite, tungstenite itself is just fine - we just want message and error enums
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,4 @@
"node-gyp": "^9.3.1",
"tslog": "3.3.3"
}
}
}
6 changes: 3 additions & 3 deletions sdk/rust/nym-sdk/src/bandwidth/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ where
St: Storage,
<St as Storage>::StorageError: Send + Sync + 'static,
{
pub(crate) fn new(
pub fn new(
network_details: NymNetworkDetails,
mnemonic: String,
storage: &'a St,
client_id: String,
client_id_private_key_base58: String,
ticketbook_type: TicketType,
) -> Result<Self> {
let nyxd_url = network_details.endpoints[0].nyxd_url.as_str();
Expand All @@ -44,7 +44,7 @@ where
Ok(Self {
client,
storage,
client_id: client_id.into(),
client_id: client_id_private_key_base58.into(),
ticketbook_type,
})
}
Expand Down
28 changes: 28 additions & 0 deletions sdk/typescript/examples/zk-nyms/browser/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Nym credential generation Usage Example

This is a simple project to show you how to use nym credential generation.

```ts
import { mixFetch } from '@nymproject/mix-fetch';

// HTTP GET
const response = await mixFetch('https://nymtech.net');
const html = await response.text();

// HTTP POST
const apiResponse = await mixFetch('https://api.example.com', {
method: 'POST',
body: JSON.stringify({ foo: 'bar' }),
headers: { [`Content-Type`]: 'application/json', Authorization: `Bearer ${AUTH_TOKEN}` }
});
```

## Running the example

```
npm install
npm run start
```

Open a browser at http://localhost:1234 and as the example loads, a connection will be made to the Nym Mixnet
and a text file and image will be downloaded and displayed in the browser.
16 changes: 16 additions & 0 deletions sdk/typescript/examples/zk-nyms/browser/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@nymproject/nym-sdk-zk-nyms-example-parcel",
"version": "1.3.0-rc.0",
"license": "Apache-2.0",
"scripts": {
"build": "parcel build --no-cache --no-content-hash",
"serve": "serve dist",
"start": "parcel --no-cache"
},
"dependencies": {
"@nymproject/sdk": "1.3.0-rc.0",
"parcel": "^2.9.3"
},
"private": false,
"source": "src/index.html"
}
Loading
Loading