Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d5c598729b | |||
| 7eb764cd5a | |||
| 854128ee21 | |||
| 6cd59124a2 | |||
| d5cc31b7f0 | |||
| ea6f009c01 | |||
| 5881f6b6aa | |||
| aafddc78d1 | |||
| 29a0e8620c | |||
| 800016f682 | |||
| 6151f15e7e | |||
| 5e6a945eef | |||
| aec23a4f83 | |||
| 3d563ece79 | |||
| f24a0dc8ae | |||
| 50fbdb4f0b | |||
| d445a26999 | |||
| 30294062af |
Generated
+27
-1
@@ -5520,6 +5520,30 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-credential-client-wasm"
|
||||
version = "1.3.0-rc.0"
|
||||
dependencies = [
|
||||
"bip39",
|
||||
"js-sys",
|
||||
"nym-bandwidth-controller",
|
||||
"nym-bin-common",
|
||||
"nym-credential-storage",
|
||||
"nym-credentials",
|
||||
"nym-credentials-interface",
|
||||
"nym-network-defaults",
|
||||
"nym-validator-client",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"thiserror",
|
||||
"tsify",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test",
|
||||
"wasm-utils",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-credential-storage"
|
||||
version = "0.1.0"
|
||||
@@ -6090,7 +6114,9 @@ dependencies = [
|
||||
"schemars",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tsify",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11039,7 +11065,6 @@ name = "wasm-client-core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"console_error_panic_hook",
|
||||
"js-sys",
|
||||
"nym-bandwidth-controller",
|
||||
"nym-client-core",
|
||||
@@ -11114,6 +11139,7 @@ dependencies = [
|
||||
name = "wasm-utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"futures",
|
||||
"getrandom 0.2.10",
|
||||
"gloo-net",
|
||||
|
||||
@@ -122,6 +122,7 @@ members = [
|
||||
# "wasm/full-nym-wasm",
|
||||
"wasm/mix-fetch",
|
||||
"wasm/node-tester",
|
||||
"wasm/credentials"
|
||||
]
|
||||
|
||||
default-members = [
|
||||
@@ -235,6 +236,12 @@ tendermint-rpc = "0.34" # same version as used by cosmrs
|
||||
prost = "0.12"
|
||||
|
||||
# wasm-related dependencies
|
||||
|
||||
# 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 = "0.1.7"
|
||||
gloo-utils = "0.1.7"
|
||||
js-sys = "0.3.63"
|
||||
serde-wasm-bindgen = "0.5.0"
|
||||
|
||||
@@ -103,6 +103,7 @@ sdk-wasm: sdk-wasm-build sdk-wasm-test sdk-wasm-lint
|
||||
sdk-wasm-build:
|
||||
$(MAKE) -C nym-browser-extension/storage wasm-pack
|
||||
$(MAKE) -C wasm/client
|
||||
$(MAKE) -C wasm/credentials
|
||||
$(MAKE) -C wasm/node-tester
|
||||
$(MAKE) -C wasm/mix-fetch
|
||||
#$(MAKE) -C wasm/full-nym-wasm
|
||||
|
||||
@@ -17,13 +17,17 @@ use zeroize::Zeroizing;
|
||||
|
||||
pub mod state;
|
||||
|
||||
pub async fn deposit<C>(client: &C, amount: Coin) -> Result<State, BandwidthControllerError>
|
||||
pub async fn deposit<C>(
|
||||
client: &C,
|
||||
amount: impl Into<Coin>,
|
||||
) -> Result<State, BandwidthControllerError>
|
||||
where
|
||||
C: CoconutBandwidthSigningClient + Sync,
|
||||
{
|
||||
let mut rng = OsRng;
|
||||
let signing_key = identity::PrivateKey::new(&mut rng);
|
||||
let encryption_key = encryption::PrivateKey::new(&mut rng);
|
||||
let amount = amount.into();
|
||||
|
||||
let tx_hash = client
|
||||
.deposit(
|
||||
|
||||
@@ -44,7 +44,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}")]
|
||||
@@ -56,22 +56,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")]
|
||||
@@ -86,7 +86,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")]
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
async-trait = { workspace = true }
|
||||
|
||||
log = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true, features = ["sync"]}
|
||||
@@ -26,4 +25,4 @@ features = [ "rt-multi-thread", "net", "signal", "fs" ]
|
||||
|
||||
[build-dependencies]
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
|
||||
|
||||
@@ -33,6 +33,12 @@ impl CoconutCredentialManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn take_credentials(self) -> Vec<StoredIssuedCredential> {
|
||||
let mut inner = self.inner.write().await;
|
||||
inner.credential_usage = Vec::new();
|
||||
std::mem::take(&mut inner.credentials)
|
||||
}
|
||||
|
||||
pub async fn insert_issued_credential(
|
||||
&self,
|
||||
credential_type: String,
|
||||
|
||||
@@ -15,6 +15,12 @@ pub struct EphemeralStorage {
|
||||
coconut_credential_manager: CoconutCredentialManager,
|
||||
}
|
||||
|
||||
impl EphemeralStorage {
|
||||
pub async fn take_credentials(self) -> Vec<StoredIssuedCredential> {
|
||||
self.coconut_credential_manager.take_credentials().await
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EphemeralStorage {
|
||||
fn default() -> Self {
|
||||
EphemeralStorage {
|
||||
|
||||
@@ -3,19 +3,6 @@
|
||||
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
// #[derive(Clone)]
|
||||
// pub struct CoconutCredential {
|
||||
// #[allow(dead_code)]
|
||||
// pub id: i64,
|
||||
// pub voucher_value: String,
|
||||
// pub voucher_info: String,
|
||||
// pub serial_number: String,
|
||||
// pub binding_number: String,
|
||||
// pub signature: String,
|
||||
// pub epoch_id: String,
|
||||
// pub consumed: bool,
|
||||
// }
|
||||
|
||||
#[cfg_attr(not(target_arch = "wasm32"), derive(sqlx::FromRow))]
|
||||
#[derive(Zeroize, ZeroizeOnDrop, Clone)]
|
||||
pub struct StoredIssuedCredential {
|
||||
|
||||
@@ -17,3 +17,11 @@ schemars = { workspace = true, features = ["preserve_order"] }
|
||||
serde = { workspace = true, features = ["derive"]}
|
||||
thiserror = { workspace = true }
|
||||
url = { workspace = true }
|
||||
|
||||
# 'wasm-serde-types' feature
|
||||
tsify = { workspace = true, features = ["js"], optional = true }
|
||||
wasm-bindgen = { workspace = true, optional = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
wasm-serde-types = ["tsify", "wasm-bindgen"]
|
||||
@@ -11,39 +11,96 @@ use std::{
|
||||
ffi::OsStr,
|
||||
ops::Not,
|
||||
};
|
||||
use url::Url;
|
||||
pub use url::{ParseError as UrlParseError, Url};
|
||||
|
||||
#[cfg(feature = "wasm-serde-types")]
|
||||
use tsify::Tsify;
|
||||
|
||||
#[cfg(feature = "wasm-serde-types")]
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
|
||||
pub mod mainnet;
|
||||
pub mod var_names;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, JsonSchema)]
|
||||
#[cfg_attr(feature = "wasm-serde-types", derive(Tsify))]
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(into_wasm_abi, from_wasm_abi))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ChainDetails {
|
||||
#[serde(alias = "bech32_account_prefix")]
|
||||
pub bech32_account_prefix: String,
|
||||
|
||||
#[serde(alias = "mix_denom")]
|
||||
pub mix_denom: DenomDetailsOwned,
|
||||
|
||||
#[serde(alias = "stake_denom")]
|
||||
pub stake_denom: DenomDetailsOwned,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, JsonSchema)]
|
||||
#[cfg_attr(feature = "wasm-serde-types", derive(Tsify))]
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(into_wasm_abi, from_wasm_abi))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NymContracts {
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
#[serde(alias = "mixnet_contract_address")]
|
||||
pub mixnet_contract_address: Option<String>,
|
||||
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
#[serde(alias = "vesting_contract_address")]
|
||||
pub vesting_contract_address: Option<String>,
|
||||
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
#[serde(alias = "coconut_bandwidth_contract_address")]
|
||||
pub coconut_bandwidth_contract_address: Option<String>,
|
||||
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
#[serde(alias = "group_contract_address")]
|
||||
pub group_contract_address: Option<String>,
|
||||
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
#[serde(alias = "multisig_contract_address")]
|
||||
pub multisig_contract_address: Option<String>,
|
||||
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
#[serde(alias = "coconut_dkg_contract_address")]
|
||||
pub coconut_dkg_contract_address: Option<String>,
|
||||
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
#[serde(alias = "ephemera_contract_address")]
|
||||
pub ephemera_contract_address: Option<String>,
|
||||
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
#[serde(alias = "service_provider_directory_contract_address")]
|
||||
pub service_provider_directory_contract_address: Option<String>,
|
||||
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
#[serde(alias = "name_service_contract_address")]
|
||||
pub name_service_contract_address: Option<String>,
|
||||
}
|
||||
|
||||
// I wanted to use the simpler `NetworkDetails` name, but there's a clash
|
||||
// with `NetworkDetails` defined in all.rs...
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, JsonSchema)]
|
||||
#[cfg_attr(feature = "wasm-serde-types", derive(Tsify))]
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(into_wasm_abi, from_wasm_abi))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NymNetworkDetails {
|
||||
#[serde(alias = "network_name")]
|
||||
pub network_name: String,
|
||||
|
||||
#[serde(alias = "chain_details")]
|
||||
pub chain_details: ChainDetails,
|
||||
|
||||
pub endpoints: Vec<ValidatorDetails>,
|
||||
|
||||
pub contracts: NymContracts,
|
||||
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
#[serde(alias = "explorer_api")]
|
||||
pub explorer_api: Option<String>,
|
||||
}
|
||||
|
||||
@@ -316,10 +373,17 @@ impl DenomDetails {
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Hash, Clone, PartialEq, Eq, JsonSchema)]
|
||||
#[cfg_attr(feature = "wasm-serde-types", derive(Tsify))]
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(into_wasm_abi, from_wasm_abi))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct DenomDetailsOwned {
|
||||
pub base: String,
|
||||
|
||||
pub display: String,
|
||||
|
||||
// i.e. display_amount * 10^display_exponent = base_amount
|
||||
#[serde(alias = "display_exponent")]
|
||||
pub display_exponent: u32,
|
||||
}
|
||||
|
||||
@@ -344,14 +408,24 @@ impl DenomDetailsOwned {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, JsonSchema)]
|
||||
#[cfg_attr(feature = "wasm-serde-types", derive(Tsify))]
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(into_wasm_abi, from_wasm_abi))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[non_exhaustive]
|
||||
pub struct ValidatorDetails {
|
||||
// it is assumed those values are always valid since they're being provided in our defaults file
|
||||
#[serde(alias = "nyxd_url")]
|
||||
pub nyxd_url: String,
|
||||
//
|
||||
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
#[serde(alias = "websocket_url")]
|
||||
pub websocket_url: Option<String>,
|
||||
|
||||
// Right now api_url is optional as we are not running the api reliably on all validators
|
||||
// however, later on it should be a mandatory field
|
||||
#[cfg_attr(feature = "wasm-serde-types", tsify(optional))]
|
||||
#[serde(alias = "api_url")]
|
||||
pub api_url: Option<String>,
|
||||
// TODO: I'd argue this one should also have a field like `gas_price` since its a validator-specific setting
|
||||
}
|
||||
@@ -373,16 +447,26 @@ impl ValidatorDetails {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_nyxd_url(&self) -> Result<Url, url::ParseError> {
|
||||
self.nyxd_url.parse()
|
||||
}
|
||||
|
||||
pub fn nyxd_url(&self) -> Url {
|
||||
self.nyxd_url
|
||||
.parse()
|
||||
self.try_nyxd_url()
|
||||
.expect("the provided nyxd url is invalid!")
|
||||
}
|
||||
|
||||
pub fn try_api_url(&self) -> Option<Result<Url, url::ParseError>> {
|
||||
self.api_url.as_ref().map(|url| url.parse())
|
||||
}
|
||||
|
||||
pub fn api_url(&self) -> Option<Url> {
|
||||
self.api_url
|
||||
.as_ref()
|
||||
.map(|url| url.parse().expect("the provided api url is invalid!"))
|
||||
self.try_api_url()
|
||||
.map(|url| url.expect("the provided api url is invalid!"))
|
||||
}
|
||||
|
||||
pub fn try_websocket_url(&self) -> Option<Result<Url, url::ParseError>> {
|
||||
self.websocket_url.as_ref().map(|url| url.parse())
|
||||
}
|
||||
|
||||
pub fn websocket_url(&self) -> Option<Url> {
|
||||
|
||||
@@ -37,11 +37,5 @@ wasm-utils = { path = "../utils" }
|
||||
wasm-storage = { path = "../storage" }
|
||||
|
||||
|
||||
# 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 = { version = "0.1", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
default = ["wasm-utils/console_error_panic_hook"]
|
||||
@@ -17,6 +17,12 @@ gloo-utils = { workspace = true }
|
||||
gloo-net = { version = "0.3.1", 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
|
||||
[dependencies.tungstenite]
|
||||
workspace = true
|
||||
@@ -29,6 +35,7 @@ optional = true
|
||||
|
||||
[features]
|
||||
default = ["sleep"]
|
||||
panic-hook = ["console_error_panic_hook"]
|
||||
sleep = ["web-sys", "web-sys/Window"]
|
||||
websocket = [
|
||||
"getrandom",
|
||||
|
||||
@@ -70,3 +70,15 @@ pub async fn sleep(ms: i32) -> Result<(), wasm_bindgen::JsValue> {
|
||||
js_fut.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[cfg(feature = "panic-hook")]
|
||||
pub fn set_panic_hook() {
|
||||
// When the `console_error_panic_hook` feature is enabled, we can call the
|
||||
// `set_panic_hook` function at least once during initialization, and then
|
||||
// we will get better error messages if our code ever panics.
|
||||
//
|
||||
// For more details see
|
||||
// https://github.com/rustwasm/console_error_panic_hook#readme
|
||||
console_error_panic_hook::set_once();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ wasm-bindgen = { workspace = true }
|
||||
wasm-bindgen-futures = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
console_error_panic_hook = { version = "0.1", optional = true }
|
||||
console_error_panic_hook = { workspace = true , optional = true }
|
||||
|
||||
wasm-utils = { path = "../../common/wasm/utils" }
|
||||
wasm-storage = { path = "../../common/wasm/storage" }
|
||||
|
||||
@@ -12,19 +12,3 @@ pub use error::ExtensionStorageError;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub use storage::ExtensionStorage;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[wasm_bindgen]
|
||||
pub fn set_panic_hook() {
|
||||
// When the `console_error_panic_hook` feature is enabled, we can call the
|
||||
// `set_panic_hook` function at least once during initialization, and then
|
||||
// we will get better error messages if our code ever panics.
|
||||
//
|
||||
// For more details see
|
||||
// https://github.com/rustwasm/console_error_panic_hook#readme
|
||||
#[cfg(feature = "console_error_panic_hook")]
|
||||
console_error_panic_hook::set_once();
|
||||
}
|
||||
|
||||
Generated
+11
@@ -962,6 +962,16 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console_error_panic_hook"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.5"
|
||||
@@ -7988,6 +7998,7 @@ dependencies = [
|
||||
name = "wasm-utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"futures",
|
||||
"getrandom 0.2.10",
|
||||
"gloo-net",
|
||||
|
||||
+7
-1
@@ -15,7 +15,13 @@
|
||||
"nym-connect/**",
|
||||
"explorer",
|
||||
"types",
|
||||
"clients/validator"
|
||||
"clients/validator",
|
||||
"sdk/typescript/packages/**",
|
||||
"sdk/typescript/examples/**",
|
||||
"sdk/typescript/codegen/**",
|
||||
"sdk/typescript/packages/**",
|
||||
"sdk/typescript/examples/**",
|
||||
"sdk/typescript/codegen/**"
|
||||
],
|
||||
"scripts": {
|
||||
"nuke": "npx rimraf **/node_modules node_modules",
|
||||
|
||||
@@ -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.
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "@nymproject/nym-credentials-example-parcel",
|
||||
"version": "1.0.4-rc.2",
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"build": "parcel build --no-cache --no-content-hash",
|
||||
"serve": "serve dist",
|
||||
"start": "parcel --no-cache"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nymproject/sdk": "1.2.4-rc.2",
|
||||
"parcel": "^2.9.3"
|
||||
},
|
||||
"private": false,
|
||||
"source": "src/index.html"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Internal Credential Tester</title>
|
||||
<script type="module" src="./index.ts"></script>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
padding: 2rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<h1>Credential</h1>
|
||||
<input id="mnemonic" placeholder="mnemonic"></input>
|
||||
<input id="coin" placeholder="amount" value="1unym"></input>
|
||||
<button id="button">Get Credential</button>
|
||||
<div id="credential"></div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,38 @@
|
||||
import { createNymCredentialsClient } from '@nymproject/sdk';
|
||||
import { appendOutput } from './utils';
|
||||
|
||||
async function main() {
|
||||
const mnemonic = document.getElementById('mnemonic') as HTMLInputElement;
|
||||
if (process.env.MNEMONIC) {
|
||||
mnemonic.defaultValue = process.env.MNEMONIC;
|
||||
}
|
||||
const coin = document.getElementById('coin') as HTMLInputElement;
|
||||
const button = document.getElementById('button') as HTMLButtonElement;
|
||||
|
||||
const client = await createNymCredentialsClient();
|
||||
|
||||
const generateCredential = async () => {
|
||||
const amount = coin.value;
|
||||
const mnemonicString = mnemonic.value;
|
||||
console.log({ amount, mnemonicString });
|
||||
try {
|
||||
appendOutput('About to get a credential... 🥁');
|
||||
const credential = await client.comlink.acquireCredential(amount, mnemonicString, { useSandbox: true }); // options: {useSandbox?: boolean; networkDetails?: {}}
|
||||
appendOutput('Success! 🎉');
|
||||
appendOutput(JSON.stringify(credential, null, 2));
|
||||
} catch (e) {
|
||||
console.error('Failed to get credential', e);
|
||||
appendOutput((e as any).message);
|
||||
}
|
||||
};
|
||||
|
||||
if (button) {
|
||||
button.addEventListener('click', () => generateCredential());
|
||||
}
|
||||
}
|
||||
|
||||
// wait for the html to load
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
// let's do this!
|
||||
main();
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
export function appendOutput(value: string) {
|
||||
const el = document.getElementById('credential') as HTMLPreElement;
|
||||
const text = document.createTextNode(`${value}\n`);
|
||||
el.appendChild(text);
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
src/mixnet/wasm/worker.js
|
||||
src/coconut/worker.js
|
||||
docs/
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
"scripts": {
|
||||
"build": "scripts/build-prod.sh",
|
||||
"build:dev": "scripts/build.sh",
|
||||
"build:dev:esm": "scripts/build-dev-esm.sh",
|
||||
"build:dev:esm": "SDK_DEV_MODE=true scripts/build-dev-esm.sh",
|
||||
"build:dev:esm:no-inline": "scripts/build-dev-esm.sh",
|
||||
"build:worker": "rollup -c rollup-worker.config.mjs",
|
||||
"clean": "rimraf dist",
|
||||
"docs:dev": "run-p docs:watch docs:serve ",
|
||||
@@ -32,6 +33,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@nymproject/nym-client-wasm": ">=1.2.4-rc.2 || ^1",
|
||||
"@nymproject/nym-credential-client-wasm": ">=1.2.0-rc.9 || ^1",
|
||||
"comlink": "^4.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { getConfig } from './rollup/worker.mjs';
|
||||
|
||||
export default {
|
||||
...getConfig('src/coconut/worker.ts', 'nym_credential_client_wasm_bg.wasm'),
|
||||
inlineWasm: true,
|
||||
format: 'cjs',
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import { getConfig } from './rollup/worker.mjs';
|
||||
|
||||
export default {
|
||||
...getConfig('src/coconut/worker.ts', 'nym_credential_client_wasm_bg.wasm', {
|
||||
inlineWasm: process.env.SDK_DEV_MODE === 'true',
|
||||
}),
|
||||
};
|
||||
@@ -2,6 +2,6 @@ import { getConfig } from './rollup/esm.mjs';
|
||||
|
||||
export default {
|
||||
...getConfig({
|
||||
inline: false,
|
||||
inline: process.env.SDK_DEV_MODE === 'true',
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { getConfig } from './rollup/worker.mjs';
|
||||
|
||||
export default {
|
||||
...getConfig('src/mixnet/wasm/worker.ts', 'nym_client_wasm_bg.wasm', {
|
||||
inlineWasm: true,
|
||||
format: 'cjs',
|
||||
}),
|
||||
};
|
||||
@@ -1,26 +1,7 @@
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import { wasm } from '@rollup/plugin-wasm';
|
||||
import replace from '@rollup/plugin-replace';
|
||||
|
||||
const extensions = ['.js', '.jsx', '.ts', '.tsx'];
|
||||
import { getConfig } from './rollup/worker.mjs';
|
||||
|
||||
export default {
|
||||
input: 'src/mixnet/wasm/worker.ts',
|
||||
output: {
|
||||
dir: 'dist',
|
||||
format: 'cjs',
|
||||
},
|
||||
plugins: [
|
||||
resolve({ extensions }),
|
||||
// this is some nasty monkey patching that removes the WASM URL (because it is handled by the `wasm` plugin)
|
||||
replace({
|
||||
values: { "input = new URL('nym_client_wasm_bg.wasm', import.meta.url);": 'input = undefined;' },
|
||||
delimiters: ['', ''],
|
||||
preventAssignment: true,
|
||||
}),
|
||||
// force the wasm plugin to embed the wasm bundle - this means no downstream bundlers have to worry about handling it
|
||||
wasm({ maxFileSize: 10000000, targetEnv: 'browser' }),
|
||||
typescript({ compilerOptions: { declaration: false, target: 'es5' } }),
|
||||
],
|
||||
...getConfig('src/mixnet/wasm/worker.ts', 'nym_client_wasm_bg.wasm', {
|
||||
inlineWasm: process.env.SDK_DEV_MODE === 'true',
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@ export const getConfig = (opts) => ({
|
||||
webWorkerLoader({ targetPlatform: 'browser', inline: opts.inline }), // the inline param is used here
|
||||
resolve({ extensions }),
|
||||
typescript({
|
||||
exclude: ['mixnet/wasm/worker.ts'],
|
||||
exclude: ['mixnet/wasm/worker.ts', 'coconut/worker.ts'],
|
||||
compilerOptions: { outDir: opts.outputDir || 'dist/esm' },
|
||||
}),
|
||||
],
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import { wasm } from '@rollup/plugin-wasm';
|
||||
import replace from '@rollup/plugin-replace';
|
||||
|
||||
const extensions = ['.js', '.jsx', '.ts', '.tsx'];
|
||||
|
||||
/**
|
||||
* Configure worker output
|
||||
*
|
||||
* @param opts
|
||||
* `format`: `es` or `cjs`,
|
||||
* `inlineWasm`: true or false,
|
||||
* `tsTarget`: `es5` or `es6`
|
||||
*/
|
||||
export const getConfig = (input, wasmFilename, opts) => ({
|
||||
input,
|
||||
output: {
|
||||
dir: 'dist',
|
||||
format: opts?.format || 'es',
|
||||
},
|
||||
plugins: [
|
||||
resolve({ extensions }),
|
||||
// this is some nasty monkey patching that removes the WASM URL (because it is handled by the `wasm` plugin)
|
||||
replace({
|
||||
values: { [`input = new URL('${wasmFilename}', import.meta.url);`]: 'input = undefined;' },
|
||||
delimiters: ['', ''],
|
||||
preventAssignment: true,
|
||||
}),
|
||||
opts?.inlineWasm === true
|
||||
? wasm({ maxFileSize: 10_000_000, targetEnv: 'browser' }) // force the wasm plugin to embed the wasm bundle - this means no downstream bundlers have to worry about handling it
|
||||
: wasm({
|
||||
targetEnv: 'browser',
|
||||
fileName: '[name].wasm',
|
||||
}),
|
||||
typescript({
|
||||
compilerOptions: {
|
||||
declaration: false,
|
||||
target: opts?.tsTarget || 'es6',
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
@@ -14,7 +14,21 @@ set -o pipefail
|
||||
rollup -c rollup-worker.config.mjs
|
||||
|
||||
# move it next to the Typescript `src/index.ts` so it can be inlined by rollup
|
||||
cp dist/worker.js src/worker/worker.js || true
|
||||
cp dist/worker.js src/mixnet/wasm/worker.js || true
|
||||
rm dist/worker.js || true
|
||||
|
||||
#-------------------------------------------------------
|
||||
# WEB WORKER (COCONUT WASM)
|
||||
#-------------------------------------------------------
|
||||
# The web worker needs to be bundled because the WASM bundle needs to be loaded synchronously and all dependencies
|
||||
# must be included in the worker script (because it is not loaded as an ES Module)
|
||||
|
||||
# build the worker
|
||||
rollup -c rollup-coconut-worker.config.mjs
|
||||
|
||||
# move it next to the Typescript `src/index.ts` so it can be inlined by rollup
|
||||
mkdir dist/esm || true
|
||||
cp dist/worker.js src/coconut/worker.js || true
|
||||
rm dist/worker.js || true
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
@@ -19,6 +19,19 @@ rollup -c rollup-worker.config.mjs
|
||||
rm -f src/mixnet/wasm/worker.js
|
||||
mv dist/worker.js src/mixnet/wasm/worker.js
|
||||
|
||||
#-------------------------------------------------------
|
||||
# WEB WORKER (COCONUT WASM)
|
||||
#-------------------------------------------------------
|
||||
# The web worker needs to be bundled because the WASM bundle needs to be loaded synchronously and all dependencies
|
||||
# must be included in the worker script (because it is not loaded as an ES Module)
|
||||
|
||||
# build the worker
|
||||
rollup -c rollup-coconut-worker.config.mjs
|
||||
|
||||
# move it next to the Typescript `src/index.ts` so it can be inlined by rollup
|
||||
cp dist/worker.js src/coconut/worker.js || true
|
||||
rm dist/worker.js || true
|
||||
|
||||
#-------------------------------------------------------
|
||||
# ESM
|
||||
#-------------------------------------------------------
|
||||
|
||||
@@ -1,7 +1,41 @@
|
||||
// eslint-disable-next-line no-console
|
||||
import * as Comlink from 'comlink';
|
||||
import InlineWasmWebWorker from 'web-worker:./worker';
|
||||
import { EventKinds, INymCredentialClientWebWorker, NymCredentialsClient } from './types';
|
||||
|
||||
export const createNymCredentialsClient = async (): Promise<NymCredentialsClient> => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
const worker = await createWorker();
|
||||
|
||||
// let comlink handle interop with the web worker
|
||||
const comlink = Comlink.wrap<INymCredentialClientWebWorker>(worker);
|
||||
|
||||
return { comlink };
|
||||
};
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* @internal
|
||||
* Async method to create a web worker that runs the Nym credentials client on another thread. It will only return once the worker
|
||||
* has passed back a `Loaded` event to the calling thread.
|
||||
*
|
||||
* @return The instance of the web worker.
|
||||
*/
|
||||
export const notImplementedYet = () => console.log('Not implement, coming soon...');
|
||||
const createWorker = async () =>
|
||||
new Promise<Worker>((resolve, reject) => {
|
||||
// rollup will inline the built worker script, so that when the SDK is used in
|
||||
// other projects, they will not need to mess around trying to bundle it
|
||||
// however, it will make this SDK bundle bigger because of Base64 inline data
|
||||
const worker = new InlineWasmWebWorker();
|
||||
|
||||
worker.addEventListener('error', reject);
|
||||
worker.addEventListener(
|
||||
'message',
|
||||
(msg) => {
|
||||
worker.removeEventListener('error', reject);
|
||||
if (msg.data?.kind === EventKinds.Loaded) {
|
||||
resolve(worker);
|
||||
} else {
|
||||
reject(msg);
|
||||
}
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Enum representing various event kinds.
|
||||
* @enum
|
||||
*/
|
||||
export enum EventKinds {
|
||||
Loaded = 'Loaded',
|
||||
}
|
||||
|
||||
export interface LoadedEvent {
|
||||
kind: EventKinds.Loaded;
|
||||
args: {
|
||||
loaded: true;
|
||||
};
|
||||
}
|
||||
|
||||
export type Credential = any; // TODO
|
||||
|
||||
export interface CredentialClientOpts {
|
||||
useSandbox?: boolean;
|
||||
networkDetails?: {};
|
||||
}
|
||||
|
||||
export interface INymCredentialClientWebWorker {
|
||||
acquireCredential: (coin: string, mnemonic: string, opts: CredentialClientOpts) => Promise<Credential>;
|
||||
}
|
||||
|
||||
// export interface NymCredentialsClient {
|
||||
// init: (mnemonic: string) => void;
|
||||
// acquireCredential: (coin: Coin, mnemonic: string, options?: CredentialsClientOpts) => Promise<Credentials>;
|
||||
// }
|
||||
|
||||
export interface NymCredentialsClient {
|
||||
comlink: INymCredentialClientWebWorker;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
import * as Comlink from 'comlink';
|
||||
//
|
||||
// Rollup will replace wasmBytes with a function that loads the WASM bundle from a base64 string embedded in the output.
|
||||
//
|
||||
// Doing it this way, saves having to support a large variety of bundlers and their quirks.
|
||||
//
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import wasmBytes from '@nymproject/nym-credential-client-wasm/nym_credential_client_wasm_bg.wasm';
|
||||
import init, { acquireCredential } from '@nymproject/nym-credential-client-wasm/nym_credential_client_wasm';
|
||||
import type { INymCredentialClientWebWorker, CredentialClientOpts, LoadedEvent } from './types';
|
||||
import { EventKinds } from './types';
|
||||
|
||||
/**
|
||||
* Helper method to send typed messages.
|
||||
* @param event The strongly typed message to send back to the calling thread.
|
||||
*/
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
const postMessageWithType = <E>(event: E) => self.postMessage(event);
|
||||
|
||||
console.log('[Nym WASM client for Credentials] Starting Nym WASM web worker...');
|
||||
|
||||
// load WASM binary
|
||||
async function main() {
|
||||
// rollup with provide a function to get the mixFetch WASM bytes
|
||||
const bytes = await wasmBytes();
|
||||
|
||||
// load rust WASM package
|
||||
const wasmPackage = await init(bytes);
|
||||
|
||||
console.log('Loaded RUST WASM');
|
||||
|
||||
wasmPackage.set_panic_hook();
|
||||
|
||||
const webWorker: INymCredentialClientWebWorker = {
|
||||
async acquireCredential(coin: string, mnemonic: string, opts: CredentialClientOpts) {
|
||||
console.log('[Worker] --- acquireCredential ---', { coin, mnemonic, opts });
|
||||
return acquireCredential(mnemonic, coin, opts);
|
||||
},
|
||||
};
|
||||
|
||||
// start comlink listening for messages and handle them above
|
||||
Comlink.expose(webWorker);
|
||||
|
||||
// notify any listeners that the web worker has loaded and is ready for testing
|
||||
postMessageWithType<LoadedEvent>({ kind: EventKinds.Loaded, args: { loaded: true } });
|
||||
}
|
||||
|
||||
main().catch((e: any) => console.error('Unhandled exception in credential worker', e));
|
||||
@@ -0,0 +1,119 @@
|
||||
Arguments:
|
||||
/Users/galacalero/.nvm/versions/node/v16.19.0/bin/node /Users/galacalero/.yarn/bin/yarn.js install
|
||||
|
||||
PATH:
|
||||
/Users/galacalero/.rvm/gems/ruby-2.7.5/bin:/Users/galacalero/.rvm/gems/ruby-2.7.5@global/bin:/Users/galacalero/.rvm/rubies/ruby-2.7.5/bin:/Users/galacalero/.rvm/bin:/Users/galacalero/.pyenv/shims:/Users/galacalero/.nvm/versions/node/v16.19.0/bin:/Users/galacalero/.yarn/bin:/Users/galacalero/.config/yarn/global/node_modules/.bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/Applications/Keybase.app/Contents/SharedSupport/bin:/Library/Apple/usr/bin:/Applications/Postgres.app/Contents/Versions/latest/bin:/Users/galacalero/.cargo/bin
|
||||
|
||||
Yarn version:
|
||||
1.22.18
|
||||
|
||||
Node version:
|
||||
16.19.0
|
||||
|
||||
Platform:
|
||||
darwin arm64
|
||||
|
||||
Trace:
|
||||
Error: https://registry.yarnpkg.com/@nymproject%2feslint-config-react-typescript: Not found
|
||||
at Request.params.callback [as _callback] (/Users/galacalero/.yarn/lib/cli.js:66138:18)
|
||||
at Request.self.callback (/Users/galacalero/.yarn/lib/cli.js:140883:22)
|
||||
at Request.emit (node:events:513:28)
|
||||
at Request.<anonymous> (/Users/galacalero/.yarn/lib/cli.js:141855:10)
|
||||
at Request.emit (node:events:513:28)
|
||||
at IncomingMessage.<anonymous> (/Users/galacalero/.yarn/lib/cli.js:141777:12)
|
||||
at Object.onceWrapper (node:events:627:28)
|
||||
at IncomingMessage.emit (node:events:525:35)
|
||||
at endReadableNT (node:internal/streams/readable:1358:12)
|
||||
at processTicksAndRejections (node:internal/process/task_queues:83:21)
|
||||
|
||||
npm manifest:
|
||||
{
|
||||
"name": "@nymproject/sdk",
|
||||
"version": "1.2.4-rc.2",
|
||||
"license": "Apache-2.0",
|
||||
"author": "Nym Technologies SA",
|
||||
"files": [
|
||||
"dist/esm/worker.js",
|
||||
"dist/cjs/worker.js",
|
||||
"dist/**/*"
|
||||
],
|
||||
"main": "dist/cjs/index.js",
|
||||
"browser": "dist/esm/index.js",
|
||||
"scripts": {
|
||||
"build": "scripts/build-prod.sh",
|
||||
"build:dev": "scripts/build.sh",
|
||||
"build:dev:esm": "scripts/build-dev-esm.sh",
|
||||
"build:worker": "rollup -c rollup-worker.config.mjs",
|
||||
"clean": "rimraf dist",
|
||||
"docs:dev": "run-p docs:watch docs:serve ",
|
||||
"docs:generate": "typedoc",
|
||||
"docs:generate:prod": "typedoc --basePath ./docs/tsdoc/nymproject/sdk/",
|
||||
"docs:prod:build": "scripts/build-prod-docs-collect.sh",
|
||||
"docs:serve": "reload -b -d ./docs -p 3000",
|
||||
"docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\"",
|
||||
"lint": "eslint src",
|
||||
"lint:fix": "eslint src --fix",
|
||||
"prebuild": "node scripts/showDependencyLocation.cjs",
|
||||
"start": "tsc -w",
|
||||
"start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'",
|
||||
"test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache",
|
||||
"tsc": "tsc --noEmit true"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nymproject/nym-client-wasm": ">=1.2.4-rc.2 || ^1",
|
||||
"comlink": "^4.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.15.0",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.14.5",
|
||||
"@babel/preset-env": "^7.15.0",
|
||||
"@babel/preset-react": "^7.14.5",
|
||||
"@babel/preset-typescript": "^7.15.0",
|
||||
"@nymproject/eslint-config-react-typescript": "^1.0.0",
|
||||
"@rollup/plugin-commonjs": "^24.0.1",
|
||||
"@rollup/plugin-inject": "^5.0.3",
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
"@rollup/plugin-replace": "^5.0.2",
|
||||
"@rollup/plugin-terser": "^0.2.1",
|
||||
"@rollup/plugin-typescript": "^10.0.1",
|
||||
"@rollup/plugin-url": "^8.0.1",
|
||||
"@rollup/plugin-wasm": "^6.1.1",
|
||||
"@types/jest": "^27.0.1",
|
||||
"@types/node": "^16.7.13",
|
||||
"@typescript-eslint/eslint-plugin": "^5.13.0",
|
||||
"@typescript-eslint/parser": "^5.13.0",
|
||||
"eslint": "^8.10.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-airbnb-typescript": "^16.1.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-import-resolver-root-import": "^1.0.4",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-plugin-jest": "^26.1.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.5.1",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-react": "^7.29.2",
|
||||
"eslint-plugin-react-hooks": "^4.3.0",
|
||||
"handlebars": "^4.7.8",
|
||||
"jest": "^29.5.0",
|
||||
"nodemon": "3.0.1",
|
||||
"reload": "^3.2.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "^3.9.1",
|
||||
"rollup-plugin-base64": "^1.0.1",
|
||||
"rollup-plugin-web-worker-loader": "^1.6.1",
|
||||
"ts-jest": "^29.1.0",
|
||||
"ts-loader": "^9.4.2",
|
||||
"typedoc": "^0.24.8",
|
||||
"typescript": "^4.8.4"
|
||||
},
|
||||
"private": false,
|
||||
"type": "module",
|
||||
"types": "./dist/esm/index.d.ts"
|
||||
}
|
||||
|
||||
yarn manifest:
|
||||
No manifest
|
||||
|
||||
Lockfile:
|
||||
No lockfile
|
||||
@@ -0,0 +1,43 @@
|
||||
[package]
|
||||
name = "nym-credential-client-wasm"
|
||||
authors = []
|
||||
version = "1.3.0-rc.0"
|
||||
edition = "2021"
|
||||
keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"]
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/nymtech/nym"
|
||||
description = "A webassembly client which can be used to issue Coconut credentials."
|
||||
rust-version = "1.56"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
bip39 = { workspace = true }
|
||||
#futures = { workspace = true }
|
||||
js-sys = { workspace = true }
|
||||
#rand = { version = "0.7.3", features = ["wasm-bindgen"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
#serde_json = { workspace = true }
|
||||
serde-wasm-bindgen = { workspace = true }
|
||||
wasm-bindgen = { workspace = true }
|
||||
wasm-bindgen-futures = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tsify = { workspace = true, features = ["js"] }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
wasm-utils = { path = "../../common/wasm/utils", features = ["panic-hook"] }
|
||||
|
||||
nym-bin-common = { path = "../../common/bin-common" }
|
||||
nym-credentials = { path = "../../common/credentials" }
|
||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
|
||||
nym-validator-client = { path = "../../common/client-libs/validator-client", default-features = false }
|
||||
nym-credentials-interface = { path = "../../common/credentials-interface" }
|
||||
nym-network-defaults = { path = "../../common/network-defaults" }
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.36"
|
||||
|
||||
[package.metadata.wasm-pack.profile.release]
|
||||
wasm-opt = false
|
||||
@@ -0,0 +1,7 @@
|
||||
build:
|
||||
wasm-pack build --scope nymproject --target web --out-dir ../../dist/wasm/credentials
|
||||
wasm-opt -Oz -o ../../dist/wasm/credentials/nym_credential_client_wasm_bg.wasm ../../dist/wasm/credentials/nym_credential_client_wasm_bg.wasm
|
||||
|
||||
# make my life easier so I wouldn't need to deal with any bundlers. sorry @MS : )
|
||||
build-debug-dev:
|
||||
wasm-pack build --scope nymproject --target no-modules
|
||||
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
dist
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
// A dependency graph that contains any wasm must all be imported
|
||||
// asynchronously. This `bootstrap.js` file does the single async import, so
|
||||
// that no one else needs to worry about it again.
|
||||
import('./index.js')
|
||||
.catch(e => console.error('Error importing `index.js`:', e));
|
||||
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Nym Credentials WebAssembly Demo</title>
|
||||
<script src="bootstrap.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1> Yet another coconut demo </h1>
|
||||
<div>
|
||||
<label>mnemonic: </label>
|
||||
<input type="text" size = "120" id="mnemonic" value="...">
|
||||
|
||||
</br>
|
||||
</br>
|
||||
|
||||
<label>amount (in <b>unym</b>): </label>
|
||||
<input type="number" size = "60" id="credential-amount" value=0>
|
||||
|
||||
<button id="coconut-button"> Get Coconut Credential </button>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<span id="output"></span>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright 2020-2023 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
class WebWorkerClient {
|
||||
worker = null;
|
||||
|
||||
constructor() {
|
||||
this.worker = new Worker('./worker.js');
|
||||
|
||||
this.worker.onmessage = (ev) => {
|
||||
if (ev.data && ev.data.kind) {
|
||||
switch (ev.data.kind) {
|
||||
case 'ReceivedCredential':
|
||||
const { credential } = ev.data.args;
|
||||
displayCredential(credential)
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
getCredential = (amount, mnemonic) => {
|
||||
if (!this.worker) {
|
||||
console.error('Could not get credential because worker does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.postMessage({
|
||||
kind: 'GetCredential',
|
||||
args: {
|
||||
amount,
|
||||
mnemonic
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
let client = null;
|
||||
|
||||
async function main() {
|
||||
client = new WebWorkerClient();
|
||||
|
||||
const coconutButton = document.querySelector('#coconut-button');
|
||||
coconutButton.onclick = function () {
|
||||
getCredential();
|
||||
};
|
||||
}
|
||||
|
||||
async function getCredential() {
|
||||
const amount = document.getElementById('credential-amount').value;
|
||||
const mnemonic = document.getElementById('mnemonic').value;
|
||||
|
||||
await client.getCredential(amount, mnemonic);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function displayCredential(credential) {
|
||||
console.log("got credential", credential)
|
||||
|
||||
let timestamp = new Date().toISOString().substr(11, 12);
|
||||
|
||||
let credentialDiv = document.createElement('div');
|
||||
let paragraph = document.createElement('p');
|
||||
paragraph.setAttribute('style', 'color: blue');
|
||||
let paragraphContent = document.createTextNode(timestamp + ' 🥥🥥🥥 >>> ' + JSON.stringify(credential));
|
||||
paragraph.appendChild(paragraphContent);
|
||||
|
||||
credentialDiv.appendChild(paragraph);
|
||||
document.getElementById('output').appendChild(credentialDiv);
|
||||
}
|
||||
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "create-wasm-app",
|
||||
"version": "0.1.0",
|
||||
"description": "create an app to consume rust-generated wasm packages",
|
||||
"main": "index.js",
|
||||
"bin": {
|
||||
"create-wasm-app": ".bin/create-wasm-app.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"build:wasm": "cd ../ && make wasm-build",
|
||||
"start": "webpack-dev-server --port 8001"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/rustwasm/create-wasm-app.git"
|
||||
},
|
||||
"keywords": [
|
||||
"webassembly",
|
||||
"wasm",
|
||||
"rust",
|
||||
"webpack"
|
||||
],
|
||||
"author": "Gala Calero <https://github.com/gala1234>",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/nymtech/nym/issues"
|
||||
},
|
||||
"homepage": "https://nymtech.net/docs",
|
||||
"devDependencies": {
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"hello-wasm-pack": "^0.1.0",
|
||||
"webpack": "^5.70.0",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-dev-server": "^4.7.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nymproject/nym-credential-client-wasm": "file:../pkg"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
performance: {
|
||||
hints: false,
|
||||
maxEntrypointSize: 512000,
|
||||
maxAssetSize: 512000,
|
||||
},
|
||||
entry: {
|
||||
bootstrap: "./bootstrap.js",
|
||||
worker: "./worker.js",
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
filename: "[name].js",
|
||||
},
|
||||
mode: "development",
|
||||
// mode: 'production',
|
||||
plugins: [
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
"index.html",
|
||||
{
|
||||
from: "../pkg/*.(js|wasm)",
|
||||
to: "[name][ext]",
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
devServer: {
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'https://sandbox-nym-api1.nymtech.net/',
|
||||
secure: false,
|
||||
},
|
||||
},
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
|
||||
"Access-Control-Allow-Headers":
|
||||
"X-Requested-With, content-type, Authorization",
|
||||
},
|
||||
},
|
||||
experiments: { syncWebAssembly: true },
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright 2020-2023 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
const RUST_WASM_URL = "nym_credential_client_wasm_bg.wasm"
|
||||
|
||||
importScripts('nym_credential_client_wasm.js');
|
||||
|
||||
console.log('Initializing worker');
|
||||
|
||||
// wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts`
|
||||
const {
|
||||
acquireCredential,
|
||||
} = wasm_bindgen;
|
||||
|
||||
async function testGetCredential() {
|
||||
self.onmessage = async event => {
|
||||
if (event.data && event.data.kind) {
|
||||
switch (event.data.kind) {
|
||||
case 'GetCredential': {
|
||||
const { amount, mnemonic } = event.data.args;
|
||||
|
||||
// TODO: this should just use cosmjs' coin
|
||||
let coin = `${amount}unym`
|
||||
console.log(`getting credential for ${coin}`);
|
||||
|
||||
let credential = await acquireCredential(mnemonic, coin, { useSandbox: true })
|
||||
|
||||
self.postMessage({
|
||||
kind : 'ReceivedCredential',
|
||||
args: {
|
||||
credential
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log(">>>>>>>>>>>>>>>>>>>>> JS WORKER MAIN START");
|
||||
|
||||
// load rust WASM package
|
||||
await wasm_bindgen(RUST_WASM_URL);
|
||||
console.log('Loaded RUST WASM');
|
||||
|
||||
// run test on simplified and dedicated tester:
|
||||
await testGetCredential();
|
||||
//
|
||||
console.log(">>>>>>>>>>>>>>>>>>>>> JS WORKER MAIN END")
|
||||
}
|
||||
|
||||
// Let's get started!
|
||||
main();
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,123 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::WasmCredentialClientError;
|
||||
use crate::opts::CredentialClientOpts;
|
||||
use js_sys::Promise;
|
||||
use nym_credential_storage::ephemeral_storage::EphemeralCredentialStorage;
|
||||
use nym_credential_storage::models::StoredIssuedCredential;
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use nym_validator_client::nyxd::{Config, CosmWasmCoin};
|
||||
use nym_validator_client::DirectSigningReqwestRpcNyxdClient;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tsify::Tsify;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_futures::future_to_promise;
|
||||
use wasm_utils::console_log;
|
||||
use wasm_utils::error::PromisableResult;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
#[wasm_bindgen(js_name = acquireCredential)]
|
||||
pub fn acquire_credential(mnemonic: String, amount: String, opts: CredentialClientOpts) -> Promise {
|
||||
future_to_promise(async move {
|
||||
acquire_credential_async(mnemonic, amount, opts)
|
||||
.await
|
||||
.map(|credential| {
|
||||
serde_wasm_bindgen::to_value(&credential).expect("this serialization can't fail")
|
||||
})
|
||||
.into_promise_result()
|
||||
})
|
||||
}
|
||||
|
||||
async fn acquire_credential_async(
|
||||
mnemonic: String,
|
||||
amount: String,
|
||||
opts: CredentialClientOpts,
|
||||
) -> Result<WasmIssuedCredential, WasmCredentialClientError> {
|
||||
// start by parsing mnemonic so that we could immediately move it into a Zeroizing wrapper
|
||||
let mnemonic = crate::helpers::parse_mnemonic(mnemonic)?;
|
||||
|
||||
// why are we parsing into CosmWasmCoin and not "our" Coin?
|
||||
// simple. because it has the nicest 'FromStr' impl
|
||||
let amount: CosmWasmCoin =
|
||||
amount
|
||||
.parse()
|
||||
.map_err(|source| WasmCredentialClientError::MalformedCoin {
|
||||
source: Box::new(source),
|
||||
})?;
|
||||
|
||||
if amount.amount.is_zero() {
|
||||
return Err(WasmCredentialClientError::ZeroCoinValue);
|
||||
}
|
||||
|
||||
let network = match opts.network_details {
|
||||
Some(specified) => specified,
|
||||
None => {
|
||||
if let Some(true) = opts.use_sandbox {
|
||||
crate::helpers::minimal_coconut_sandbox()
|
||||
} else {
|
||||
NymNetworkDetails::new_mainnet()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let config = Config::try_from_nym_network_details(&network)?;
|
||||
|
||||
// just get the first nyxd endpoint
|
||||
let nyxd_endpoint = network
|
||||
.endpoints
|
||||
.get(0)
|
||||
.ok_or(WasmCredentialClientError::NoNyxdEndpoints)?
|
||||
.try_nyxd_url()?;
|
||||
|
||||
let client = DirectSigningReqwestRpcNyxdClient::connect_reqwest_with_mnemonic(
|
||||
config,
|
||||
nyxd_endpoint,
|
||||
mnemonic,
|
||||
);
|
||||
|
||||
console_log!("starting the deposit...");
|
||||
let deposit_state = nym_bandwidth_controller::acquire::deposit(&client, amount).await?;
|
||||
let blinded_serial = deposit_state.voucher.blinded_serial_number_bs58();
|
||||
console_log!(
|
||||
"obtained bandwidth voucher with the following blinded serial number: {blinded_serial}"
|
||||
);
|
||||
|
||||
// TODO: use proper persistent storage here. probably indexeddb like we have for our 'normal' wasm client
|
||||
let ephemeral_storage = EphemeralCredentialStorage::default();
|
||||
|
||||
// store credential in the ephemeral storage...
|
||||
nym_bandwidth_controller::acquire::get_bandwidth_voucher(
|
||||
&deposit_state,
|
||||
&client,
|
||||
&ephemeral_storage,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// and immediately get it out!
|
||||
let mut credentials = ephemeral_storage.take_credentials().await;
|
||||
let cred = credentials.pop().expect("we just got a credential issued");
|
||||
|
||||
Ok(cred.into())
|
||||
}
|
||||
|
||||
#[derive(Tsify, Debug, Clone, Serialize, Deserialize, Zeroize, ZeroizeOnDrop)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct WasmIssuedCredential {
|
||||
pub serialization_revision: u8,
|
||||
pub credential_data: Vec<u8>,
|
||||
pub credential_type: String,
|
||||
pub epoch_id: u32,
|
||||
}
|
||||
|
||||
impl From<StoredIssuedCredential> for WasmIssuedCredential {
|
||||
fn from(value: StoredIssuedCredential) -> Self {
|
||||
WasmIssuedCredential {
|
||||
serialization_revision: value.serialization_revision,
|
||||
credential_data: value.credential_data.clone(),
|
||||
credential_type: value.credential_type.clone(),
|
||||
epoch_id: value.epoch_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use js_sys::Promise;
|
||||
use nym_bandwidth_controller::error::BandwidthControllerError;
|
||||
use nym_network_defaults::UrlParseError;
|
||||
use nym_validator_client::nyxd::error::NyxdError;
|
||||
use thiserror::Error;
|
||||
use wasm_utils::wasm_error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WasmCredentialClientError {
|
||||
#[error(transparent)]
|
||||
BandwidthControllerError {
|
||||
#[from]
|
||||
source: BandwidthControllerError,
|
||||
},
|
||||
|
||||
#[error("the passed credential value had a value of zero")]
|
||||
ZeroCoinValue,
|
||||
|
||||
#[error("failed to use credential storage: {source}")]
|
||||
StorageError {
|
||||
#[from]
|
||||
source: nym_credential_storage::error::StorageError,
|
||||
},
|
||||
|
||||
#[error(transparent)]
|
||||
NyxdFailure {
|
||||
#[from]
|
||||
source: NyxdError,
|
||||
},
|
||||
|
||||
#[error("no nyxd endpoints have been provided - we can't interact with the chain")]
|
||||
NoNyxdEndpoints,
|
||||
|
||||
#[error("the provided nyxd endpoint is malformed: {source}")]
|
||||
MalformedNyxdEndpoint {
|
||||
#[from]
|
||||
source: UrlParseError,
|
||||
},
|
||||
|
||||
// #[error("The provided deposit value was malformed: {source}")]
|
||||
// MalformedCoin { source: serde_wasm_bindgen::Error },
|
||||
#[error("The provided deposit value was malformed: {source}")]
|
||||
// annoyingly cosmwasm hasn't exposed CoinFromStrError directly
|
||||
// so we have to rely on the dynamic dispatch here
|
||||
MalformedCoin { source: Box<dyn std::error::Error> },
|
||||
|
||||
// #[error("Coin parse error")]
|
||||
// CoinParseError,
|
||||
// #[error("State error")]
|
||||
// StateError,
|
||||
#[error("The provided mnemonic was malformed: {source}")]
|
||||
MalformedMnemonic {
|
||||
#[from]
|
||||
source: bip39::Error,
|
||||
},
|
||||
}
|
||||
|
||||
wasm_error!(WasmCredentialClientError);
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::WasmCredentialClientError;
|
||||
use nym_network_defaults::{NymContracts, NymNetworkDetails, ValidatorDetails};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
pub(crate) fn parse_mnemonic(raw: String) -> Result<bip39::Mnemonic, WasmCredentialClientError> {
|
||||
// make sure that whatever happens, the raw value gets zeroized
|
||||
let wrapped = Zeroizing::new(raw);
|
||||
Ok(bip39::Mnemonic::parse(&*wrapped)?)
|
||||
}
|
||||
|
||||
pub(crate) fn minimal_coconut_sandbox() -> NymNetworkDetails {
|
||||
// we can piggyback on mainnet defaults for certain things,
|
||||
// since sandbox uses the same network name, denoms, etc.
|
||||
let default_mainnet = NymNetworkDetails::new_mainnet();
|
||||
|
||||
NymNetworkDetails {
|
||||
network_name: default_mainnet.network_name,
|
||||
chain_details: default_mainnet.chain_details,
|
||||
endpoints: vec![ValidatorDetails::new(
|
||||
"https://sandbox-validator1.nymtech.net",
|
||||
None,
|
||||
None,
|
||||
)],
|
||||
contracts: NymContracts {
|
||||
coconut_bandwidth_contract_address: Some(
|
||||
"n16a32stm6kknhq5cc8rx77elr66pygf2hfszw7wvpq746x3uffylqkjar4l".into(),
|
||||
),
|
||||
coconut_dkg_contract_address: Some(
|
||||
"n1ahg0erc2fs6xx3j5m8sfx3ryuzdjh6kf6qm9plsf865fltekyrfsesac6a".into(),
|
||||
),
|
||||
// we don't need other contracts for getting credential
|
||||
..Default::default()
|
||||
},
|
||||
explorer_api: None,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
mod credential;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
mod error;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
mod helpers;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
mod opts;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen(start)]
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn main() {
|
||||
wasm_utils::console_log!("[rust main]: rust module loaded");
|
||||
wasm_utils::console_log!(
|
||||
"credential client version used: {:#?}",
|
||||
nym_bin_common::bin_info!()
|
||||
);
|
||||
wasm_utils::console_log!("[rust main]: setting panic hook");
|
||||
wasm_utils::set_panic_hook();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tsify::Tsify;
|
||||
|
||||
#[derive(Tsify, Debug, Clone, Serialize, Deserialize)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CredentialClientOpts {
|
||||
#[tsify(optional)]
|
||||
pub network_details: Option<NymNetworkDetails>,
|
||||
|
||||
#[tsify(optional)]
|
||||
pub use_sandbox: Option<bool>,
|
||||
}
|
||||
Reference in New Issue
Block a user