removed legacy nym-vpn-lib-wasm
This commit is contained in:
@@ -1,42 +0,0 @@
|
||||
name: ci-build-vpn-api-wasm
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'common/**'
|
||||
- 'nym-credential-proxy/**'
|
||||
- '.github/workflows/ci-build-vpn-api-wasm.yml'
|
||||
|
||||
jobs:
|
||||
wasm:
|
||||
runs-on: arc-linux-latest
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: ${{ vars.REQUIRED_RUSTC_VERSION }}
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
|
||||
- name: Install wasm-opt
|
||||
uses: ./.github/actions/install-wasm-opt
|
||||
with:
|
||||
version: '116'
|
||||
|
||||
- name: Install wasm-bindgen-cli
|
||||
run: cargo install wasm-bindgen-cli
|
||||
|
||||
- name: "Build"
|
||||
run: make
|
||||
working-directory: nym-credential-proxy/vpn-api-lib-wasm
|
||||
Generated
-24
@@ -8302,30 +8302,6 @@ dependencies = [
|
||||
"ts-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-vpn-api-lib-wasm"
|
||||
version = "1.20.4"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"js-sys",
|
||||
"nym-bin-common",
|
||||
"nym-compact-ecash",
|
||||
"nym-credential-proxy-requests",
|
||||
"nym-credentials",
|
||||
"nym-credentials-interface",
|
||||
"nym-crypto",
|
||||
"nym-ecash-time",
|
||||
"nym-wasm-utils",
|
||||
"serde",
|
||||
"serde-wasm-bindgen 0.6.5",
|
||||
"serde_json",
|
||||
"thiserror 2.0.12",
|
||||
"time",
|
||||
"tsify",
|
||||
"wasm-bindgen",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-wallet-types"
|
||||
version = "1.0.0"
|
||||
|
||||
@@ -129,7 +129,6 @@ members = [
|
||||
"nym-browser-extension/storage",
|
||||
"nym-credential-proxy/nym-credential-proxy",
|
||||
"nym-credential-proxy/nym-credential-proxy-requests",
|
||||
"nym-credential-proxy/vpn-api-lib-wasm",
|
||||
"nym-data-observatory",
|
||||
"nym-ip-packet-client",
|
||||
"nym-network-monitor",
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
[package]
|
||||
name = "nym-vpn-api-lib-wasm"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
bs58 = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
time = { workspace = true, features = ["wasm-bindgen"] }
|
||||
thiserror.workspace = true
|
||||
zeroize = { workspace = true }
|
||||
|
||||
# wasm-specific deps
|
||||
wasm-bindgen = { workspace = true }
|
||||
js-sys = { workspace = true }
|
||||
tsify = { workspace = true, features = ["js"] }
|
||||
serde-wasm-bindgen = { workspace = true }
|
||||
|
||||
# NYM:
|
||||
nym-bin-common = { workspace = true }
|
||||
nym-crypto = { workspace = true, features = ["asymmetric"] }
|
||||
nym-compact-ecash = { workspace = true }
|
||||
nym-credentials = { workspace = true }
|
||||
nym-credentials-interface = { workspace = true }
|
||||
nym-ecash-time = { workspace = true, features = ["expiration"] }
|
||||
nym-credential-proxy-requests = { workspace = true, features = ["tsify"] }
|
||||
nym-wasm-utils = { workspace = true }
|
||||
@@ -1,4 +0,0 @@
|
||||
build:
|
||||
wasm-pack build --scope nymproject --target web --out-dir ../../dist/wasm/nym-vpn-api-lib-wasm
|
||||
wasm-opt -Oz -o ../../dist/wasm/nym-vpn-api-lib-wasm/nym_vpn_api_lib_wasm_bg.wasm ../../dist/wasm/nym-vpn-api-lib-wasm/nym_vpn_api_lib_wasm_bg.wasm
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
import("./index.js")
|
||||
.catch(e => console.error("Error importing `index.js`:", e));
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Nym WebAssembly Demo</title>
|
||||
<script src="bootstrap.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>everything happens in the console</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,49 +0,0 @@
|
||||
import init, { NymIssuanceTicketbook } from "@nymproject/nym-vpn-api-lib-wasm";
|
||||
|
||||
async function main() {
|
||||
await init();
|
||||
|
||||
let cryptoData = new NymIssuanceTicketbook({});
|
||||
|
||||
console.log("getting partial vks");
|
||||
const partialVksRes = await fetch("http://localhost:8080/api/v1/ticketbook/partial-verification-keys", {
|
||||
headers: new Headers({ "Authorization": "Bearer foomp" })
|
||||
});
|
||||
const partialVks = await partialVksRes.json();
|
||||
console.debug(partialVks);
|
||||
|
||||
console.log("getting master vk");
|
||||
const masterVkRes = await fetch("http://localhost:8080/api/v1/ticketbook/master-verification-key", {
|
||||
headers: new Headers({ "Authorization": "Bearer foomp" })
|
||||
});
|
||||
const masterVk = await masterVkRes.json();
|
||||
console.debug(masterVk);
|
||||
|
||||
let request = cryptoData.buildRequestPayload(false);
|
||||
console.log(request);
|
||||
|
||||
|
||||
console.log("getting blinded wallet shares");
|
||||
const sharesRes = await fetch("http://localhost:8080/api/v1/ticketbook/obtain?include-coin-index-signatures=true&include-expiration-date-signatures=true", {
|
||||
method: "POST",
|
||||
headers: new Headers(
|
||||
{
|
||||
"Authorization": "Bearer foomp",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
),
|
||||
body: request
|
||||
});
|
||||
|
||||
const credentialShares = await sharesRes.json();
|
||||
console.log(credentialShares);
|
||||
|
||||
console.log("unblinding shares");
|
||||
const unblinded = cryptoData.unblindWalletShares(credentialShares, partialVks, masterVk);
|
||||
|
||||
const serialised = unblinded.serialise();
|
||||
console.log("serialised:\n", serialised);
|
||||
}
|
||||
|
||||
|
||||
main();
|
||||
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"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": "Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||
"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": "^5.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nymproject/nym-vpn-api-lib-wasm": "file:../../../dist/wasm/nym-vpn-api-lib-wasm"
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
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: "../../../dist/wasm/nym-vpn-api-lib-wasm/*.(js|wasm)",
|
||||
to: "[name][ext]"
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
],
|
||||
experiments: { syncWebAssembly: true }
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,35 +0,0 @@
|
||||
// Copyright 2024 Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use nym_wasm_utils::wasm_error;
|
||||
use serde_wasm_bindgen::Error;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum VpnApiLibError {
|
||||
#[error("{0}")]
|
||||
Json(String),
|
||||
|
||||
#[error("[ecash] cryptographic failure: {source}")]
|
||||
EcashFailure {
|
||||
#[from]
|
||||
source: nym_compact_ecash::CompactEcashError,
|
||||
},
|
||||
|
||||
#[error("provided invalid ticket type")]
|
||||
MalformedTicketType,
|
||||
|
||||
#[error("the provided shares and issuers are not from the same epoch! {shares} and {issuers}")]
|
||||
InconsistentEpochId { shares: u64, issuers: u64 },
|
||||
|
||||
#[error("failed to recover ed25519 private key from its base58 representation")]
|
||||
MalformedEd25519Key,
|
||||
}
|
||||
|
||||
wasm_error!(VpnApiLibError);
|
||||
|
||||
impl From<serde_wasm_bindgen::Error> for VpnApiLibError {
|
||||
fn from(value: Error) -> Self {
|
||||
VpnApiLibError::Json(value.to_string())
|
||||
}
|
||||
}
|
||||
@@ -1,277 +0,0 @@
|
||||
// Copyright 2024 Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::error::VpnApiLibError;
|
||||
use nym_compact_ecash::scheme::keygen::KeyPairUser;
|
||||
use nym_compact_ecash::scheme::withdrawal::RequestInfo;
|
||||
use nym_compact_ecash::{
|
||||
Base58, BlindedSignature, VerificationKeyAuth, WithdrawalRequest, aggregate_wallets,
|
||||
issue_verify, withdrawal_request,
|
||||
};
|
||||
use nym_credential_proxy_requests::api::v1::ticketbook::models::{
|
||||
MasterVerificationKeyResponse, PartialVerificationKeysResponse, TicketbookRequest,
|
||||
TicketbookWalletSharesResponse, WalletShare,
|
||||
};
|
||||
use nym_credentials::{
|
||||
AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, EpochVerificationKey,
|
||||
IssuedTicketBook,
|
||||
};
|
||||
use nym_credentials_interface::TicketType;
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_ecash_time::{EcashTime, ecash_default_expiration_date};
|
||||
use nym_wasm_utils::console_error;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use time::Date;
|
||||
use tsify::Tsify;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
pub mod error;
|
||||
|
||||
#[derive(Tsify, Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct WalletShares(Vec<WalletShare>);
|
||||
|
||||
pub type WalletIssuers = PartialVerificationKeysResponse;
|
||||
|
||||
impl From<Vec<WalletShare>> for WalletShares {
|
||||
fn from(shares: Vec<WalletShare>) -> Self {
|
||||
WalletShares(shares)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Tsify, Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct NymIssuanceTicketbookOpts {
|
||||
#[tsify(optional)]
|
||||
pub ticketbook_type: Option<String>,
|
||||
|
||||
// bs58-encoded user secret key used for seeding the ecash crypto keypair generation
|
||||
// I reiterate, this is a **SECRET** key, not a public key.
|
||||
#[tsify(optional)]
|
||||
pub user_secret_key: Option<String>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub struct NymIssuanceTicketbook {
|
||||
/// ecash keypair related to the credential
|
||||
ecash_keypair: KeyPairUser,
|
||||
|
||||
withdrawal_request: WithdrawalRequest,
|
||||
|
||||
ticketbook_type: TicketType,
|
||||
|
||||
expiration_date: Date,
|
||||
|
||||
request_info: Zeroizing<RequestInfo>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl NymIssuanceTicketbook {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(opts: NymIssuanceTicketbookOpts) -> Result<NymIssuanceTicketbook, VpnApiLibError> {
|
||||
let ecash_keypair = match opts.user_secret_key {
|
||||
None => KeyPairUser::new(),
|
||||
Some(maybe_sk) => {
|
||||
let pk = ed25519::PrivateKey::from_base58_string(maybe_sk)
|
||||
.map(Zeroizing::new)
|
||||
.map_err(|_| VpnApiLibError::MalformedEd25519Key)?;
|
||||
let bytes = Zeroizing::new(pk.to_bytes());
|
||||
KeyPairUser::new_seeded(&bytes)
|
||||
}
|
||||
};
|
||||
|
||||
let ticketbook_type = match opts.ticketbook_type {
|
||||
None => TicketType::V1MixnetEntry,
|
||||
Some(typ) => typ
|
||||
.parse()
|
||||
.map_err(|_| VpnApiLibError::MalformedTicketType)?,
|
||||
};
|
||||
|
||||
let expiration_date = ecash_default_expiration_date();
|
||||
|
||||
let (withdrawal_request, request_info) = withdrawal_request(
|
||||
ecash_keypair.secret_key(),
|
||||
expiration_date.ecash_unix_timestamp(),
|
||||
ticketbook_type.encode(),
|
||||
)?;
|
||||
|
||||
Ok(NymIssuanceTicketbook {
|
||||
ecash_keypair,
|
||||
withdrawal_request,
|
||||
ticketbook_type,
|
||||
expiration_date,
|
||||
request_info: Zeroizing::new(request_info),
|
||||
})
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "buildRequestPayload")]
|
||||
pub fn build_request_payload(&self, is_freepass_request: bool) -> String {
|
||||
serde_json::to_string(&TicketbookRequest {
|
||||
withdrawal_request: self.withdrawal_request.clone().into(),
|
||||
ecash_pubkey: self.ecash_keypair.public_key(),
|
||||
expiration_date: self.expiration_date,
|
||||
ticketbook_type: self.ticketbook_type,
|
||||
is_freepass_request,
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getWithdrawalRequest")]
|
||||
pub fn get_encoded_withdrawal_request(&self) -> String {
|
||||
self.withdrawal_request.to_bs58()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getEncodedPublicKey")]
|
||||
pub fn get_encoded_public_key(&self) -> String {
|
||||
self.ecash_keypair.public_key().to_bs58()
|
||||
}
|
||||
|
||||
//
|
||||
// #[wasm_bindgen(js_name = "unblindShare")]
|
||||
// pub fn unblind_share(&self, share: UnblindableShare) -> Result<CredentialWrapper, ZkNymError> {
|
||||
// let blinded_sig = BlindedSignature::try_from_bs58(share.blinded_share_bs58)?;
|
||||
// let vk = VerificationKey::try_from_bs58(share.issuer_key_bs58)?;
|
||||
//
|
||||
// Ok(blinded_sig
|
||||
// .unblind(&vk, &self.pedersen_commitments_openings)
|
||||
// .into())
|
||||
// }
|
||||
//
|
||||
#[wasm_bindgen(js_name = "unblindWalletShares")]
|
||||
pub fn unblind_wallet_shares(
|
||||
self,
|
||||
shares: JsValue,
|
||||
issuers: WalletIssuers,
|
||||
master_key: MasterVerificationKeyResponse,
|
||||
) -> Result<NymIssuedTicketbook, VpnApiLibError> {
|
||||
// we couldn't derive all the required abi traits due to crypto types deep in the stack
|
||||
let shares: TicketbookWalletSharesResponse = serde_wasm_bindgen::from_value(shares)?;
|
||||
|
||||
if shares.epoch_id != issuers.epoch_id {
|
||||
console_error!(
|
||||
"the provided shares and issuers are not from the same epoch! {} and {}",
|
||||
shares.epoch_id,
|
||||
issuers.epoch_id
|
||||
);
|
||||
return Err(VpnApiLibError::InconsistentEpochId {
|
||||
shares: shares.epoch_id,
|
||||
issuers: issuers.epoch_id,
|
||||
});
|
||||
}
|
||||
|
||||
let master_vk = VerificationKeyAuth::try_from_bs58(master_key.bs58_encoded_key)?;
|
||||
|
||||
let mut decoded_keys = HashMap::new();
|
||||
for key in issuers.keys {
|
||||
let vk = VerificationKeyAuth::try_from_bs58(key.bs58_encoded_key)?;
|
||||
decoded_keys.insert(key.node_index, vk);
|
||||
}
|
||||
|
||||
let mut partial_wallets = Vec::new();
|
||||
for share in shares.shares {
|
||||
let blinded_sig = BlindedSignature::try_from_bs58(share.bs58_encoded_share)?;
|
||||
let Some(vk) = decoded_keys.get(&share.node_index) else {
|
||||
console_error!(
|
||||
"received a share from issuer {} but did not receive a corresponding verification key!",
|
||||
share.node_index
|
||||
);
|
||||
continue;
|
||||
};
|
||||
|
||||
match issue_verify(
|
||||
vk,
|
||||
self.ecash_keypair.secret_key(),
|
||||
&blinded_sig,
|
||||
&self.request_info,
|
||||
share.node_index,
|
||||
) {
|
||||
Ok(partial_wallet) => partial_wallets.push(partial_wallet),
|
||||
Err(err) => {
|
||||
console_error!(
|
||||
"failed to unblind partial wallet corresponding to index {}: {err}",
|
||||
share.node_index
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let aggregated_wallet = aggregate_wallets(
|
||||
&master_vk,
|
||||
self.ecash_keypair.secret_key(),
|
||||
&partial_wallets,
|
||||
&self.request_info,
|
||||
)?;
|
||||
|
||||
Ok(NymIssuedTicketbook {
|
||||
inner_ticketbook: IssuedTicketBook::new(
|
||||
aggregated_wallet.into_wallet_signatures(),
|
||||
shares.epoch_id,
|
||||
self.ecash_keypair.into(),
|
||||
self.ticketbook_type,
|
||||
self.expiration_date,
|
||||
),
|
||||
master_vk: EpochVerificationKey {
|
||||
epoch_id: shares.epoch_id,
|
||||
key: master_vk,
|
||||
},
|
||||
expiration_date_signatures: shares
|
||||
.aggregated_expiration_date_signatures
|
||||
.map(|s| s.signatures),
|
||||
coin_index_signatures: shares
|
||||
.aggregated_coin_index_signatures
|
||||
.map(|s| s.signatures),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct NymIssuedTicketbook {
|
||||
inner_ticketbook: IssuedTicketBook,
|
||||
|
||||
master_vk: EpochVerificationKey,
|
||||
expiration_date_signatures: Option<AggregatedExpirationDateSignatures>,
|
||||
coin_index_signatures: Option<AggregatedCoinIndicesSignatures>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl NymIssuedTicketbook {
|
||||
pub fn serialise(self) -> FullSerialisedNymIssuedTicketbook {
|
||||
let serialised = self
|
||||
.inner_ticketbook
|
||||
.begin_export()
|
||||
.with_master_verification_key(&self.master_vk)
|
||||
.with_maybe_expiration_date_signatures(&self.expiration_date_signatures)
|
||||
.with_maybe_coin_index_signatures(&self.coin_index_signatures)
|
||||
.finalize_export();
|
||||
|
||||
FullSerialisedNymIssuedTicketbook {
|
||||
serialisation_revision: serialised.revision,
|
||||
bs58_encoded_data: bs58::encode(serialised.data).into_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Tsify, Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FullSerialisedNymIssuedTicketbook {
|
||||
pub serialisation_revision: u8,
|
||||
pub bs58_encoded_data: String,
|
||||
}
|
||||
|
||||
#[wasm_bindgen(start)]
|
||||
pub fn main() {
|
||||
nym_wasm_utils::console_log!("[rust main]: rust module loaded");
|
||||
nym_wasm_utils::console_log!(
|
||||
"vpn-api-lib version used:\n{}",
|
||||
nym_bin_common::bin_info!().pretty_print()
|
||||
);
|
||||
nym_wasm_utils::console_log!("[rust main]: setting panic hook");
|
||||
nym_wasm_utils::set_panic_hook();
|
||||
}
|
||||
Reference in New Issue
Block a user