Compare commits

...

61 Commits

Author SHA1 Message Date
Mark Sinclair 00571c3892 ts-sdk: fix minimatch dependency and correct casing on selfAddress function call 2025-11-07 14:30:06 +00:00
Mark Sinclair 0257cb050a TS SDK 1.4.1-rc2 2025-11-07 14:29:19 +00:00
Mark Sinclair 503b7c5307 add back version complexity for CI 2025-11-05 15:59:51 +00:00
Mark Sinclair a86b3a3ee3 simplify version dependencies and add dist to dev mode 2025-11-05 15:46:53 +00:00
Mark Sinclair 6841516bf2 TS SDK 1.4.1-rc1 2025-11-05 12:23:45 +00:00
Mark Sinclair 0e97d6c040 limit packages published to only wasm clients 2025-11-04 19:41:45 +00:00
Mark Sinclair 854dccd79c bump versions to rc0 2025-11-04 19:40:04 +00:00
Mark Sinclair a792313b68 try disable typedoc because of minimatch errors 2025-11-04 18:15:45 +00:00
Mark Sinclair 7778adb493 Update publish-sdk-npm.yml 2025-11-04 14:57:24 +00:00
Mark Sinclair 33988b5164 Update publish-sdk-npm.yml 2025-11-04 14:52:22 +00:00
Mark Sinclair 284c25ff5a Update publish-sdk-npm.yml 2025-11-04 14:48:28 +00:00
Mark Sinclair 9d72229fa6 Update publish-sdk-npm.yml 2025-11-04 14:42:36 +00:00
Mark Sinclair da8d14ae84 bump versions to rc 2025-10-31 14:29:21 +00:00
Mark Sinclair 2e4f7bbc70 pin minimatch typings to fix lint errors 2025-10-25 00:24:29 +01:00
Mark Sinclair cbafe4adcf update go 2025-10-24 23:57:20 +01:00
Mark Sinclair 967b6c8e34 ts: fix linting errors 2025-10-24 23:26:17 +01:00
Mark Sinclair c3dad4231d ts-sdk: contract clients: update and re-run autogen 2025-10-24 23:25:35 +01:00
Mark Sinclair ba8ed878c9 remove bump version tool from workspace 2025-10-24 20:29:40 +01:00
Mark Sinclair 744860d4f9 Release Typescript SDK v1.4.1 2025-10-24 19:56:01 +01:00
Mark Sinclair 0013e7ac40 wasm: mix-fetch: fix up internal tester 2025-10-24 19:55:51 +01:00
Mark Sinclair 0fcc42e02d wasm: mix-fetch: remove harbour master client and use Nym API client 2025-10-24 19:55:51 +01:00
p17o 4f0974fcf1 Update quic_bridge_deployment.sh for IPv4 and .deb package (#6138)
Updated ping commands to explicitly use IPv4 and adjusted file permission checks with sudo. Changed the forward address prompt to specify IPv4 and modified the binary download process to fetch and install the latest .deb release URL automatically.
2025-10-22 15:46:23 +00:00
Jędrzej Stuczyński bd2174641e bugfix: update internal owner address in transferred share (#6139) 2025-10-22 10:42:26 +01:00
Tommy Verrall 59b62fabc9 Merge pull request #6134 from nymtech/feature/domain-fronting-v2
Domain fronting
2025-10-22 11:08:21 +02:00
Tommy Verrall e6f4bae895 Last failing test - fix 2025-10-21 19:34:20 +02:00
Tommy Verrall d71742af32 Use explicit Vec<ApiUrl> handling in BaseClientBuilder
- Replace NymNetworkDetails with explicit API URL handling
- Fix deprecated from_network() usage and improve fallback logic
- Add URL validation and remove unused backwards compatibility
2025-10-21 19:15:24 +02:00
Tommy Verrall 3b7c07e249 Actually commit the recommended changes 2025-10-21 18:12:38 +02:00
Tommy Verrall 3b429dde69 Fix broken tests in CI 2025-10-21 16:29:26 +02:00
Tommy Verrall 3a29c296da Replace deprecated from_network() with new_with_fronted_urls() 2025-10-21 16:05:41 +02:00
Tommy Verrall 8544c54f8f Merge develop into feature/domain-fronting-v2
- Use new_with_fronted_urls() for explicit domain fronting
- Deprecate from_network() in favor of explicit method
2025-10-21 15:58:20 +02:00
Jędrzej Stuczyński 9f9639950b feat: expose more explicit new_with_fronted_urls builder for http API client (#6136) 2025-10-21 14:47:58 +01:00
Jędrzej Stuczyński 111a0b20b6 bugfix: update stored epoch share when changing ownership (#6135) 2025-10-21 14:10:20 +01:00
Tommy Verrall 67b300d0b8 Fix new_from_env() to populate nym_api_urls for domain fronting 2025-10-21 12:22:51 +02:00
Jędrzej Stuczyński 88c4e0ce6c bugfix: update stored epoch share when changing announce address (#6131)
* bugfix: update stored epoch share when changing announce address

* chore: remove placeholder legacy mixnode bonding test [mixnet contract]
2025-10-21 10:59:17 +01:00
Tommy Verrall f6800aff0a fix all clippy messages 2025-10-21 11:32:47 +02:00
Tommy Verrall 0c7c927ca2 Add more tests for retry logic 2025-10-21 11:32:47 +02:00
Tommy Verrall a69c8b1660 Fix confusing tracing logs 2025-10-21 11:32:47 +02:00
Tommy Verrall f3ea310a46 Fix retries - this is working 2025-10-21 11:32:46 +02:00
Tommy Verrall 92f9ff035d Add configuration-based domain fronting support
Changes:
- Add network_details field to BaseClientBuilder (optional, backwards compatible)
- Add with_network_details() method for opt-in domain fronting
- Update construct_nym_api_client() to use from_network() when network_details provided
- Enable network-defaults feature in nym-client-core Cargo.toml
- SDK passes network_details to BaseClientBuilder
2025-10-21 11:32:46 +02:00
Tommy Verrall 5a817e1df1 Merge pull request #6126 from nymtech/multiple-fall-back-urls
Changes:

Multiple URL fallback with configurable retries (defaults to 3)
Infallible URL conversion per Andrews feedback (Url::from() instead of parse().ok())
Non-breaking builder pattern for BuilderConfig per Andrej's "too many arguments" feedback
Reverted redundant node filtering per Andrew's clarification that API already filters by supported_roles.entry
2025-10-21 11:27:37 +02:00
Tommy Verrall a07a24db00 Fix CI issues 2025-10-21 11:01:04 +02:00
Tommy Verrall a0cb812eff Allow clippy::enum_variant_names for BuilderConfigError 2025-10-21 10:35:57 +02:00
Tommy Verrall 923c1fa184 Improve error handling
Changes:
- Replace String error with BuilderConfigError enum in BuilderConfigBuilder
- Update tests to use pattern matching instead of string assertions
2025-10-20 16:57:31 +02:00
Tommy Verrall 35ea7e4926 - Add DEFAULT_NYM_API_RETRIES constant (replaces magic number 3)
- Run cargo fmt on all affected packages
- All clippy warnings resolved
2025-10-20 16:51:07 +02:00
Tommy Verrall d1cb9afaf0 not sure what happened but it's fixed 2025-10-20 15:20:24 +02:00
Tommy Verrall 79d4b4b2e3 Merge branch 'develop' into multiple-fall-back-urls 2025-10-20 15:16:36 +02:00
Tommy Verrall 8460b33946 Merge branch 'multiple-fall-back-urls' of https://github.com/nymtech/nym into multiple-fall-back-urls 2025-10-20 15:16:17 +02:00
Tommy Verrall ae6539e07c Merge resolution 2025-10-20 15:14:48 +02:00
Tommy Verrall 18cebdfedc Add accessor methods for Url internals
Add inner_url() and fronts() accessor methods to nym_http_api_client::Url
for VPN client integration
2025-10-20 14:33:57 +02:00
Tommy Verrall c448ec823a Remove tests for removed with_nym_api_client method
These tests were referencing with_nym_api_client() which was removed when
cleaning domain fronting code from this branch
2025-10-20 11:52:04 +02:00
Tommy Verrall a266137278 Add optional builder pattern for BuilderConfig (non-breaking)
Addresses @jstuczyn's feedback about too many arguments by adding
BuilderConfigBuilder as an alternative to the existing new() method.
2025-10-20 11:39:50 +02:00
Tommy Verrall 6f4dfd1dab fix conversion type && make the retry count configurable 2025-10-20 11:15:31 +02:00
Andy Duplain 57719787db Merge pull request #6130 from nymtech/andy/url_fronts
VPN-4262: Update `Url` to return `url` and `front` fields.
2025-10-17 15:44:08 +01:00
Andy Duplain 29a57bf172 VPN-4262: Update Url to return url and front fields.
The VPN client is using the `Url` type alot now and in order to avoid
double URL-parsing we would like the content of the `Url` type exposed.
2025-10-17 15:37:07 +01:00
Tommy Verrall db813b6e3e Revert node filtering changes per Andrew's feedback
Andrew clarified that get_basic_entry_assigned_nodes_v2() already filters by
supported_roles.entry
2025-10-17 15:18:28 +02:00
Tommy Verrall 1be5ba310a Remove domain fronting code to keep gateway changes only
This branch now contains only gateway registration improvements:
- Multiple URL fallback support in gateways_for_init()
- Get all entry-capable nodes for registration
- Performance and code quality improvements
2025-10-17 14:27:31 +02:00
Tommy Verrall 41ff3f7824 Address PR feedback: simplify code and reduce log noise
- Reverted all changes to topology_control/nym_api_provider.rs
- Changed info/warn logs to debug for custom client messages
- Removed unused _rng parameter from gateways_for_init()
- Simplified URL builder to always use new_with_urls()
2025-10-17 14:20:12 +02:00
Tommy Verrall c9d4d62446 Fix clippy warnings: use arrays instead of vec! in tests 2025-10-17 13:30:30 +02:00
Tommy Verrall e839a0d80e Merge develop into multiple-fall-back-urls
Resolved conflicts:
- Added event_tx field to MixnetClientBuilder alongside custom_nym_api_client
- Both features are independent and coexist:
  * custom_nym_api_client: for domain fronting support
  * event_tx: for event handling
- Updated all constructors and methods to properly handle both fields
2025-10-17 13:23:04 +02:00
Tommy Verrall cd61f930bf feat: pass custom HTTP client through SDK stack for domain fronting
- Add with_nym_api_client() to BaseClientBuilder, MixnetClientBuilder, and RegistrationClientBuilderConfig

- Modify nym_api_provider to fetch all nodes then filter by supported_roles.entry (fixes metadata inconsistency)

- Update helpers.rs to build HTTP client with all nym_apis URLs and retries for fallback support

- Fix SDK to use entry_capable_nodes() instead of entry_gateways() for broader gateway selection

This enables domain fronting and URL rotation throughout the entire SDK stack, improving censorship resistance and connection reliability. All changes are backward compatible - custom client is optional.
2025-10-17 08:36:23 +02:00
Tommy Verrall edcf2b1204 enable URL rotation and retries for mixnet gateway init 2025-10-16 16:22:57 +02:00
87 changed files with 6096 additions and 4271 deletions
+1 -1
View File
@@ -54,7 +54,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --lib --manifest-path contracts/Cargo.toml
args: --lib --manifest-path contracts/Cargo.toml --all-features
- name: Check formatting
uses: actions-rs/cargo@v1
+7 -4
View File
@@ -4,7 +4,7 @@ on:
jobs:
publish:
runs-on: arc-ubuntu-22.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -17,10 +17,13 @@ jobs:
- name: Setup yarn
run: npm install -g yarn
- name: Install Rust stable
- name: Install rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt, clippy
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
@@ -29,9 +32,9 @@ jobs:
run: cargo install wasm-opt
- name: Set up Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: "1.23.7"
go-version: "1.24.6"
- name: Install dependencies
run: yarn
Generated
+8 -7
View File
@@ -2262,7 +2262,7 @@ dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.59.0",
"windows-sys 0.60.2",
]
[[package]]
@@ -2579,7 +2579,7 @@ dependencies = [
[[package]]
name = "extension-storage"
version = "1.4.0-rc.0"
version = "1.4.1"
dependencies = [
"bip39",
"console_error_panic_hook",
@@ -4478,7 +4478,7 @@ dependencies = [
[[package]]
name = "mix-fetch-wasm"
version = "1.4.0-rc.0"
version = "1.4.1-rc2"
dependencies = [
"async-trait",
"futures",
@@ -4488,6 +4488,7 @@ dependencies = [
"nym-ordered-buffer",
"nym-service-providers-common",
"nym-socks5-requests",
"nym-validator-client",
"rand 0.8.5",
"serde",
"serde-wasm-bindgen 0.6.5",
@@ -5283,7 +5284,7 @@ dependencies = [
[[package]]
name = "nym-client-wasm"
version = "1.4.0-rc.0"
version = "1.4.1-rc2"
dependencies = [
"anyhow",
"futures",
@@ -6642,7 +6643,7 @@ dependencies = [
[[package]]
name = "nym-node-tester-wasm"
version = "1.3.0-rc.0"
version = "1.3.1-rc0"
dependencies = [
"futures",
"js-sys",
@@ -7823,9 +7824,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]]
name = "openssl-sys"
version = "0.9.109"
version = "0.9.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571"
checksum = "0a9f0075ba3c21b09f8e8b2026584b1d18d49388648f2fbbf3c97ea8deced8e2"
dependencies = [
"cc",
"libc",
+1 -1
View File
@@ -150,7 +150,7 @@ members = [
"tools/internal/contract-state-importer/importer-cli",
"tools/internal/contract-state-importer/importer-contract",
"tools/internal/mixnet-connectivity-check",
# "tools/internal/sdk-version-bump",
# "tools/internal/sdk-version-bump",
"tools/internal/ssl-inject",
"tools/internal/testnet-manager",
"tools/internal/testnet-manager/dkg-bypass-contract",
+4 -4
View File
@@ -107,16 +107,16 @@ sdk-wasm-build:
$(MAKE) -C nym-browser-extension/storage wasm-pack
$(MAKE) -C wasm/client
$(MAKE) -C wasm/node-tester
# $(MAKE) -C wasm/mix-fetch
$(MAKE) -C wasm/mix-fetch
$(MAKE) -C wasm/zknym-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
sdk-typescript-build:
npx lerna run --scope @nymproject/sdk build --stream
# npx lerna run --scope @nymproject/mix-fetch build --stream
# npx lerna run --scope @nymproject/node-tester build --stream
# yarn --cwd sdk/typescript/codegen/contract-clients build
npx lerna run --scope @nymproject/mix-fetch build --stream
npx lerna run --scope @nymproject/node-tester build --stream
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
+1 -1
View File
@@ -36,7 +36,7 @@ nym-bandwidth-controller = { path = "../bandwidth-controller" }
nym-crypto = { path = "../crypto" }
nym-gateway-client = { path = "../client-libs/gateway-client" }
nym-gateway-requests = { path = "../gateway-requests" }
nym-http-api-client = { path = "../http-api-client" }
nym-http-api-client = { path = "../http-api-client", features = ["network-defaults"] }
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
nym-sphinx = { path = "../nymsphinx" }
nym-statistics-common = { path = "../statistics" }
@@ -114,13 +114,12 @@ where
})?;
hardcoded_topology.entry_capable_nodes().cloned().collect()
} else {
let mut rng = rand::thread_rng();
crate::init::helpers::gateways_for_init(
&mut rng,
&core.client.nym_api_urls,
user_agent,
core.debug.topology.minimum_gateway_performance,
core.debug.topology.ignore_ingress_epoch_role,
None,
)
.await?
};
@@ -173,13 +173,12 @@ where
})?;
hardcoded_topology.entry_capable_nodes().cloned().collect()
} else {
let mut rng = rand::thread_rng();
crate::init::helpers::gateways_for_init(
&mut rng,
&core.client.nym_api_urls,
user_agent,
core.debug.topology.minimum_gateway_performance,
core.debug.topology.ignore_ingress_epoch_role,
None,
)
.await?
};
@@ -73,6 +73,10 @@ use url::Url;
#[cfg(debug_assertions)]
use wasm_utils::console_log;
/// Default number of retries for Nym API requests when using network details with domain fronting.
/// This allows the client to try alternative URLs if the primary endpoint is unavailable.
const DEFAULT_NYM_API_RETRIES: usize = 3;
#[cfg(all(
not(target_arch = "wasm32"),
feature = "fs-surb-storage",
@@ -212,6 +216,9 @@ pub struct BaseClientBuilder<C, S: MixnetClientStorage> {
client_store: S,
dkg_query_client: Option<C>,
// Optional API URLs for domain fronting support
nym_api_urls: Option<Vec<nym_network_defaults::ApiUrl>>,
wait_for_gateway: bool,
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
@@ -241,6 +248,7 @@ where
config: base_config,
client_store,
dkg_query_client,
nym_api_urls: None,
wait_for_gateway: false,
custom_topology_provider: None,
custom_gateway_transceiver: None,
@@ -263,6 +271,16 @@ where
self
}
/// Set Nym API URLs for domain fronting support.
///
/// When provided, the client will use these API URLs (which include front_hosts)
/// to construct HTTP clients with domain fronting enabled.
#[must_use]
pub fn with_nym_api_urls(mut self, nym_api_urls: Vec<nym_network_defaults::ApiUrl>) -> Self {
self.nym_api_urls = Some(nym_api_urls);
self
}
#[must_use]
pub fn with_forget_me(mut self, forget_me: &ForgetMe) -> Self {
self.config.debug.forget_me = *forget_me;
@@ -863,21 +881,67 @@ where
}
fn construct_nym_api_client(
nym_api_urls: Option<&Vec<nym_network_defaults::ApiUrl>>,
config: &Config,
user_agent: Option<UserAgent>,
) -> Result<nym_http_api_client::Client, ClientCoreError> {
tracing::debug!(
"construct_nym_api_client called with nym_api_urls: {}",
nym_api_urls.is_some()
);
// If API URLs are provided, use new_with_fronted_urls() which handles domain fronting
if let Some(nym_api_urls) = nym_api_urls {
if nym_api_urls.is_empty() {
tracing::warn!("Provided nym_api_urls is empty, falling back to config endpoints");
} else {
tracing::info!(
"Building nym-api client from provided URLs (with domain fronting support): {} URLs",
nym_api_urls.len()
);
let mut builder =
nym_http_api_client::ClientBuilder::new_with_fronted_urls(nym_api_urls.clone())
.map_err(ClientCoreError::from)?
.with_retries(DEFAULT_NYM_API_RETRIES);
if let Some(user_agent) = user_agent {
builder = builder.with_user_agent(user_agent);
}
return builder.build().map_err(ClientCoreError::from);
}
}
// Fallback to basic client for backwards compatibility
tracing::debug!("Building basic nym-api HTTP client from config endpoints");
let mut nym_api_urls = config.get_nym_api_endpoints();
if nym_api_urls.is_empty() {
tracing::warn!("No API endpoints configured in config, this may cause issues");
}
nym_api_urls.shuffle(&mut thread_rng());
let mut builder = nym_http_api_client::Client::builder(nym_api_urls[0].clone())
.map_err(ClientCoreError::from)?;
// Convert config URLs to ApiUrl format for consistency
let api_urls: Vec<nym_network_defaults::ApiUrl> = nym_api_urls
.into_iter()
.map(|url| nym_network_defaults::ApiUrl {
url: url.to_string(),
front_hosts: None,
})
.collect();
tracing::debug!("Using {} config API endpoints", api_urls.len());
let mut builder = nym_http_api_client::ClientBuilder::new_with_fronted_urls(api_urls)
.map_err(ClientCoreError::from)?
.with_retries(DEFAULT_NYM_API_RETRIES)
.with_bincode();
if let Some(user_agent) = user_agent {
builder = builder.with_user_agent(user_agent);
}
builder = builder.with_bincode();
builder.build().map_err(ClientCoreError::from)
}
@@ -961,7 +1025,11 @@ where
.dkg_query_client
.map(|client| BandwidthController::new(credential_store, client));
let nym_api_client = Self::construct_nym_api_client(&self.config, self.user_agent.clone())?;
let nym_api_client = Self::construct_nym_api_client(
self.nym_api_urls.as_ref(),
&self.config,
self.user_agent.clone(),
)?;
let key_rotation_config = Self::determine_key_rotation_state(&nym_api_client).await?;
let topology_provider = Self::setup_topology_provider(
@@ -1136,3 +1204,53 @@ pub struct BaseClient {
pub forget_me: ForgetMe,
pub remember_me: RememberMe,
}
#[cfg(test)]
mod tests {
use super::*;
use nym_network_defaults::{ApiUrl, NymNetworkDetails};
#[test]
fn test_network_details_with_multiple_urls() {
// Verify that network details can be configured with multiple API URLs
let mut network_details = NymNetworkDetails::new_empty();
network_details.nym_api_urls = Some(vec![
ApiUrl {
url: "https://validator.nymtech.net/api/".to_string(),
front_hosts: None,
},
ApiUrl {
url: "https://nym-frontdoor.vercel.app/api/".to_string(),
front_hosts: Some(vec!["vercel.app".to_string(), "vercel.com".to_string()]),
},
]);
assert_eq!(network_details.nym_api_urls.as_ref().unwrap().len(), 2);
assert!(network_details.nym_api_urls.as_ref().unwrap()[1]
.front_hosts
.is_some());
}
#[test]
fn test_network_details_with_front_hosts() {
// Verify that ApiUrl can store domain fronting configuration
let api_url = ApiUrl {
url: "https://nym-frontdoor.vercel.app/api/".to_string(),
front_hosts: Some(vec!["vercel.app".to_string(), "vercel.com".to_string()]),
};
assert_eq!(api_url.url, "https://nym-frontdoor.vercel.app/api/");
assert_eq!(api_url.front_hosts.as_ref().unwrap().len(), 2);
assert!(api_url
.front_hosts
.as_ref()
.unwrap()
.contains(&"vercel.app".to_string()));
}
#[test]
fn test_default_nym_api_retries_constant() {
// Verify the retry constant is set correctly
assert_eq!(DEFAULT_NYM_API_RETRIES, 3);
}
}
+77 -20
View File
@@ -45,6 +45,7 @@ type WsConn = JSWebsocket;
const CONCURRENT_GATEWAYS_MEASURED: usize = 20;
const MEASUREMENTS: usize = 3;
const DEFAULT_NYM_API_RETRIES: usize = 3;
#[cfg(not(target_arch = "wasm32"))]
const CONN_TIMEOUT: Duration = Duration::from_millis(1500);
@@ -132,25 +133,27 @@ impl<'a, G: ConnectableGateway> GatewayWithLatency<'a, G> {
}
}
pub async fn gateways_for_init<R: Rng>(
rng: &mut R,
pub async fn gateways_for_init(
nym_apis: &[Url],
user_agent: Option<UserAgent>,
minimum_performance: u8,
ignore_epoch_roles: bool,
retry_count: Option<usize>,
) -> Result<Vec<RoutingNode>, ClientCoreError> {
let nym_api = nym_apis
.choose(rng)
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
// Build client with ALL URLs for fallback support
let nym_api_urls: Vec<nym_http_api_client::Url> = nym_apis
.iter()
.map(|url| nym_http_api_client::Url::from(url.clone()))
.collect();
// Use the unified HTTP client directly with optional user agent
let mut builder = nym_http_api_client::Client::builder(nym_api.clone())
.map_err(|e| {
ClientCoreError::ValidatorClientError(nym_validator_client::ValidatorClientError::from(
e,
))
})?
.with_bincode(); // Use bincode for better performance
if nym_api_urls.is_empty() {
return Err(ClientCoreError::ListOfNymApisIsEmpty);
}
let retry_count = retry_count.unwrap_or(DEFAULT_NYM_API_RETRIES);
let mut builder = nym_http_api_client::ClientBuilder::new_with_urls(nym_api_urls.clone())?
.with_retries(retry_count)
.with_bincode();
if let Some(user_agent) = user_agent {
builder = builder.with_user_agent(user_agent);
@@ -160,7 +163,7 @@ pub async fn gateways_for_init<R: Rng>(
ClientCoreError::ValidatorClientError(nym_validator_client::ValidatorClientError::from(e))
})?;
tracing::debug!("Fetching list of gateways from: {nym_api}");
tracing::debug!("Fetching list of gateways from: {:?}", nym_api_urls);
// Use our helper to handle pagination
let gateways = get_all_basic_entry_nodes_with_metadata(&client, true)
@@ -172,17 +175,15 @@ pub async fn gateways_for_init<R: Rng>(
// filter out gateways below minimum performance and ones that could operate as a mixnode
// (we don't want instability)
let valid_gateways = gateways
let valid_gateways: Vec<RoutingNode> = gateways
.iter()
.filter(|g| ignore_epoch_roles || !g.supported_roles.mixnode)
.filter(|g| g.performance.round_to_integer() >= minimum_performance)
.filter_map(|gateway| gateway.try_into().ok())
.collect::<Vec<_>>();
tracing::debug!("After checking validity: {}", valid_gateways.len());
tracing::trace!("Valid gateways: {valid_gateways:#?}");
.collect();
tracing::info!(
"and {} after validity and performance filtering",
"Found {} valid gateways after filtering",
valid_gateways.len()
);
@@ -345,13 +346,20 @@ pub(super) fn get_specified_gateway(
must_use_tls: bool,
) -> Result<RoutingNode, ClientCoreError> {
tracing::debug!("Requesting specified gateway: {gateway_identity}");
let user_gateway = ed25519::PublicKey::from_base58_string(gateway_identity)
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
let gateway = gateways
.iter()
.find(|gateway| gateway.identity_key == user_gateway)
.ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string()))?;
.ok_or_else(|| {
tracing::debug!(
"Gateway {gateway_identity} not found in {} available gateways",
gateways.len()
);
ClientCoreError::NoGatewayWithId(gateway_identity.to_string())
})?;
let Some(entry_details) = gateway.entry.as_ref() else {
return Err(ClientCoreError::UnsupportedEntry {
@@ -414,3 +422,52 @@ pub(super) async fn register_with_gateway(
authenticated_ephemeral_client: gateway_client,
})
}
#[cfg(test)]
mod tests {
use url::Url;
#[test]
fn test_single_url_builds_without_retries() {
let urls = [Url::parse("https://api.nym.com").unwrap()];
let nym_api_urls: Vec<nym_http_api_client::Url> = urls
.iter()
.map(|url| nym_http_api_client::Url::from(url.clone()))
.collect();
assert_eq!(nym_api_urls.len(), 1, "Should have exactly one URL");
}
#[test]
fn test_multiple_urls_prepared_for_retries() {
let urls = vec![
Url::parse("https://api1.nym.com").unwrap(),
Url::parse("https://api2.nym.com").unwrap(),
Url::parse("https://api3.nym.com").unwrap(),
];
let nym_api_urls: Vec<nym_http_api_client::Url> = urls
.iter()
.map(|url| nym_http_api_client::Url::from(url.clone()))
.collect();
assert_eq!(nym_api_urls.len(), 3, "Should have all three URLs");
assert!(
nym_api_urls.len() > 1,
"Multiple URLs trigger retry behavior"
);
}
#[test]
fn test_empty_url_list_is_detected() {
let urls: Vec<Url> = vec![];
let nym_api_urls: Vec<nym_http_api_client::Url> = urls
.iter()
.map(|url| nym_http_api_client::Url::from(url.clone()))
.collect();
assert!(nym_api_urls.is_empty(), "Empty list should remain empty");
}
}
+36 -20
View File
@@ -296,6 +296,9 @@ impl std::error::Error for ReqwestErrorWrapper {}
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum HttpClientError {
#[error("did not provide any valid client URLs")]
NoUrlsProvided,
#[error("failed to construct inner reqwest client: {source}")]
ReqwestBuildError {
#[source]
@@ -582,24 +585,29 @@ impl ClientBuilder {
Self::new(alt)
} else {
let url = url.to_url()?;
Ok(Self::new_with_urls(vec![url]))
Self::new_with_urls(vec![url])
}
}
/// Create a client builder from network details with sensible defaults
#[cfg(feature = "network-defaults")]
// deprecating function since it's not clear from its signature whether the client
// would be constructed using `nym_api_urls` or `nym_vpn_api_urls`
#[deprecated(note = "use explicit Self::new_with_fronted_urls instead")]
pub fn from_network(
network: &nym_network_defaults::NymNetworkDetails,
) -> Result<Self, HttpClientError> {
let urls = network
.nym_api_urls
.as_ref()
.ok_or_else(|| {
HttpClientError::GenericRequestFailure(
"No API URLs configured in network details".to_string(),
)
})?
.iter()
let urls = network.nym_api_urls.as_ref().cloned().unwrap_or_default();
Self::new_with_fronted_urls(urls.clone())
}
/// Create a client builder using the provided set of domain-fronted URLs
#[cfg(feature = "network-defaults")]
pub fn new_with_fronted_urls(
urls: Vec<nym_network_defaults::ApiUrl>,
) -> Result<Self, HttpClientError> {
let urls = urls
.into_iter()
.map(|api_url| {
// Convert ApiUrl to our Url type with fronting support
let mut url = Url::parse(&api_url.url)?;
@@ -611,15 +619,19 @@ impl ClientBuilder {
.iter()
.map(|host| format!("https://{}", host))
.collect();
url = Url::new(api_url.url.clone(), Some(fronts))
.map_err(|e| HttpClientError::GenericRequestFailure(e.to_string()))?;
url = Url::new(api_url.url.clone(), Some(fronts)).map_err(|source| {
HttpClientError::MalformedUrl {
raw: api_url.url.clone(),
source,
}
})?;
}
Ok(url)
})
.collect::<Result<Vec<_>, HttpClientError>>()?;
let mut builder = Self::new_with_urls(urls);
let mut builder = Self::new_with_urls(urls)?;
// Enable domain fronting by default (on retry)
#[cfg(feature = "tunneling")]
@@ -631,7 +643,11 @@ impl ClientBuilder {
}
/// Constructs a new http `ClientBuilder` from a valid url.
pub fn new_with_urls(urls: Vec<Url>) -> Self {
pub fn new_with_urls(urls: Vec<Url>) -> Result<Self, HttpClientError> {
if urls.is_empty() {
return Err(HttpClientError::NoUrlsProvided);
}
let urls = Self::check_urls(urls);
#[cfg(target_arch = "wasm32")]
@@ -640,7 +656,7 @@ impl ClientBuilder {
#[cfg(not(target_arch = "wasm32"))]
let reqwest_client_builder = default_builder();
ClientBuilder {
Ok(ClientBuilder {
urls,
timeout: None,
custom_user_agent: false,
@@ -651,7 +667,7 @@ impl ClientBuilder {
retry_limit: 0,
serialization: SerializationFormat::Json,
}
})
}
/// Add an additional URL to the set usable by this constructed `Client`
@@ -948,13 +964,13 @@ impl Client {
return (url.as_str(), url.front_str());
} else {
warn!(
"Domain fronting is enabled, but no host_url is defined! Domain fronting WILL NOT WORK"
tracing::debug!(
"Domain fronting is enabled, but no host_url is defined for current URL"
)
}
} else {
warn!(
"Domain fronting is enabled, but no front_url is defined! Domain fronting WILL NOT WORK"
tracing::debug!(
"Domain fronting is enabled, but current URL has no front_hosts configured"
)
}
}
+9 -1
View File
@@ -21,6 +21,10 @@ inventory::collect!(ConfigRecord);
/// Returns the default builder with all registered configurations applied.
pub fn default_builder() -> ReqwestClientBuilder {
let mut b = ReqwestClientBuilder::new();
#[cfg(feature = "debug-inventory")]
let mut test_client = ReqwestClientBuilder::new();
let mut records: Vec<&'static ConfigRecord> =
inventory::iter::<ConfigRecord>.into_iter().collect();
records.sort_by_key(|r| r.priority); // lower runs first
@@ -35,6 +39,10 @@ pub fn default_builder() -> ReqwestClientBuilder {
for r in records {
b = (r.apply)(b);
#[cfg(feature = "debug-inventory")]
{
test_client = (r.apply)(test_client);
}
}
#[cfg(feature = "debug-inventory")]
@@ -47,7 +55,7 @@ pub fn default_builder() -> ReqwestClientBuilder {
eprintln!("[HTTP-INVENTORY] Building test client to verify configuration...");
// Try to build a client to see if it works
match b.try_clone().unwrap().build() {
match test_client.build() {
Ok(client) => {
eprintln!("[HTTP-INVENTORY] ✓ Client built successfully");
eprintln!("[HTTP-INVENTORY] Client debug info: {:#?}", client);
+110 -49
View File
@@ -2,77 +2,77 @@ use super::*;
#[test]
fn sanitizing_urls() {
let base_url: Url = "http://foomp.com".parse().unwrap();
let base_url: Url = "http://api.test".parse().unwrap();
// works with a full string
assert_eq!(
"http://foomp.com/foo/bar",
"http://api.test/foo/bar",
sanitize_url(&base_url, "/foo//bar/", NO_PARAMS).as_str()
);
// (and leading slash doesn't matter)
assert_eq!(
"http://foomp.com/foo/bar",
"http://api.test/foo/bar",
sanitize_url(&base_url, "foo//bar/", NO_PARAMS).as_str()
);
// works with 1 segment
assert_eq!(
"http://foomp.com/foo",
"http://api.test/foo",
sanitize_url(&base_url, &["foo"], NO_PARAMS).as_str()
);
// works with 2 segments
assert_eq!(
"http://foomp.com/foo/bar",
"http://api.test/foo/bar",
sanitize_url(&base_url, &["foo", "bar"], NO_PARAMS).as_str()
);
// works with leading slash
assert_eq!(
"http://foomp.com/foo",
"http://api.test/foo",
sanitize_url(&base_url, &["/foo"], NO_PARAMS).as_str()
);
assert_eq!(
"http://foomp.com/foo/bar",
"http://api.test/foo/bar",
sanitize_url(&base_url, &["/foo", "bar"], NO_PARAMS).as_str()
);
assert_eq!(
"http://foomp.com/foo/bar",
"http://api.test/foo/bar",
sanitize_url(&base_url, &["foo", "/bar"], NO_PARAMS).as_str()
);
// works with trailing slash
assert_eq!(
"http://foomp.com/foo",
"http://api.test/foo",
sanitize_url(&base_url, &["foo/"], NO_PARAMS).as_str()
);
assert_eq!(
"http://foomp.com/foo/bar",
"http://api.test/foo/bar",
sanitize_url(&base_url, &["foo/", "bar"], NO_PARAMS).as_str()
);
assert_eq!(
"http://foomp.com/foo/bar",
"http://api.test/foo/bar",
sanitize_url(&base_url, &["foo", "bar/"], NO_PARAMS).as_str()
);
// works with both leading and trailing slash
assert_eq!(
"http://foomp.com/foo",
"http://api.test/foo",
sanitize_url(&base_url, &["/foo/"], NO_PARAMS).as_str()
);
assert_eq!(
"http://foomp.com/foo/bar",
"http://api.test/foo/bar",
sanitize_url(&base_url, &["/foo/", "/bar/"], NO_PARAMS).as_str()
);
// adds params
assert_eq!(
"http://foomp.com/foo/bar?foomp=baz",
"http://api.test/foo/bar?foomp=baz",
sanitize_url(&base_url, &["foo", "bar"], &[("foomp", "baz")]).as_str()
);
assert_eq!(
"http://foomp.com/foo/bar?arg1=val1&arg2=val2",
"http://api.test/foo/bar?arg1=val1&arg2=val2",
sanitize_url(
&base_url,
&["/foo/", "/bar/"],
@@ -91,83 +91,87 @@ fn sanitizing_urls() {
#[tokio::test]
async fn api_client_retry() -> Result<(), Box<dyn std::error::Error>> {
let client = ClientBuilder::new_with_urls(vec![
"http://broken.nym.badurl".parse()?,
"http://example.com/".parse()?,
])
"http://broken.nym.test".parse()?, // This will fail
"https://httpbin.org/status/200".parse()?, // This will succeed
])?
.with_retries(3)
.build()?;
let req = client.create_get_request(&["/"], NO_PARAMS).unwrap();
let req = client.create_get_request(&[], NO_PARAMS).unwrap();
let resp = client.send(req).await?;
assert_eq!(resp.status(), 200);
// The main test is that we successfully retried and switched to the working URL
// We accept any response from the working endpoint since external services can be unreliable
assert_eq!(
client.current_url().as_str(),
"https://httpbin.org/status/200"
);
// check that the url was updated
assert_eq!(client.current_url().as_str(), "http://example.com/");
println!("Response status: {}", resp.status());
Ok(())
}
#[test]
fn host_updating() {
let url = Url::new("http://example.com", None).unwrap();
let url = Url::new("http://nym-api1.test", None).unwrap();
let mut client = ClientBuilder::new(url).unwrap().build().unwrap();
// check that the url is set correctly
let current_url = client.current_url();
assert_eq!(current_url.as_str(), "http://example.com/");
assert_eq!(current_url.as_str(), "http://nym-api1.test/");
assert_eq!(current_url.front_str(), None);
// update the url
client.update_host();
// check that the url is still the same since there is one URL
assert_eq!(client.current_url().as_str(), "http://example.com/");
assert_eq!(client.current_url().as_str(), "http://nym-api1.test/");
// =======================================
// we rotate through urls when available
let new_urls = vec![
Url::new("http://example.com", None).unwrap(),
Url::new("http://example.org", None).unwrap(),
Url::new("http://nym-api1.test", None).unwrap(),
Url::new("http://nym-api2.test", None).unwrap(),
];
client.change_base_urls(new_urls);
assert_eq!(client.current_url().as_str(), "http://example.com/");
assert_eq!(client.current_url().as_str(), "http://nym-api1.test/");
client.update_host();
// check that the url got updated now that there are multiple URLs
assert_eq!(client.current_url().as_str(), "http://example.org/");
assert_eq!(client.current_url().as_str(), "http://nym-api2.test/");
assert_eq!(client.current_url().front_str(), None);
client.update_host();
assert_eq!(client.current_url().as_str(), "http://example.com/");
assert_eq!(client.current_url().as_str(), "http://nym-api1.test/");
// =======================================
// we rotate through urls when available if fronting is disabled
let new_urls = vec![
Url::new(
"http://example.com",
Some(vec!["http://front1.com", "http://front2.com"]),
"http://nym-api1.test",
Some(vec!["http://cdn1.test", "http://cdn2.test"]),
)
.unwrap(),
Url::new("http://example.org", None).unwrap(),
Url::new("http://nym-api2.test", None).unwrap(),
];
client.change_base_urls(new_urls);
assert_eq!(client.current_url().as_str(), "http://example.com/");
assert_eq!(client.current_url().as_str(), "http://nym-api1.test/");
client.update_host();
// check that the url got updated now that there are multiple URLs
assert_eq!(client.current_url().as_str(), "http://example.org/");
assert_eq!(client.current_url().as_str(), "http://nym-api2.test/");
}
#[test]
#[cfg(feature = "tunneling")]
fn fronted_host_updating() {
let url = Url::new("http://example.com", Some(vec!["http://front1.com"])).unwrap();
let url = Url::new("http://nym-api.test", Some(vec!["http://cdn1.test"])).unwrap();
let mut client = ClientBuilder::new(url)
.unwrap()
.with_fronting(crate::fronted::FrontPolicy::Always)
@@ -176,46 +180,103 @@ fn fronted_host_updating() {
// check that the url is set correctly
let current_url = client.current_url();
assert_eq!(current_url.as_str(), "http://example.com/");
assert_eq!(current_url.front_str(), Some("front1.com"));
assert_eq!(current_url.as_str(), "http://nym-api.test/");
assert_eq!(current_url.front_str(), Some("cdn1.test"));
// update the url
client.update_host();
// check that the url is still the same since there is one URL and one front
let current_url = client.current_url();
assert_eq!(current_url.as_str(), "http://example.com/");
assert_eq!(current_url.front_str(), Some("front1.com"));
assert_eq!(current_url.as_str(), "http://nym-api.test/");
assert_eq!(current_url.front_str(), Some("cdn1.test"));
// =======================================
// we rotate through front urls when available if fronting is enabled
let new_urls = vec![
Url::new(
"http://example.com",
Some(vec!["http://front1.com", "http://front2.com"]),
"http://nym-api.test",
Some(vec!["http://cdn1.test", "http://cdn2.test"]),
)
.unwrap(),
Url::new("http://example.org", None).unwrap(),
Url::new("http://nym-api2.test", None).unwrap(),
];
client.change_base_urls(new_urls);
let current_url = client.current_url();
assert_eq!(current_url.as_str(), "http://example.com/");
assert_eq!(current_url.front_str(), Some("front1.com"));
assert_eq!(current_url.as_str(), "http://nym-api.test/");
assert_eq!(current_url.front_str(), Some("cdn1.test"));
// update the url - this should keep the same host but change the front
client.update_host();
let current_url = client.current_url();
// check that the url is still the same since there is one URL
assert_eq!(current_url.as_str(), "http://example.com/");
assert_eq!(current_url.front_str(), Some("front2.com"));
assert_eq!(current_url.as_str(), "http://nym-api.test/");
assert_eq!(current_url.front_str(), Some("cdn2.test"));
// update the url - this should wrap around to the first front as the second url is not fronted
client.update_host();
let current_url = client.current_url();
assert_eq!(current_url.as_str(), "http://example.com/");
assert_eq!(current_url.front_str(), Some("front1.com"));
assert_eq!(current_url.as_str(), "http://nym-api.test/");
assert_eq!(current_url.front_str(), Some("cdn1.test"));
}
#[test]
#[cfg(feature = "network-defaults")]
fn from_network_configures_multiple_urls_and_retries() {
use nym_network_defaults::{ApiUrl, NymNetworkDetails};
// Create network details with multiple URLs and fronting
let mut network_details = NymNetworkDetails::new_empty();
network_details.nym_api_urls = Some(vec![
ApiUrl {
url: "https://validator.nymtech.net/api/".to_string(),
front_hosts: None,
},
ApiUrl {
url: "https://nym-frontdoor.vercel.app/api/".to_string(),
front_hosts: Some(vec!["vercel.app".to_string(), "vercel.com".to_string()]),
},
ApiUrl {
url: "https://nym-frontdoor.global.ssl.fastly.net/api/".to_string(),
front_hosts: Some(vec!["yelp.global.ssl.fastly.net".to_string()]),
},
]);
// Build client from network details
let client = ClientBuilder::new_with_fronted_urls(
network_details.nym_api_urls.clone().unwrap_or_default(),
)
.expect("Failed to create client from network")
.build()
.expect("Failed to build client");
// Verify all URLs were configured
assert_eq!(
client.base_urls().len(),
3,
"Expected 3 URLs to be configured from network details"
);
// Verify the URLs have fronting configured where appropriate
assert_eq!(
client.base_urls()[0].as_str(),
"https://validator.nymtech.net/api/"
);
assert!(client.base_urls()[0].front_str().is_none());
assert_eq!(
client.base_urls()[1].as_str(),
"https://nym-frontdoor.vercel.app/api/"
);
assert!(client.base_urls()[1].front_str().is_some());
assert_eq!(
client.base_urls()[2].as_str(),
"https://nym-frontdoor.global.ssl.fastly.net/api/"
);
assert!(client.base_urls()[2].front_str().is_some());
}
+10
View File
@@ -183,6 +183,11 @@ impl Url {
})
}
/// Returns the underlying URL
pub fn inner_url(&self) -> &url::Url {
&self.url
}
/// Returns true if the URL has a front domain set
pub fn has_front(&self) -> bool {
if let Some(fronts) = &self.fronts {
@@ -201,6 +206,11 @@ impl Url {
.and_then(|url| url.host_str())
}
/// Returns the fronts
pub fn fronts(&self) -> Option<&[url::Url]> {
self.fronts.as_deref()
}
/// Return the string representation of the host (domain or IP address) for this URL, if any.
pub fn host_str(&self) -> Option<&str> {
self.url.host_str()
+13 -1
View File
@@ -124,6 +124,8 @@ impl NymNetworkDetails {
}
}
let nym_api = var(var_names::NYM_API).expect("nym api not set");
NymNetworkDetails::new_empty()
.with_network_name(var(var_names::NETWORK_NAME).expect("network name not set"))
.with_bech32_account_prefix(
@@ -149,7 +151,7 @@ impl NymNetworkDetails {
})
.with_additional_validator_endpoint(ValidatorDetails::new(
var(var_names::NYXD).expect("nyxd validator not set"),
Some(var(var_names::NYM_API).expect("nym api not set")),
Some(nym_api.clone()),
get_optional_env(var_names::NYXD_WEBSOCKET),
))
.with_mixnet_contract(get_optional_env(var_names::MIXNET_CONTRACT_ADDRESS))
@@ -159,6 +161,10 @@ impl NymNetworkDetails {
.with_multisig_contract(get_optional_env(var_names::MULTISIG_CONTRACT_ADDRESS))
.with_coconut_dkg_contract(get_optional_env(var_names::COCONUT_DKG_CONTRACT_ADDRESS))
.with_nym_vpn_api_url(get_optional_env(var_names::NYM_VPN_API))
.with_nym_api_urls(Some(vec![ApiUrl {
url: nym_api,
front_hosts: None,
}]))
}
pub fn new_mainnet() -> Self {
@@ -348,6 +354,12 @@ impl NymNetworkDetails {
self
}
#[must_use]
pub fn with_nym_api_urls(mut self, urls: Option<Vec<ApiUrl>>) -> Self {
self.nym_api_urls = urls;
self
}
pub fn nym_vpn_api_url(&self) -> Option<Url> {
self.nym_vpn_api_url.as_ref().map(|url| {
url.parse()
+2 -4
View File
@@ -160,13 +160,12 @@ pub async fn setup_gateway_from_api(
minimum_performance: u8,
ignore_epoch_roles: bool,
) -> Result<InitialisationResult, WasmCoreError> {
let mut rng = thread_rng();
let gateways = gateways_for_init(
&mut rng,
nym_apis,
None,
minimum_performance,
ignore_epoch_roles,
None,
)
.await?;
setup_gateway_wasm(client_store, force_tls, chosen_gateway, gateways).await
@@ -178,13 +177,12 @@ pub async fn current_gateways_wasm(
minimum_performance: u8,
ignore_epoch_roles: bool,
) -> Result<Vec<RoutingNode>, ClientCoreError> {
let mut rng = thread_rng();
gateways_for_init(
&mut rng,
nym_apis,
user_agent,
minimum_performance,
ignore_epoch_roles,
None,
)
.await
}
@@ -9,6 +9,7 @@ use crate::epoch_state::storage::{load_current_epoch, save_epoch};
use crate::epoch_state::utils::check_epoch_state;
use crate::error::ContractError;
use crate::state::storage::STATE;
use crate::verification_key_shares::storage::vk_shares;
use crate::Dealer;
use cosmwasm_std::{Deps, DepsMut, Env, Event, MessageInfo, Response};
use nym_coconut_dkg_common::dealer::{DealerRegistrationDetails, OwnershipTransfer};
@@ -109,7 +110,7 @@ pub fn try_transfer_ownership(
DEALERS_INDICES.save(deps.storage, &transfer_to, &current_index)?;
DEALERS_INDICES.remove(deps.storage, &info.sender);
// update registration detail for every epoch the current dealer has participated in the protocol
// update registration detail and share information for every epoch the current dealer has participated in the protocol
// ideally, we'd have only updated the current epoch, but the way the contract is constructed
// forbids that otherwise we'd have introduced inconsistency
for epoch_id in 0..=epoch.epoch_id {
@@ -117,6 +118,11 @@ pub fn try_transfer_ownership(
EPOCH_DEALERS_MAP.remove(deps.storage, (epoch_id, &info.sender));
EPOCH_DEALERS_MAP.save(deps.storage, (epoch_id, &transfer_to), &details)?;
}
if let Some(mut vk_share) = vk_shares().may_load(deps.storage, (&info.sender, epoch_id))? {
vk_shares().remove(deps.storage, (&info.sender, epoch_id))?;
vk_share.owner = transfer_to.clone();
vk_shares().save(deps.storage, (&transfer_to, epoch_id), &vk_share)?;
}
}
let Some(transaction_info) = env.transaction else {
@@ -161,6 +167,14 @@ pub fn try_update_announce_address(
details.announce_address = new_address.clone();
EPOCH_DEALERS_MAP.save(deps.storage, (epoch.epoch_id, &info.sender), &details)?;
let mut contract_share = vk_shares().load(deps.storage, (&info.sender, epoch.epoch_id))?;
contract_share.announce_address = new_address.clone();
vk_shares().save(
deps.storage,
(&info.sender, epoch.epoch_id),
&contract_share,
)?;
Ok(Response::new().add_event(
Event::new("dkg-announce-address-update")
.add_attribute("dealer", info.sender)
@@ -228,9 +242,14 @@ pub(crate) mod tests {
#[cfg(feature = "testable-dkg-contract")]
mod tests_with_mock {
use super::*;
use crate::testable_dkg_contract::{init_contract_tester, DkgContractTesterExt};
use crate::testable_dkg_contract::{
init_contract_tester, init_contract_tester_with_group_members, DkgContractTesterExt,
};
use anyhow::Context;
use cosmwasm_std::testing::message_info;
use nym_contracts_common_testing::ContractOpts;
use nym_coconut_dkg_common::msg::QueryMsg;
use nym_coconut_dkg_common::verification_key::PagedVKSharesResponse;
use nym_contracts_common_testing::{ChainOpts, ContractOpts};
#[test]
fn transferring_ownership() -> anyhow::Result<()> {
@@ -248,6 +267,7 @@ mod tests_with_mock {
contract.run_initial_dummy_dkg();
let old_index = DEALERS_INDICES.load(&contract, &group_member)?;
let old_details = EPOCH_DEALERS_MAP.load(&contract, (0, &group_member))?;
let old_share = vk_shares().load(&contract, (&group_member, 0))?;
let not_group_member = contract.addr_make("not_group_member");
let (deps, env) = contract.deps_mut_env();
@@ -277,13 +297,20 @@ mod tests_with_mock {
assert!(EPOCH_DEALERS_MAP
.may_load(&contract, (0, &group_member))?
.is_none());
assert!(vk_shares()
.may_load(&contract, (&group_member, 0))?
.is_none());
let new_index = DEALERS_INDICES.load(&contract, &new_group_member)?;
let new_details = EPOCH_DEALERS_MAP.load(&contract, (0, &new_group_member))?;
let new_share = vk_shares().load(&contract, (&new_group_member, 0))?;
// the underlying info hasn't changed
assert_eq!(old_index, new_index);
assert_eq!(old_details, new_details);
assert_ne!(old_share, new_share);
assert_eq!(old_share.owner, group_member);
assert_eq!(new_share.owner, new_group_member);
assert_eq!(
OWNERSHIP_TRANSFER_LOG.load(
@@ -436,9 +463,91 @@ mod tests_with_mock {
assert_eq!(old_details1, new_details1);
assert_eq!(old_details2, new_details2);
// most recent entry is updated
// most recent entry is updated
assert_eq!(new_details3.announce_address, new_address);
Ok(())
}
#[test]
fn updating_announce_address_updates_vk_shares() -> anyhow::Result<()> {
let mut contract = init_contract_tester_with_group_members(3);
let group_member = contract.random_group_member();
contract.run_initial_dummy_dkg(); // => epoch 0
contract.run_reset_dkg(); // => epoch 1
// LEAVE DKG MEMBERSHIP
contract.remove_group_member(group_member.clone());
contract.run_reset_dkg(); // => epoch 2
// COME BACK
contract.add_group_member(group_member.clone());
contract.run_reset_dkg(); // => epoch 3
let old_address = EPOCH_DEALERS_MAP
.load(&contract, (3, &group_member))?
.announce_address;
let old_share0 = vk_shares().load(&contract, (&group_member, 0))?;
let old_share1 = vk_shares().load(&contract, (&group_member, 1))?;
let old_share2 = vk_shares().may_load(&contract, (&group_member, 2))?;
assert!(old_share2.is_none());
let old_share3 = vk_shares().may_load(&contract, (&group_member, 3))?;
assert!(old_share3.is_some());
let new_address = "https://new-address.com".to_string();
try_update_announce_address(
contract.deps_mut(),
message_info(&group_member, &[]),
new_address.clone(),
)?;
let new_share0 = vk_shares().load(&contract, (&group_member, 0))?;
let new_share1 = vk_shares().load(&contract, (&group_member, 1))?;
let new_share2 = vk_shares().may_load(&contract, (&group_member, 2))?;
assert!(new_share2.is_none());
let new_share3 = vk_shares().load(&contract, (&group_member, 3))?;
// old epoch data is unchanged
assert_eq!(old_share0, new_share0);
assert_eq!(old_share1, new_share1);
assert_eq!(old_share2, new_share2);
// most recent entry is updated
assert_eq!(new_share3.announce_address, new_address);
// finally an integration check against query endpoint
let epoch0_shares: PagedVKSharesResponse =
contract.query(&QueryMsg::GetVerificationKeys {
epoch_id: 0,
limit: None,
start_after: None,
})?;
assert_eq!(epoch0_shares.shares.len(), 3);
let member_share = epoch0_shares
.shares
.iter()
.find(|s| s.owner == group_member)
.context("failed to find member's share")?;
assert_eq!(member_share.announce_address, old_address);
let epoch0_shares: PagedVKSharesResponse =
contract.query(&QueryMsg::GetVerificationKeys {
epoch_id: 3,
limit: None,
start_after: None,
})?;
assert_eq!(epoch0_shares.shares.len(), 3);
let member_share = epoch0_shares
.shares
.iter()
.find(|s| s.owner == group_member)
.context("failed to find member's share")?;
assert_eq!(member_share.announce_address, new_address);
Ok(())
}
}
@@ -62,12 +62,18 @@ impl TestableNymContract for DkgContract {
where
Self: Sized,
{
init_contract_tester_with_group_members(DEFAULT_GROUP_MEMBERS)
init_contract_tester()
}
}
pub fn init_contract_tester() -> ContractTester<DkgContract> {
DkgContract::init().with_common_storage_key(CommonStorageKeys::Admin, "dkg-admin")
init_contract_tester_with_group_members(DEFAULT_GROUP_MEMBERS)
}
pub fn init_contract_tester_with_group_members(members: usize) -> ContractTester<DkgContract> {
prepare_contract_tester_builder_with_group_members(members)
.build()
.with_common_storage_key(CommonStorageKeys::Admin, "dkg-admin")
}
pub fn prepare_contract_tester_builder_with_group_members<C>(
@@ -137,12 +143,6 @@ where
builder
}
pub fn init_contract_tester_with_group_members(members: usize) -> ContractTester<DkgContract> {
prepare_contract_tester_builder_with_group_members(members)
.build()
.with_common_storage_key(CommonStorageKeys::Admin, "dkg-admin")
}
pub trait DkgContractTesterExt:
ContractOpts<ExecuteMsg = ExecuteMsg, QueryMsg = QueryMsg, ContractError = ContractError>
+ ChainOpts
-12
View File
@@ -1,12 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn legacy_mixnode_bonding() {
todo!()
}
}
-4
View File
@@ -2,7 +2,3 @@
// SPDX-License-Identifier: Apache-2.0
pub(crate) mod transactions;
// the purpose of that module is to keep track of tests of legacy features that will eventually be phased out
// such as standalone mixnode/gateway bonding
pub(crate) mod legacy;
+16 -16
View File
@@ -2,23 +2,23 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
reactStrictMode: true,
basePath: "/explorer",
assetPrefix: "/explorer",
trailingSlash: false,
basePath: "/explorer",
assetPrefix: "/explorer",
trailingSlash: false,
async redirects() {
return [
// Change the basePath to /explorer
{
source: "/",
destination: "/explorer",
basePath: false,
permanent: true,
},
];
},
async redirects() {
return [
// Change the basePath to /explorer
{
source: "/",
destination: "/explorer",
basePath: false,
permanent: true,
},
];
},
};
module.exports = nextConfig
module.exports = nextConfig;
@@ -1,5 +1,6 @@
"use client";
import type { IObservatoryNode } from "@/app/api/types";
import { NYM_ACCOUNT_ADDRESS } from "@/app/api/urls";
import { Search } from "@mui/icons-material";
import {
Autocomplete,
@@ -13,7 +14,6 @@ import { useQuery } from "@tanstack/react-query";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { fetchObservatoryNodes } from "../../app/api";
import { NYM_ACCOUNT_ADDRESS } from "@/app/api/urls";
const NodeAndAddressSearch = () => {
const router = useRouter();
@@ -50,7 +50,7 @@ const NodeAndAddressSearch = () => {
}
} catch {
setErrorText(
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again."
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again.",
);
setIsLoading(false); // Stop loading
@@ -58,7 +58,7 @@ const NodeAndAddressSearch = () => {
}
} else {
setErrorText(
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again."
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again.",
);
setIsLoading(false); // Stop loading
@@ -68,7 +68,7 @@ const NodeAndAddressSearch = () => {
// Check if it's a node identity key
if (nymNodes) {
const matchingNode = nymNodes.find(
(node) => node.identity_key === inputValue
(node) => node.identity_key === inputValue,
);
if (matchingNode) {
@@ -77,13 +77,13 @@ const NodeAndAddressSearch = () => {
}
}
setErrorText(
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again."
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again.",
);
setIsLoading(false);
}
} catch (error) {
setErrorText(
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again."
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again.",
);
console.error(error);
setIsLoading(false); // Stop loading
@@ -92,7 +92,7 @@ const NodeAndAddressSearch = () => {
// Handle search input change
const handleSearchInputChange = (
event: React.ChangeEvent<HTMLInputElement>
event: React.ChangeEvent<HTMLInputElement>,
) => {
const value = event.target.value;
setInputValue(value);
@@ -107,7 +107,7 @@ const NodeAndAddressSearch = () => {
const filteredNodes = nymNodes.filter((node) =>
node.self_description?.moniker
?.toLowerCase()
.includes(value.toLowerCase())
.includes(value.toLowerCase()),
);
setSearchOptions(filteredNodes);
} else {
@@ -118,7 +118,7 @@ const NodeAndAddressSearch = () => {
// Handle node selection from dropdown
const handleNodeSelect = (
event: React.SyntheticEvent,
value: string | IObservatoryNode | null
value: string | IObservatoryNode | null,
) => {
if (value && typeof value !== "string") {
setIsLoading(true); // Show loading spinner
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "extension-storage"
version = "1.4.0-rc.0"
version = "1.4.1"
edition = "2024"
license = "Apache-2.0"
repository = "https://github.com/nymtech/nym"
@@ -57,7 +57,7 @@ async fn run(
.clone()
.expect("rust sdk mainnet default missing api_url");
let nym_api = nym_http_api_client::ClientBuilder::new_with_urls(vec![default_api_url.into()])
let nym_api = nym_http_api_client::ClientBuilder::new_with_urls(vec![default_api_url.into()])?
.no_hickory_dns()
.with_timeout(nym_api_client_timeout)
.build()?;
@@ -98,7 +98,7 @@ impl Monitor {
.expect("rust sdk mainnet default missing api_url");
let nym_api =
nym_http_api_client::ClientBuilder::new_with_urls(vec![default_api_url.into()])
nym_http_api_client::ClientBuilder::new_with_urls(vec![default_api_url.into()])?
.no_hickory_dns()
.with_timeout(self.nym_api_client_timeout)
.build()?;
@@ -56,6 +56,53 @@ pub struct MixnetClientConfig {
}
impl BuilderConfig {
/// Creates a new BuilderConfig with all required parameters.
///
/// However, consider using `BuilderConfig::builder()` instead.
#[allow(clippy::too_many_arguments)]
pub fn new(
entry_node: NymNodeWithKeys,
exit_node: NymNodeWithKeys,
data_path: Option<PathBuf>,
mixnet_client_config: MixnetClientConfig,
two_hops: bool,
user_agent: UserAgent,
custom_topology_provider: Box<dyn TopologyProvider + Send + Sync>,
network_env: NymNetworkDetails,
cancel_token: CancellationToken,
#[cfg(unix)] connection_fd_callback: Arc<dyn Fn(RawFd) + Send + Sync>,
) -> Self {
Self {
entry_node,
exit_node,
data_path,
mixnet_client_config,
two_hops,
user_agent,
custom_topology_provider,
network_env,
cancel_token,
#[cfg(unix)]
connection_fd_callback,
}
}
/// Creates a builder for BuilderConfig
///
/// This is the preferred way to construct a BuilderConfig.
///
/// # Example
/// ```ignore
/// let config = BuilderConfig::builder()
/// .entry_node(entry)
/// .exit_node(exit)
/// .user_agent(agent)
/// .build()?;
/// ```
pub fn builder() -> BuilderConfigBuilder {
BuilderConfigBuilder::default()
}
pub fn mixnet_client_debug_config(&self) -> DebugConfig {
if self.two_hops {
two_hop_debug_config(&self.mixnet_client_config)
@@ -116,6 +163,7 @@ impl BuilderConfig {
.credentials_mode(true)
.with_remember_me(remember_me)
.custom_topology_provider(self.custom_topology_provider);
#[cfg(unix)]
let builder = builder.with_connection_fd_callback(self.connection_fd_callback);
@@ -205,3 +253,205 @@ fn log_mixnet_client_config(debug_config: &DebugConfig) {
fn true_to_disabled(val: bool) -> &'static str {
if val { "disabled" } else { "enabled" }
}
/// Error type for BuilderConfig validation
#[derive(Debug, Clone, thiserror::Error)]
#[allow(clippy::enum_variant_names)]
pub enum BuilderConfigError {
#[error("entry_node is required")]
MissingEntryNode,
#[error("exit_node is required")]
MissingExitNode,
#[error("mixnet_client_config is required")]
MissingMixnetClientConfig,
#[error("user_agent is required")]
MissingUserAgent,
#[error("custom_topology_provider is required")]
MissingTopologyProvider,
#[error("network_env is required")]
MissingNetworkEnv,
#[error("cancel_token is required")]
MissingCancelToken,
#[cfg(unix)]
#[error("connection_fd_callback is required")]
MissingConnectionFdCallback,
}
/// Builder for `BuilderConfig`
///
/// This provides a more convenient way to construct a `BuilderConfig` compared to the
/// `new()` constructor with many arguments.
#[derive(Default)]
pub struct BuilderConfigBuilder {
entry_node: Option<NymNodeWithKeys>,
exit_node: Option<NymNodeWithKeys>,
data_path: Option<PathBuf>,
mixnet_client_config: Option<MixnetClientConfig>,
two_hops: bool,
user_agent: Option<UserAgent>,
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
network_env: Option<NymNetworkDetails>,
cancel_token: Option<CancellationToken>,
#[cfg(unix)]
connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
}
impl BuilderConfigBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn entry_node(mut self, entry_node: NymNodeWithKeys) -> Self {
self.entry_node = Some(entry_node);
self
}
pub fn exit_node(mut self, exit_node: NymNodeWithKeys) -> Self {
self.exit_node = Some(exit_node);
self
}
pub fn data_path(mut self, data_path: Option<PathBuf>) -> Self {
self.data_path = data_path;
self
}
pub fn mixnet_client_config(mut self, mixnet_client_config: MixnetClientConfig) -> Self {
self.mixnet_client_config = Some(mixnet_client_config);
self
}
pub fn two_hops(mut self, two_hops: bool) -> Self {
self.two_hops = two_hops;
self
}
pub fn user_agent(mut self, user_agent: UserAgent) -> Self {
self.user_agent = Some(user_agent);
self
}
pub fn custom_topology_provider(
mut self,
custom_topology_provider: Box<dyn TopologyProvider + Send + Sync>,
) -> Self {
self.custom_topology_provider = Some(custom_topology_provider);
self
}
pub fn network_env(mut self, network_env: NymNetworkDetails) -> Self {
self.network_env = Some(network_env);
self
}
pub fn cancel_token(mut self, cancel_token: CancellationToken) -> Self {
self.cancel_token = Some(cancel_token);
self
}
#[cfg(unix)]
pub fn connection_fd_callback(
mut self,
connection_fd_callback: Arc<dyn Fn(RawFd) + Send + Sync>,
) -> Self {
self.connection_fd_callback = Some(connection_fd_callback);
self
}
/// Builds the `BuilderConfig`.
///
/// Returns an error if any required field is missing.
pub fn build(self) -> Result<BuilderConfig, BuilderConfigError> {
Ok(BuilderConfig {
entry_node: self
.entry_node
.ok_or(BuilderConfigError::MissingEntryNode)?,
exit_node: self.exit_node.ok_or(BuilderConfigError::MissingExitNode)?,
data_path: self.data_path,
mixnet_client_config: self
.mixnet_client_config
.ok_or(BuilderConfigError::MissingMixnetClientConfig)?,
two_hops: self.two_hops,
user_agent: self
.user_agent
.ok_or(BuilderConfigError::MissingUserAgent)?,
custom_topology_provider: self
.custom_topology_provider
.ok_or(BuilderConfigError::MissingTopologyProvider)?,
network_env: self
.network_env
.ok_or(BuilderConfigError::MissingNetworkEnv)?,
cancel_token: self
.cancel_token
.ok_or(BuilderConfigError::MissingCancelToken)?,
#[cfg(unix)]
connection_fd_callback: self
.connection_fd_callback
.ok_or(BuilderConfigError::MissingConnectionFdCallback)?,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mixnet_client_config_default_values() {
let config = MixnetClientConfig::default();
assert!(!config.disable_poisson_rate);
assert!(!config.disable_background_cover_traffic);
assert_eq!(config.min_mixnode_performance, None);
assert_eq!(config.min_gateway_performance, None);
}
#[test]
fn test_builder_config_builder_fails_without_required_fields() {
// Building without any fields should fail with specific error
let result = BuilderConfig::builder().build();
assert!(result.is_err());
match result {
Err(BuilderConfigError::MissingEntryNode) => (), // Expected
Err(e) => panic!("Expected MissingEntryNode, got: {}", e),
Ok(_) => panic!("Expected error, got Ok"),
}
}
#[test]
fn test_builder_config_builder_validates_all_required_fields() {
// Test that each required field is validated
let result = BuilderConfig::builder().build();
assert!(result.is_err());
// Short-circuits at first missing field, so we just verify it's one of the expected errors
#[allow(unreachable_patterns)] // All variants are covered, but keeping catch-all for safety
match result {
Err(BuilderConfigError::MissingEntryNode)
| Err(BuilderConfigError::MissingExitNode)
| Err(BuilderConfigError::MissingMixnetClientConfig)
| Err(BuilderConfigError::MissingUserAgent)
| Err(BuilderConfigError::MissingTopologyProvider)
| Err(BuilderConfigError::MissingNetworkEnv)
| Err(BuilderConfigError::MissingCancelToken) => (),
#[cfg(unix)]
Err(BuilderConfigError::MissingConnectionFdCallback) => (),
Err(e) => panic!("Unexpected error: {}", e),
Ok(_) => panic!("Expected validation error, got Ok"),
}
}
#[test]
fn test_builder_config_builder_method_chaining() {
// Test that builder methods chain properly and return Self
let builder = BuilderConfig::builder();
// Verify the builder returns itself for chaining
let builder = builder.two_hops(true);
let builder = builder.two_hops(false);
let builder = builder.data_path(None);
// Builder should still fail because required fields are missing
let result = builder.build();
assert!(result.is_err());
}
}
+3 -24
View File
@@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "NymWallet"
@@ -773,7 +773,7 @@ dependencies = [
[[package]]
name = "bls12_381"
version = "0.8.0"
source = "git+https://github.com/jstuczyn/bls12_381?branch=temp/experimental-serdect-updated#9bf520059cb28323fc51469cae86868ef4fa6fbd"
source = "git+https://github.com/jstuczyn/bls12_381?branch=temp%2Fexperimental-serdect-updated#9bf520059cb28323fc51469cae86868ef4fa6fbd"
dependencies = [
"digest 0.10.7",
"ff",
@@ -1723,15 +1723,6 @@ dependencies = [
"dirs-sys 0.3.7",
]
[[package]]
name = "dirs"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
dependencies = [
"dirs-sys 0.4.1",
]
[[package]]
name = "dirs"
version = "6.0.0"
@@ -1752,18 +1743,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "dirs-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
"redox_users 0.4.6",
"windows-sys 0.48.0",
]
[[package]]
name = "dirs-sys"
version = "0.5.0"
@@ -4100,7 +4079,7 @@ dependencies = [
name = "nym-config"
version = "0.1.0"
dependencies = [
"dirs 5.0.1",
"dirs 6.0.0",
"handlebars",
"log",
"nym-network-defaults",
+4
View File
@@ -80,6 +80,7 @@
"@types/big.js": "^6.1.6",
"@types/bs58": "^4.0.1",
"@types/jest": "^27.0.1",
"@types/minimatch": "5.1.2",
"@types/node": "^16.7.13",
"@types/qrcode.react": "^1.0.2",
"@types/react": "^18.0.26",
@@ -131,5 +132,8 @@
"webpack-favicons": "^1.3.8",
"webpack-merge": "^5.8.0"
},
"resolutions": {
"@types/minimatch": "5.1.2"
},
"private": false
}
+22 -26
View File
@@ -1,32 +1,32 @@
import React from 'react';
import { Box, Typography, Grid, Link, Card, CardContent, Stack } from '@mui/material';
import { NymCard } from '..';
import BitfinexIcon from 'src/svg-icons/bitfinex.svg';
import KrakenIcon from 'src/svg-icons/kraken.svg';
import BybitIcon from 'src/svg-icons/bybit.svg';
import GateIcon from 'src/svg-icons/gate22.svg';
import HTXIcon from 'src/svg-icons/htx.svg';
import { NymCard } from '..';
const ExchangeCard = ({
name,
tokenType,
url,
IconComponent
const ExchangeCard = ({
name,
tokenType,
url,
IconComponent,
}: {
name: string;
tokenType: string;
url: string;
IconComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
}) => (
<Card
variant="outlined"
sx={{
<Card
variant="outlined"
sx={{
height: '100%',
transition: 'all 0.2s ease-in-out',
'&:hover': {
transform: 'translateY(-2px)',
boxShadow: 2,
}
},
}}
>
<CardContent sx={{ p: 3 }}>
@@ -51,17 +51,17 @@ const ExchangeCard = ({
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
{tokenType}
</Typography>
<Link
href={url}
target="_blank"
<Link
href={url}
target="_blank"
variant="body2"
data-testid="link-get-nym"
sx={{
sx={{
textDecoration: 'underline',
fontWeight: 500,
'&:hover': {
textDecoration: 'none',
}
},
}}
>
GET NYM
@@ -78,44 +78,40 @@ export const Tutorial = () => {
name: 'Bitfinex',
tokenType: 'Native NYM, ERC-20',
url: 'https://www.bitfinex.com/',
IconComponent: BitfinexIcon
IconComponent: BitfinexIcon,
},
{
name: 'Kraken',
tokenType: 'Native NYM',
url: 'https://www.kraken.com/',
IconComponent: KrakenIcon
IconComponent: KrakenIcon,
},
{
name: 'Bybit',
tokenType: 'ERC-20',
url: 'https://www.bybit.com/en/',
IconComponent: BybitIcon
IconComponent: BybitIcon,
},
{
name: 'Gate.io',
tokenType: 'ERC-20',
url: 'https://www.gate.io/',
IconComponent: GateIcon
IconComponent: GateIcon,
},
{
name: 'HTX',
tokenType: 'ERC-20',
url: 'https://www.htx.com/',
IconComponent: HTXIcon
IconComponent: HTXIcon,
},
];
return (
<NymCard
borderless
title="Where you can get NYM tokens"
sx={{ mt: 4 }}
>
<NymCard borderless title="Where you can get NYM tokens" sx={{ mt: 4 }}>
<Typography mb={3} fontSize={14} sx={{ color: 'text.secondary' }}>
You can get NYM tokens from these exchanges
</Typography>
<Grid container spacing={3}>
{exchanges.map((exchange) => (
<Grid item xs={12} md={6} lg={4} key={exchange.name}>
+41 -40
View File
@@ -1,49 +1,41 @@
{
"name": "@nymproject/nymsphere",
"version": "1.0.0",
"private": true,
"version": "1.0.1",
"license": "Apache 2.0",
"workspaces": [
"sdk/typescript/packages/**",
"sdk/typescript/examples/**",
"ts-packages/*",
"nym-wallet",
"explorer-nextjs",
"explorer-v2",
"types",
"clients/validator",
"sdk/typescript/packages/**",
"sdk/typescript/examples/**",
"sdk/typescript/codegen/**"
],
"scripts": {
"nuke": "npx rimraf **/node_modules node_modules",
"scrub": "npx rimraf **/dist dist",
"clean": "lerna run clean",
"audit:fix": "npm_config_yes=true npx yarn-audit-fix -- --dry-run",
"build": "run-s build:types build:packages",
"build:wasm": "make sdk-wasm-build",
"build:types": "lerna run --scope @nymproject/types build --stream",
"build:packages": "run-s build:packages:theme build:packages:react",
"build:packages:theme": "lerna run --scope @nymproject/mui-theme build",
"build:packages:react": "lerna run --scope @nymproject/react build",
"build:playground": "lerna run --scope @nymproject/react storybook:build --stream",
"build:ci": "run-s build:types build:packages build:wasm build:ci:sdk",
"build:ci:sdk": "lerna run --scope '{@nymproject/sdk,@nymproject/node-tester,@nymproject/sdk-react,@nymproject/mix-fetch,@nymproject/nodejs-client,@nymproject/mix-fetch-node}' build --stream",
"build:ci:storybook": "yarn build && yarn dev:on && run-p build:playground && yarn build:ci:storybook:collect-artifacts ",
"build:ci:storybook:collect-artifacts": "mkdir -p ts-packages/dist && mv sdk/typescript/packages/react-components/storybook-static ts-packages/dist/storybook ",
"prebuild:ci": "yarn dev:on && yarn",
"build:ci": "run-s build:types build:packages build:wasm build:ci:sdk",
"postbuild:ci": "yarn dev:off",
"build:ci:sdk": "lerna run --scope '{@nymproject/sdk,@nymproject/node-tester,@nymproject/sdk-react,@nymproject/mix-fetch,@nymproject/nodejs-client,@nymproject/mix-fetch-node}' build --stream",
"build:packages": "run-s build:packages:theme build:packages:react",
"build:packages:react": "lerna run --scope @nymproject/react build",
"build:packages:theme": "lerna run --scope @nymproject/mui-theme build",
"build:playground": "lerna run --scope @nymproject/react storybook:build --stream",
"build:types": "lerna run --scope @nymproject/types build --stream",
"build:wasm": "make sdk-wasm-build",
"clean": "lerna run clean",
"dev:off": "node sdk/typescript/scripts/dev-mode-remove.mjs",
"dev:on": "node sdk/typescript/scripts/dev-mode-add.mjs",
"docs:prod:build": "run-s docs:prod:build:ws",
"docs:prod:build:ws": "lerna run docs:prod:build --stream",
"sdk:build": "./sdk/typescript/scripts/build-prod-sdk.sh",
"sdk:publish": "./sdk/typescript/scripts/publish.sh",
"lint": "lerna run lint --stream",
"lint:fix": "lerna run lint:fix --stream",
"nuke": "npx rimraf **/node_modules node_modules",
"postbuild:ci": "yarn dev:off",
"prebuild:ci": "yarn dev:on && yarn",
"scrub": "npx rimraf **/dist dist",
"sdk:build": "./sdk/typescript/scripts/build-prod-sdk.sh",
"sdk:publish": "./sdk/typescript/scripts/publish.sh",
"sdk:versions:add-rc": "cargo run -p sdk-version-bump --pre-release",
"sdk:versions:bump": "cargo run -p sdk-version-bump bump-version",
"sdk:versions:remove-rc": "cargo run -p sdk-version-bump remove-suffix",
"tsc": "lerna run tsc --stream",
"types:lint:fix": "lerna run lint:fix --scope @nymproject/types --scope @nymproject/nym-wallet-app",
"audit:fix": "npm_config_yes=true npx yarn-audit-fix -- --dry-run",
"dev:on": "node sdk/typescript/scripts/dev-mode-add.mjs",
"dev:off": "node sdk/typescript/scripts/dev-mode-remove.mjs"
"types:lint:fix": "lerna run lint:fix --scope @nymproject/types --scope @nymproject/nym-wallet-app"
},
"dependencies": {
"lucide-react": "^0.453.0"
},
"devDependencies": {
"@npmcli/node-gyp": "^3.0.0",
@@ -53,14 +45,23 @@
"npm-run-all": "^4.1.5",
"tslog": "3.3.3"
},
"dependencies": {
"lucide-react": "^0.453.0"
},
"private": true,
"resolutions": {
"@cosmjs/amino": "^0.32.4",
"@cosmjs/cosmwasm-stargate": "^0.32.4",
"@cosmjs/proto-signing": "^0.32.4",
"@cosmjs/stargate": "^0.32.4",
"@cosmjs/cosmwasm-stargate": "^0.32.4",
"cosmjs-types": "^0.9.0"
}
}
},
"workspaces": [
"ts-packages/*",
"nym-wallet",
"explorer-nextjs",
"explorer-v2",
"types",
"clients/validator",
"sdk/typescript/packages/mix-fetch/internal-dev",
"sdk/typescript/packages/react-components",
"sdk/typescript/packages/mui-theme"
]
}
@@ -155,7 +155,7 @@ check_ip_routing() {
perform_pings() {
echo "Performing IPv4 ping to google.com..."
ping -c 4 google.com
ping -4 -c 4 google.com
echo "---------------------------------------"
echo "Performing IPv6 ping to google.com..."
ping6 -c 4 google.com
@@ -189,7 +189,7 @@ test_bridge_connectivity() {
echo -e "Testing IPv4 connectivity..."
echo
if ping -c 1 -I "$ipv4_address" google.com >/dev/null 2>&1; then
if ping -4 -c 1 -I "$ipv4_address" google.com >/dev/null 2>&1; then
echo -e "${green}IPv4 connectivity is working. Fetching test data...${reset}"
joke=$(curl -s -H "Accept: application/json" --interface "$ipv4_address" https://icanhazdadjoke.com/ | jq -r .joke)
[[ -n "$joke" && "$joke" != "null" ]] && echo -e "${green}IPv4 test joke: $joke${reset}" || echo -e "${red}Failed to fetch test data via IPv4.${reset}"
@@ -277,7 +277,7 @@ check_bridge_installation() {
# Check keys directory
if [[ -d "$BRIDGE_KEYS_DIR" ]]; then
echo -e "${green}✓ Keys directory exists: $BRIDGE_KEYS_DIR${reset}"
key_count=$(ls -1 "$BRIDGE_KEYS_DIR"/*.pem 2>/dev/null | wc -l)
key_count=$(sudo bash -c "ls -1 \"$BRIDGE_KEYS_DIR\"/*.pem" 2>/dev/null | wc -l)
echo " Keys found: $key_count"
else
echo -e "${red}✗ Keys directory not found: $BRIDGE_KEYS_DIR${reset}"
@@ -494,7 +494,7 @@ generate_bridge_keys() {
# Generate ED25519 private key
local key_file="$BRIDGE_KEYS_DIR/ed25519_bridge_identity.pem"
if [[ -f "$key_file" ]]; then
if sudo test -f "$key_file"; then
echo -e "${yellow}Warning: Key file already exists at $key_file${reset}"
read -p "Overwrite existing key? (yes/no): " confirm
if [[ "$confirm" != "yes" ]]; then
@@ -532,14 +532,14 @@ create_client_params() {
# Check if key exists
local key_file="$BRIDGE_KEYS_DIR/ed25519_bridge_identity.pem"
if [[ ! -f "$key_file" ]]; then
if ! sudo test -f "$key_file"; then
echo -e "${red}Error: Bridge key not found at $key_file${reset}"
echo "Run 'nym-bridge-helper generate_bridge_keys' first"
return 1
fi
# Get forward address
read -p "Enter forward address (e.g., <IPv4>:51822, can be found by running 'curl -6 https://ifconfig.co/ip'): " forward_addr
read -p "Enter forward address (e.g., <IPv4>:51822, can be found by running 'curl -4 https://ifconfig.co/ip'): " forward_addr
if [[ -z "$forward_addr" ]]; then
echo -e "${red}Error: Forward address is required${reset}"
return 1
@@ -722,24 +722,28 @@ install_bridge_binary() {
local red="\033[0;31m"
local yellow="\033[0;33m"
local deb_arch="amd64"
local sys_arch=$(dpkg --print-architecture)
if [[ "$deb_arch" != "$sys_arch" ]]; then
echo -e "${red}Error: aborting .deb package installation as this system's arch is not amd64.${reset}"
echo " Refer to https://github.com/nymtech/nym-bridges for build instructions."
exit 1
fi
echo -e "${yellow}=== Installing nym-bridge Binary ===${reset}"
echo ""
read -p "Enter bridge binary URL for your system from here https://builds.ci.nymte.ch/QUIC/: " binary_url
if [[ -z "$binary_url" ]]; then
echo -e "${red}Error: Binary URL is required${reset}"
return 1
fi
echo "Retrieving URL to latest release..."
local binary_url=$(
curl -s "https://api.github.com/repos/nymtech/nym-bridges/releases/latest" |
grep "browser_download_url.*amd64.deb" |
grep -o 'https://[^"]*'
)
echo "Downloading nym-bridge binary..."
if sudo curl -L "$binary_url" -o "$BRIDGE_BINARY"; then
sudo chmod 755 "$BRIDGE_BINARY"
echo -e "${green}✓ Bridge binary installed at $BRIDGE_BINARY${reset}"
# Show version
echo ""
echo "Binary version:"
$BRIDGE_BINARY --version || echo "Unable to determine version"
echo "Downloading $binary_url ..."
if curl -L -o "/tmp/$(basename "$binary_url")" "$binary_url"; then
sudo dpkg -i "/tmp/$(basename "$binary_url")"
else
echo -e "${red}✗ Failed to download bridge binary${reset}"
return 1
+33 -3
View File
@@ -555,21 +555,22 @@ where
async fn available_gateways(&mut self) -> Result<Vec<RoutingNode>, ClientCoreError> {
if let Some(ref mut custom_provider) = self.custom_topology_provider {
if let Some(topology) = custom_provider.get_new_topology().await {
return Ok(topology.entry_gateways().cloned().collect());
// Use entry_capable_nodes() instead of entry_gateways() to include
// all entry-capable nodes, not just actively assigned ones
return Ok(topology.entry_capable_nodes().cloned().collect());
}
}
let nym_api_endpoints = self.get_api_endpoints();
let topology_cfg = &self.config.debug_config.topology;
let user_agent = self.user_agent.clone();
let mut rng = OsRng;
gateways_for_init(
&mut rng,
&nym_api_endpoints,
user_agent,
topology_cfg.minimum_gateway_performance,
topology_cfg.ignore_ingress_epoch_role,
None,
)
.await
}
@@ -705,6 +706,16 @@ where
.config
.as_base_client_config(nyxd_endpoints, nym_api_endpoints.clone());
tracing::debug!(
"SDK: Passing nym_api_urls to BaseClientBuilder (has {} nym_api_urls)",
self.config
.network_details
.nym_api_urls
.as_ref()
.map(|urls| urls.len())
.unwrap_or(0)
);
let mut base_builder: BaseClientBuilder<_, _> =
BaseClientBuilder::new(base_config, self.storage, self.dkg_query_client)
.with_wait_for_gateway(self.wait_for_gateway)
@@ -712,6 +723,11 @@ where
.with_remember_me(&self.remember_me)
.with_derivation_material(self.derivation_material);
// Add nym_api_urls if available in network_details
if let Some(nym_api_urls) = self.config.network_details.nym_api_urls.clone() {
base_builder = base_builder.with_nym_api_urls(nym_api_urls);
}
if let Some(user_agent) = self.user_agent {
base_builder = base_builder.with_user_agent(user_agent);
}
@@ -880,3 +896,17 @@ impl IncludedSurbs {
Self::ExposeSelfAddress
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mixnet_builder_default_no_custom_client() {
let builder = MixnetClientBuilder::new_ephemeral();
assert!(
builder.build().is_ok(),
"Builder should succeed without custom client"
);
}
}
@@ -3,13 +3,11 @@ import codegen from '@cosmwasm/ts-codegen';
codegen
.default({
contracts: [
{ name: 'coconut-bandwidth', dir: '../../../../contracts/coconut-bandwidth' },
{ name: 'ecash', dir: '../../../../contracts/ecash' },
{ name: 'coconut-dkg', dir: '../../../../contracts/coconut-dkg' },
{ name: 'mixnet', dir: '../../../../contracts/mixnet' },
{ name: 'cw3-flex-multisig', dir: '../../../../contracts/multisig/cw3-flex-multisig' },
{ name: 'cw4-group', dir: '../../../../contracts/multisig/cw4-group' },
{ name: 'name-service', dir: '../../../../contracts/name-service' },
{ name: 'service-provider-directory', dir: '../../../../contracts/service-provider-directory' },
{ name: 'vesting', dir: '../../../../contracts/vesting' },
],
outPath: './src',
@@ -1,6 +1,6 @@
{
"name": "@nymproject/contract-clients",
"version": "1.3.0-rc.0",
"version": "1.3.1-rc0",
"description": "A client for all Nym smart contracts",
"license": "Apache-2.0",
"author": "Nym Technologies SA",
@@ -18,7 +18,7 @@
"docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\""
},
"devDependencies": {
"@cosmwasm/ts-codegen": "^0.35.3",
"@cosmwasm/ts-codegen": "^1.13.3",
"nodemon": "3.0.1",
"npm-run-all": "^4.1.5",
"reload": "^3.2.1",
@@ -27,4 +27,4 @@
},
"private": false,
"types": "./dist/index.d.ts"
}
}
@@ -1,23 +1,58 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3.
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate";
import { Coin, StdFee } from "@cosmjs/amino";
import { InstantiateMsg, TimeConfiguration, ExecuteMsg, ContractSafeBytes, Addr, QueryMsg, MigrateMsg, PagedDealerResponse, DealerDetails, Timestamp, Uint64, EpochState, Epoch, DealerType, DealerDetailsResponse, PagedDealingsResponse, ContractDealing, NullableInitialReplacementData, InitialReplacementData, PagedVKSharesResponse, ContractVKShare } from "./CoconutDkg.types";
import { ICosmWasmClient, ISigningCosmWasmClient } from "./baseClient";
import { Coin, StdFee } from "@interchainjs/types";
import { InstantiateMsg, TimeConfiguration, ExecuteMsg, ContractSafeBytes, DealingChunkInfo, PartialContractDealing, QueryMsg, MigrateMsg, EpochState, Timestamp, Uint64, StateAdvanceResponse, StateProgress, ContractVersion, Addr, PagedDealerResponse, DealerDetails, Epoch, DealerDealingsStatusResponse, DealerType, DealerDetailsResponse, PagedDealerIndexResponse, DealingChunkResponse, DealingChunkStatusResponse, ChunkSubmissionStatus, DealingStatusResponse, DealingStatus, DealingMetadataResponse, DealingMetadata, PagedDealerAddressesResponse, NullableEpoch, RegisteredDealerDetails, DealerRegistrationDetails, Cw4Contract, State, VkShareResponse, ContractVKShare, PagedVKSharesResponse } from "./CoconutDkg.types";
export interface CoconutDkgReadOnlyInterface {
contractAddress: string;
getState: () => Promise<State>;
getCurrentEpochState: () => Promise<Epoch>;
getEpochStateAtHeight: ({
height
}: {
height: number;
}) => Promise<NullableEpoch>;
getCurrentEpochThreshold: () => Promise<Uint64>;
getInitialDealers: () => Promise<NullableInitialReplacementData>;
getEpochThreshold: ({
epochId
}: {
epochId: number;
}) => Promise<Uint64>;
canAdvanceState: () => Promise<StateAdvanceResponse>;
getRegisteredDealer: ({
dealerAddress,
epochId
}: {
dealerAddress: string;
epochId?: number;
}) => Promise<RegisteredDealerDetails>;
getDealerDetails: ({
dealerAddress
}: {
dealerAddress: string;
}) => Promise<DealerDetailsResponse>;
getEpochDealersAddresses: ({
epochId,
limit,
startAfter
}: {
epochId: number;
limit?: number;
startAfter?: string;
}) => Promise<PagedDealerAddressesResponse>;
getEpochDealers: ({
epochId,
limit,
startAfter
}: {
epochId: number;
limit?: number;
startAfter?: string;
}) => Promise<PagedDealerResponse>;
getCurrentDealers: ({
limit,
startAfter
@@ -25,22 +60,67 @@ export interface CoconutDkgReadOnlyInterface {
limit?: number;
startAfter?: string;
}) => Promise<PagedDealerResponse>;
getPastDealers: ({
getDealerIndices: ({
limit,
startAfter
}: {
limit?: number;
startAfter?: string;
}) => Promise<PagedDealerResponse>;
getDealing: ({
idx,
limit,
startAfter
}) => Promise<PagedDealerIndexResponse>;
getDealingsMetadata: ({
dealer,
dealingIndex,
epochId
}: {
idx: number;
limit?: number;
startAfter?: string;
}) => Promise<PagedDealingsResponse>;
dealer: string;
dealingIndex: number;
epochId: number;
}) => Promise<DealingMetadataResponse>;
getDealerDealingsStatus: ({
dealer,
epochId
}: {
dealer: string;
epochId: number;
}) => Promise<DealerDealingsStatusResponse>;
getDealingStatus: ({
dealer,
dealingIndex,
epochId
}: {
dealer: string;
dealingIndex: number;
epochId: number;
}) => Promise<DealingStatusResponse>;
getDealingChunkStatus: ({
chunkIndex,
dealer,
dealingIndex,
epochId
}: {
chunkIndex: number;
dealer: string;
dealingIndex: number;
epochId: number;
}) => Promise<DealingChunkStatusResponse>;
getDealingChunk: ({
chunkIndex,
dealer,
dealingIndex,
epochId
}: {
chunkIndex: number;
dealer: string;
dealingIndex: number;
epochId: number;
}) => Promise<DealingChunkResponse>;
getVerificationKey: ({
epochId,
owner
}: {
epochId: number;
owner: string;
}) => Promise<VkShareResponse>;
getVerificationKeys: ({
epochId,
limit,
@@ -50,37 +130,89 @@ export interface CoconutDkgReadOnlyInterface {
limit?: number;
startAfter?: string;
}) => Promise<PagedVKSharesResponse>;
getCw2ContractVersion: () => Promise<GetCw2ContractVersionResponse>;
}
export class CoconutDkgQueryClient implements CoconutDkgReadOnlyInterface {
client: CosmWasmClient;
client: ICosmWasmClient;
contractAddress: string;
constructor(client: CosmWasmClient, contractAddress: string) {
constructor(client: ICosmWasmClient, contractAddress: string) {
this.client = client;
this.contractAddress = contractAddress;
this.getState = this.getState.bind(this);
this.getCurrentEpochState = this.getCurrentEpochState.bind(this);
this.getEpochStateAtHeight = this.getEpochStateAtHeight.bind(this);
this.getCurrentEpochThreshold = this.getCurrentEpochThreshold.bind(this);
this.getInitialDealers = this.getInitialDealers.bind(this);
this.getEpochThreshold = this.getEpochThreshold.bind(this);
this.canAdvanceState = this.canAdvanceState.bind(this);
this.getRegisteredDealer = this.getRegisteredDealer.bind(this);
this.getDealerDetails = this.getDealerDetails.bind(this);
this.getEpochDealersAddresses = this.getEpochDealersAddresses.bind(this);
this.getEpochDealers = this.getEpochDealers.bind(this);
this.getCurrentDealers = this.getCurrentDealers.bind(this);
this.getPastDealers = this.getPastDealers.bind(this);
this.getDealing = this.getDealing.bind(this);
this.getDealerIndices = this.getDealerIndices.bind(this);
this.getDealingsMetadata = this.getDealingsMetadata.bind(this);
this.getDealerDealingsStatus = this.getDealerDealingsStatus.bind(this);
this.getDealingStatus = this.getDealingStatus.bind(this);
this.getDealingChunkStatus = this.getDealingChunkStatus.bind(this);
this.getDealingChunk = this.getDealingChunk.bind(this);
this.getVerificationKey = this.getVerificationKey.bind(this);
this.getVerificationKeys = this.getVerificationKeys.bind(this);
this.getCw2ContractVersion = this.getCw2ContractVersion.bind(this);
}
getState = async (): Promise<State> => {
return this.client.queryContractSmart(this.contractAddress, {
get_state: {}
});
};
getCurrentEpochState = async (): Promise<Epoch> => {
return this.client.queryContractSmart(this.contractAddress, {
get_current_epoch_state: {}
});
};
getEpochStateAtHeight = async ({
height
}: {
height: number;
}): Promise<NullableEpoch> => {
return this.client.queryContractSmart(this.contractAddress, {
get_epoch_state_at_height: {
height
}
});
};
getCurrentEpochThreshold = async (): Promise<Uint64> => {
return this.client.queryContractSmart(this.contractAddress, {
get_current_epoch_threshold: {}
});
};
getInitialDealers = async (): Promise<NullableInitialReplacementData> => {
getEpochThreshold = async ({
epochId
}: {
epochId: number;
}): Promise<Uint64> => {
return this.client.queryContractSmart(this.contractAddress, {
get_initial_dealers: {}
get_epoch_threshold: {
epoch_id: epochId
}
});
};
canAdvanceState = async (): Promise<StateAdvanceResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
can_advance_state: {}
});
};
getRegisteredDealer = async ({
dealerAddress,
epochId
}: {
dealerAddress: string;
epochId?: number;
}): Promise<RegisteredDealerDetails> => {
return this.client.queryContractSmart(this.contractAddress, {
get_registered_dealer: {
dealer_address: dealerAddress,
epoch_id: epochId
}
});
};
getDealerDetails = async ({
@@ -94,6 +226,40 @@ export class CoconutDkgQueryClient implements CoconutDkgReadOnlyInterface {
}
});
};
getEpochDealersAddresses = async ({
epochId,
limit,
startAfter
}: {
epochId: number;
limit?: number;
startAfter?: string;
}): Promise<PagedDealerAddressesResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_epoch_dealers_addresses: {
epoch_id: epochId,
limit,
start_after: startAfter
}
});
};
getEpochDealers = async ({
epochId,
limit,
startAfter
}: {
epochId: number;
limit?: number;
startAfter?: string;
}): Promise<PagedDealerResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_epoch_dealers: {
epoch_id: epochId,
limit,
start_after: startAfter
}
});
};
getCurrentDealers = async ({
limit,
startAfter
@@ -108,34 +274,119 @@ export class CoconutDkgQueryClient implements CoconutDkgReadOnlyInterface {
}
});
};
getPastDealers = async ({
getDealerIndices = async ({
limit,
startAfter
}: {
limit?: number;
startAfter?: string;
}): Promise<PagedDealerResponse> => {
}): Promise<PagedDealerIndexResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_past_dealers: {
get_dealer_indices: {
limit,
start_after: startAfter
}
});
};
getDealing = async ({
idx,
limit,
startAfter
getDealingsMetadata = async ({
dealer,
dealingIndex,
epochId
}: {
idx: number;
limit?: number;
startAfter?: string;
}): Promise<PagedDealingsResponse> => {
dealer: string;
dealingIndex: number;
epochId: number;
}): Promise<DealingMetadataResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_dealing: {
idx,
limit,
start_after: startAfter
get_dealings_metadata: {
dealer,
dealing_index: dealingIndex,
epoch_id: epochId
}
});
};
getDealerDealingsStatus = async ({
dealer,
epochId
}: {
dealer: string;
epochId: number;
}): Promise<DealerDealingsStatusResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_dealer_dealings_status: {
dealer,
epoch_id: epochId
}
});
};
getDealingStatus = async ({
dealer,
dealingIndex,
epochId
}: {
dealer: string;
dealingIndex: number;
epochId: number;
}): Promise<DealingStatusResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_dealing_status: {
dealer,
dealing_index: dealingIndex,
epoch_id: epochId
}
});
};
getDealingChunkStatus = async ({
chunkIndex,
dealer,
dealingIndex,
epochId
}: {
chunkIndex: number;
dealer: string;
dealingIndex: number;
epochId: number;
}): Promise<DealingChunkStatusResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_dealing_chunk_status: {
chunk_index: chunkIndex,
dealer,
dealing_index: dealingIndex,
epoch_id: epochId
}
});
};
getDealingChunk = async ({
chunkIndex,
dealer,
dealingIndex,
epochId
}: {
chunkIndex: number;
dealer: string;
dealingIndex: number;
epochId: number;
}): Promise<DealingChunkResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_dealing_chunk: {
chunk_index: chunkIndex,
dealer,
dealing_index: dealingIndex,
epoch_id: epochId
}
});
};
getVerificationKey = async ({
epochId,
owner
}: {
epochId: number;
owner: string;
}): Promise<VkShareResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_verification_key: {
epoch_id: epochId,
owner
}
});
};
@@ -156,91 +407,142 @@ export class CoconutDkgQueryClient implements CoconutDkgReadOnlyInterface {
}
});
};
getCw2ContractVersion = async (): Promise<GetCw2ContractVersionResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_cw2_contract_version: {}
});
};
}
export interface CoconutDkgInterface extends CoconutDkgReadOnlyInterface {
contractAddress: string;
sender: string;
initiateDkg: (fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
registerDealer: ({
announceAddress,
bteKeyWithProof,
identityKey,
resharing
}: {
announceAddress: string;
bteKeyWithProof: string;
identityKey: string;
resharing: boolean;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
commitDealing: ({
dealingBytes,
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
commitDealingsMetadata: ({
chunks,
dealingIndex,
resharing
}: {
dealingBytes: ContractSafeBytes;
chunks: DealingChunkInfo[];
dealingIndex: number;
resharing: boolean;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
commitDealingsChunk: ({
chunk
}: {
chunk: PartialContractDealing;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
commitVerificationKeyShare: ({
resharing,
share
}: {
resharing: boolean;
share: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
verifyVerificationKeyShare: ({
owner,
resharing
}: {
owner: Addr;
owner: string;
resharing: boolean;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
surpassedThreshold: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
advanceEpochState: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
advanceEpochState: (fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
triggerReset: (fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
triggerResharing: (fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
transferOwnership: ({
transferTo
}: {
transferTo: string;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
updateAnnounceAddress: ({
newAddress
}: {
newAddress: string;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
}
export class CoconutDkgClient extends CoconutDkgQueryClient implements CoconutDkgInterface {
client: SigningCosmWasmClient;
client: ISigningCosmWasmClient;
sender: string;
contractAddress: string;
constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) {
constructor(client: ISigningCosmWasmClient, sender: string, contractAddress: string) {
super(client, contractAddress);
this.client = client;
this.sender = sender;
this.contractAddress = contractAddress;
this.initiateDkg = this.initiateDkg.bind(this);
this.registerDealer = this.registerDealer.bind(this);
this.commitDealing = this.commitDealing.bind(this);
this.commitDealingsMetadata = this.commitDealingsMetadata.bind(this);
this.commitDealingsChunk = this.commitDealingsChunk.bind(this);
this.commitVerificationKeyShare = this.commitVerificationKeyShare.bind(this);
this.verifyVerificationKeyShare = this.verifyVerificationKeyShare.bind(this);
this.surpassedThreshold = this.surpassedThreshold.bind(this);
this.advanceEpochState = this.advanceEpochState.bind(this);
this.triggerReset = this.triggerReset.bind(this);
this.triggerResharing = this.triggerResharing.bind(this);
this.transferOwnership = this.transferOwnership.bind(this);
this.updateAnnounceAddress = this.updateAnnounceAddress.bind(this);
}
initiateDkg = async (fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
initiate_dkg: {}
}, fee_, memo_, funds_);
};
registerDealer = async ({
announceAddress,
bteKeyWithProof,
identityKey,
resharing
}: {
announceAddress: string;
bteKeyWithProof: string;
identityKey: string;
resharing: boolean;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
register_dealer: {
announce_address: announceAddress,
bte_key_with_proof: bteKeyWithProof,
identity_key: identityKey,
resharing
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
commitDealing = async ({
dealingBytes,
commitDealingsMetadata = async ({
chunks,
dealingIndex,
resharing
}: {
dealingBytes: ContractSafeBytes;
chunks: DealingChunkInfo[];
dealingIndex: number;
resharing: boolean;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
commit_dealing: {
dealing_bytes: dealingBytes,
commit_dealings_metadata: {
chunks,
dealing_index: dealingIndex,
resharing
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
commitDealingsChunk = async ({
chunk
}: {
chunk: PartialContractDealing;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
commit_dealings_chunk: {
chunk
}
}, fee_, memo_, funds_);
};
commitVerificationKeyShare = async ({
resharing,
@@ -248,36 +550,63 @@ export class CoconutDkgClient extends CoconutDkgQueryClient implements CoconutDk
}: {
resharing: boolean;
share: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
commit_verification_key_share: {
resharing,
share
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
verifyVerificationKeyShare = async ({
owner,
resharing
}: {
owner: Addr;
owner: string;
resharing: boolean;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
verify_verification_key_share: {
owner,
resharing
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
surpassedThreshold = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
return await this.client.execute(this.sender, this.contractAddress, {
surpassed_threshold: {}
}, fee, memo, _funds);
};
advanceEpochState = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
advanceEpochState = async (fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
advance_epoch_state: {}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
}
triggerReset = async (fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
trigger_reset: {}
}, fee_, memo_, funds_);
};
triggerResharing = async (fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
trigger_resharing: {}
}, fee_, memo_, funds_);
};
transferOwnership = async ({
transferTo
}: {
transferTo: string;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
transfer_ownership: {
transfer_to: transferTo
}
}, fee_, memo_, funds_);
};
updateAnnounceAddress = async ({
newAddress
}: {
newAddress: string;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
update_announce_address: {
new_address: newAddress
}
}, fee_, memo_, funds_);
};
}
@@ -1,11 +1,12 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3.
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
export interface InstantiateMsg {
group_addr: string;
key_size: number;
mix_denom: string;
multisig_addr: string;
time_configuration?: TimeConfiguration | null;
@@ -19,16 +20,24 @@ export interface TimeConfiguration {
verification_key_validation_time_secs: number;
}
export type ExecuteMsg = {
initiate_dkg: {};
} | {
register_dealer: {
announce_address: string;
bte_key_with_proof: string;
identity_key: string;
resharing: boolean;
};
} | {
commit_dealing: {
dealing_bytes: ContractSafeBytes;
commit_dealings_metadata: {
chunks: DealingChunkInfo[];
dealing_index: number;
resharing: boolean;
};
} | {
commit_dealings_chunk: {
chunk: PartialContractDealing;
};
} | {
commit_verification_key_share: {
resharing: boolean;
@@ -36,41 +45,115 @@ export type ExecuteMsg = {
};
} | {
verify_verification_key_share: {
owner: Addr;
owner: string;
resharing: boolean;
};
} | {
surpassed_threshold: {};
} | {
advance_epoch_state: {};
} | {
trigger_reset: {};
} | {
trigger_resharing: {};
} | {
transfer_ownership: {
transfer_to: string;
};
} | {
update_announce_address: {
new_address: string;
};
};
export type ContractSafeBytes = number[];
export type Addr = string;
export interface DealingChunkInfo {
size: number;
}
export interface PartialContractDealing {
chunk_index: number;
data: ContractSafeBytes;
dealing_index: number;
}
export type QueryMsg = {
get_state: {};
} | {
get_current_epoch_state: {};
} | {
get_epoch_state_at_height: {
height: number;
};
} | {
get_current_epoch_threshold: {};
} | {
get_initial_dealers: {};
get_epoch_threshold: {
epoch_id: number;
};
} | {
can_advance_state: {};
} | {
get_registered_dealer: {
dealer_address: string;
epoch_id?: number | null;
};
} | {
get_dealer_details: {
dealer_address: string;
};
} | {
get_epoch_dealers_addresses: {
epoch_id: number;
limit?: number | null;
start_after?: string | null;
};
} | {
get_epoch_dealers: {
epoch_id: number;
limit?: number | null;
start_after?: string | null;
};
} | {
get_current_dealers: {
limit?: number | null;
start_after?: string | null;
};
} | {
get_past_dealers: {
get_dealer_indices: {
limit?: number | null;
start_after?: string | null;
};
} | {
get_dealing: {
idx: number;
limit?: number | null;
start_after?: string | null;
get_dealings_metadata: {
dealer: string;
dealing_index: number;
epoch_id: number;
};
} | {
get_dealer_dealings_status: {
dealer: string;
epoch_id: number;
};
} | {
get_dealing_status: {
dealer: string;
dealing_index: number;
epoch_id: number;
};
} | {
get_dealing_chunk_status: {
chunk_index: number;
dealer: string;
dealing_index: number;
epoch_id: number;
};
} | {
get_dealing_chunk: {
chunk_index: number;
dealer: string;
dealing_index: number;
epoch_id: number;
};
} | {
get_verification_key: {
epoch_id: number;
owner: string;
};
} | {
get_verification_keys: {
@@ -78,22 +161,11 @@ export type QueryMsg = {
limit?: number | null;
start_after?: string | null;
};
} | {
get_cw2_contract_version: {};
};
export interface MigrateMsg {}
export interface PagedDealerResponse {
dealers: DealerDetails[];
per_page: number;
start_next_after?: Addr | null;
}
export interface DealerDetails {
address: Addr;
announce_address: string;
assigned_index: number;
bte_public_key_with_proof: string;
}
export type Timestamp = Uint64;
export type Uint64 = number;
export type EpochState = "in_progress" | {
export type EpochState = ("waiting_initialisation" | "in_progress") | {
public_key_submission: {
resharing: boolean;
};
@@ -114,36 +186,132 @@ export type EpochState = "in_progress" | {
resharing: boolean;
};
};
export type Timestamp = Uint64;
export type Uint64 = number;
export interface StateAdvanceResponse {
current_state: EpochState;
deadline?: Timestamp | null;
is_complete: boolean;
progress: StateProgress;
reached_deadline: boolean;
}
export interface StateProgress {
registered_dealers: number;
registered_resharing_dealers: number;
submitted_dealings: number;
submitted_key_shares: number;
verified_keys: number;
}
export interface ContractVersion {
contract: string;
version: string;
}
export type Addr = string;
export interface PagedDealerResponse {
dealers: DealerDetails[];
per_page: number;
start_next_after?: Addr | null;
}
export interface DealerDetails {
address: Addr;
announce_address: string;
assigned_index: number;
bte_public_key_with_proof: string;
ed25519_identity: string;
}
export interface Epoch {
deadline?: Timestamp | null;
epoch_id: number;
finish_timestamp: Timestamp;
state: EpochState;
state_progress: StateProgress;
time_configuration: TimeConfiguration;
}
export type DealerType = "current" | "past" | "unknown";
export interface DealerDealingsStatusResponse {
all_dealings_fully_submitted: boolean;
dealer: Addr;
dealing_submission_status: {};
epoch_id: number;
}
export type DealerType = "unknown" | {
current: {
assigned_index: number;
};
} | {
past: {
assigned_index: number;
};
};
export interface DealerDetailsResponse {
dealer_type: DealerType;
details?: DealerDetails | null;
}
export interface PagedDealingsResponse {
dealings: ContractDealing[];
per_page: number;
export interface PagedDealerIndexResponse {
indices: [Addr, number][];
start_next_after?: Addr | null;
}
export interface ContractDealing {
export interface DealingChunkResponse {
chunk?: ContractSafeBytes | null;
chunk_index: number;
dealer: Addr;
dealing: ContractSafeBytes;
dealing_index: number;
epoch_id: number;
}
export type NullableInitialReplacementData = InitialReplacementData | null;
export interface InitialReplacementData {
initial_dealers: Addr[];
initial_height: number;
export interface DealingChunkStatusResponse {
chunk_index: number;
dealer: Addr;
dealing_index: number;
epoch_id: number;
status: ChunkSubmissionStatus;
}
export interface PagedVKSharesResponse {
per_page: number;
shares: ContractVKShare[];
export interface ChunkSubmissionStatus {
submission_height?: number | null;
}
export interface DealingStatusResponse {
dealer: Addr;
dealing_index: number;
epoch_id: number;
status: DealingStatus;
}
export interface DealingStatus {
chunk_submission_status: {};
fully_submitted: boolean;
has_metadata: boolean;
}
export interface DealingMetadataResponse {
dealer: Addr;
dealing_index: number;
epoch_id: number;
metadata?: DealingMetadata | null;
}
export interface DealingMetadata {
dealing_index: number;
submitted_chunks: {};
}
export interface PagedDealerAddressesResponse {
dealers: Addr[];
start_next_after?: Addr | null;
}
export type NullableEpoch = Epoch | null;
export interface RegisteredDealerDetails {
details?: DealerRegistrationDetails | null;
}
export interface DealerRegistrationDetails {
announce_address: string;
bte_public_key_with_proof: string;
ed25519_identity: string;
}
export type Cw4Contract = Addr;
export interface State {
group_addr: Cw4Contract;
key_size: number;
mix_denom: string;
multisig_addr: Addr;
}
export interface VkShareResponse {
epoch_id: number;
owner: Addr;
share?: ContractVKShare | null;
}
export interface ContractVKShare {
announce_address: string;
epoch_id: number;
@@ -151,4 +319,9 @@ export interface ContractVKShare {
owner: Addr;
share: string;
verified: boolean;
}
export interface PagedVKSharesResponse {
per_page: number;
shares: ContractVKShare[];
start_next_after?: Addr | null;
}
@@ -1,13 +1,12 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3.
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate";
import { StdFee } from "@cosmjs/amino";
import { Executor, Addr, Duration, Uint128, UncheckedDenom, Threshold, Decimal, InstantiateMsg, UncheckedDepositInfo, ExecuteMsg, Expiration, Timestamp, Uint64, CosmosMsgForEmpty, BankMsg, StakingMsg, DistributionMsg, Binary, IbcMsg, WasmMsg, GovMsg, VoteOption, Vote, Coin, Empty, IbcTimeout, IbcTimeoutBlock, MemberChangedHookMsg, MemberDiff, QueryMsg, MigrateMsg, Cw4Contract, Denom, Config, DepositInfo, Status, ThresholdResponse, ProposalListResponseForEmpty, ProposalResponseForEmpty, VoterListResponse, VoterDetail, VoteListResponse, VoteInfo, VoteResponse, VoterResponse } from "./Cw3FlexMultisig.types";
import { ICosmWasmClient, ISigningCosmWasmClient } from "./baseClient";
import { StdFee } from "@interchainjs/types";
import { Executor, Addr, Duration, Uint128, UncheckedDenom, Threshold, Decimal, InstantiateMsg, UncheckedDepositInfo, ExecuteMsg, Expiration, Timestamp, Uint64, CosmosMsgForEmpty, BankMsg, WasmMsg, Binary, Vote, Coin, Empty, MemberChangedHookMsg, MemberDiff, QueryMsg, MigrateMsg, Cw4Contract, Denom, Config, DepositInfo, Status, ThresholdResponse, ProposalListResponseForEmpty, ProposalResponseForEmpty, VoterListResponse, VoterDetail, VoteListResponse, VoteInfo, VoteResponse, VoterResponse } from "./Cw3FlexMultisig.types";
export interface Cw3FlexMultisigReadOnlyInterface {
contractAddress: string;
threshold: () => Promise<ThresholdResponse>;
@@ -61,10 +60,9 @@ export interface Cw3FlexMultisigReadOnlyInterface {
config: () => Promise<Config>;
}
export class Cw3FlexMultisigQueryClient implements Cw3FlexMultisigReadOnlyInterface {
client: CosmWasmClient;
client: ICosmWasmClient;
contractAddress: string;
constructor(client: CosmWasmClient, contractAddress: string) {
constructor(client: ICosmWasmClient, contractAddress: string) {
this.client = client;
this.contractAddress = contractAddress;
this.threshold = this.threshold.bind(this);
@@ -77,7 +75,6 @@ export class Cw3FlexMultisigQueryClient implements Cw3FlexMultisigReadOnlyInterf
this.listVoters = this.listVoters.bind(this);
this.config = this.config.bind(this);
}
threshold = async (): Promise<ThresholdResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
threshold: {}
@@ -197,36 +194,35 @@ export interface Cw3FlexMultisigInterface extends Cw3FlexMultisigReadOnlyInterfa
latest?: Expiration;
msgs: CosmosMsgForEmpty[];
title: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
// vote: ({
// proposalId,
// vote
// }: {
// proposalId: number;
// vote: Vote;
// }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
vote: ({
proposalId,
vote
}: {
proposalId: number;
vote: Vote;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
execute: ({
proposalId
}: {
proposalId: number;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
close: ({
proposalId
}: {
proposalId: number;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
memberChangedHook: ({
diffs
}: {
diffs: MemberDiff[];
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
}
export class Cw3FlexMultisigClient extends Cw3FlexMultisigQueryClient implements Cw3FlexMultisigInterface {
client: SigningCosmWasmClient;
client: ISigningCosmWasmClient;
sender: string;
contractAddress: string;
constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) {
constructor(client: ISigningCosmWasmClient, sender: string, contractAddress: string) {
super(client, contractAddress);
this.client = client;
this.sender = sender;
@@ -237,7 +233,6 @@ export class Cw3FlexMultisigClient extends Cw3FlexMultisigQueryClient implements
this.close = this.close.bind(this);
this.memberChangedHook = this.memberChangedHook.bind(this);
}
propose = async ({
description,
latest,
@@ -248,7 +243,7 @@ export class Cw3FlexMultisigClient extends Cw3FlexMultisigQueryClient implements
latest?: Expiration;
msgs: CosmosMsgForEmpty[];
title: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
propose: {
description,
@@ -256,53 +251,53 @@ export class Cw3FlexMultisigClient extends Cw3FlexMultisigQueryClient implements
msgs,
title
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
vote = async ({
proposalId,
vote
}: {
proposalId: number;
vote: Vote;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
vote: {
proposal_id: proposalId,
vote
}
}, fee_, memo_, funds_);
};
// vote = async ({
// proposalId,
// vote
// }: {
// proposalId: number;
// vote: Vote;
// }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
// return await this.client.execute(this.sender, this.contractAddress, {
// vote: {
// proposal_id: proposalId,
// vote
// }
// }, fee, memo, _funds);
// };
execute = async ({
proposalId
}: {
proposalId: number;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
execute: {
proposal_id: proposalId
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
close = async ({
proposalId
}: {
proposalId: number;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
close: {
proposal_id: proposalId
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
memberChangedHook = async ({
diffs
}: {
diffs: MemberDiff[];
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
member_changed_hook: {
diffs
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
}
}
@@ -1,5 +1,5 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3.
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
@@ -84,86 +84,17 @@ export type CosmosMsgForEmpty = {
bank: BankMsg;
} | {
custom: Empty;
} | {
staking: StakingMsg;
} | {
distribution: DistributionMsg;
} | {
stargate: {
type_url: string;
value: Binary;
[k: string]: unknown;
};
} | {
ibc: IbcMsg;
} | {
wasm: WasmMsg;
} | {
gov: GovMsg;
};
export type BankMsg = {
send: {
amount: Coin[];
to_address: string;
[k: string]: unknown;
};
} | {
burn: {
amount: Coin[];
[k: string]: unknown;
};
};
export type StakingMsg = {
delegate: {
amount: Coin;
validator: string;
[k: string]: unknown;
};
} | {
undelegate: {
amount: Coin;
validator: string;
[k: string]: unknown;
};
} | {
redelegate: {
amount: Coin;
dst_validator: string;
src_validator: string;
[k: string]: unknown;
};
};
export type DistributionMsg = {
set_withdraw_address: {
address: string;
[k: string]: unknown;
};
} | {
withdraw_delegator_reward: {
validator: string;
[k: string]: unknown;
};
};
export type Binary = string;
export type IbcMsg = {
transfer: {
amount: Coin;
channel_id: string;
timeout: IbcTimeout;
to_address: string;
[k: string]: unknown;
};
} | {
send_packet: {
channel_id: string;
data: Binary;
timeout: IbcTimeout;
[k: string]: unknown;
};
} | {
close_channel: {
channel_id: string;
[k: string]: unknown;
};
};
export type WasmMsg = {
@@ -171,7 +102,6 @@ export type WasmMsg = {
contract_addr: string;
funds: Coin[];
msg: Binary;
[k: string]: unknown;
};
} | {
instantiate: {
@@ -180,54 +110,30 @@ export type WasmMsg = {
funds: Coin[];
label: string;
msg: Binary;
[k: string]: unknown;
};
} | {
migrate: {
contract_addr: string;
msg: Binary;
new_code_id: number;
[k: string]: unknown;
};
} | {
update_admin: {
admin: string;
contract_addr: string;
[k: string]: unknown;
};
} | {
clear_admin: {
contract_addr: string;
[k: string]: unknown;
};
};
export type GovMsg = {
vote: {
proposal_id: number;
vote: VoteOption;
[k: string]: unknown;
};
};
export type VoteOption = "yes" | "no" | "abstain" | "no_with_veto";
export type Binary = string;
export type Vote = "yes" | "no" | "abstain" | "veto";
export interface Coin {
amount: Uint128;
denom: string;
[k: string]: unknown;
}
export interface Empty {
[k: string]: unknown;
}
export interface IbcTimeout {
block?: IbcTimeoutBlock | null;
timestamp?: Timestamp | null;
[k: string]: unknown;
}
export interface IbcTimeoutBlock {
height: number;
revision: number;
[k: string]: unknown;
}
export interface Empty {}
export interface MemberChangedHookMsg {
diffs: MemberDiff[];
}
@@ -1,13 +1,12 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3.
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate";
import { Coin, StdFee } from "@cosmjs/amino";
import { ICosmWasmClient, ISigningCosmWasmClient } from "./baseClient";
import { Coin, StdFee } from "@interchainjs/types";
import { InstantiateMsg, Member, ExecuteMsg, QueryMsg, MigrateMsg, AdminResponse, HooksResponse, MemberListResponse, MemberResponse, TotalWeightResponse } from "./Cw4Group.types";
export interface Cw4GroupReadOnlyInterface {
contractAddress: string;
admin: () => Promise<AdminResponse>;
@@ -33,10 +32,9 @@ export interface Cw4GroupReadOnlyInterface {
hooks: () => Promise<HooksResponse>;
}
export class Cw4GroupQueryClient implements Cw4GroupReadOnlyInterface {
client: CosmWasmClient;
client: ICosmWasmClient;
contractAddress: string;
constructor(client: CosmWasmClient, contractAddress: string) {
constructor(client: ICosmWasmClient, contractAddress: string) {
this.client = client;
this.contractAddress = contractAddress;
this.admin = this.admin.bind(this);
@@ -45,7 +43,6 @@ export class Cw4GroupQueryClient implements Cw4GroupReadOnlyInterface {
this.member = this.member.bind(this);
this.hooks = this.hooks.bind(this);
}
admin = async (): Promise<AdminResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
admin: {}
@@ -103,31 +100,30 @@ export interface Cw4GroupInterface extends Cw4GroupReadOnlyInterface {
admin
}: {
admin?: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
updateMembers: ({
add,
remove
}: {
add: Member[];
remove: string[];
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
addHook: ({
addr
}: {
addr: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
removeHook: ({
addr
}: {
addr: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
}
export class Cw4GroupClient extends Cw4GroupQueryClient implements Cw4GroupInterface {
client: SigningCosmWasmClient;
client: ISigningCosmWasmClient;
sender: string;
contractAddress: string;
constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) {
constructor(client: ISigningCosmWasmClient, sender: string, contractAddress: string) {
super(client, contractAddress);
this.client = client;
this.sender = sender;
@@ -137,17 +133,16 @@ export class Cw4GroupClient extends Cw4GroupQueryClient implements Cw4GroupInter
this.addHook = this.addHook.bind(this);
this.removeHook = this.removeHook.bind(this);
}
updateAdmin = async ({
admin
}: {
admin?: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
update_admin: {
admin
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
updateMembers = async ({
add,
@@ -155,34 +150,34 @@ export class Cw4GroupClient extends Cw4GroupQueryClient implements Cw4GroupInter
}: {
add: Member[];
remove: string[];
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
update_members: {
add,
remove
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
addHook = async ({
addr
}: {
addr: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
add_hook: {
addr
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
removeHook = async ({
addr
}: {
addr: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
remove_hook: {
addr
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
}
}
@@ -1,5 +1,5 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3.
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
@@ -0,0 +1,256 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import { ICosmWasmClient, ISigningCosmWasmClient } from "./baseClient";
import { StdFee } from "@interchainjs/types";
import { Uint128, InstantiateMsg, Coin, ExecuteMsg, QueryMsg, MigrateMsg, PagedBlacklistedAccountResponse, BlacklistedAccount, Blacklisting, BlacklistedAccountResponse, DepositResponse, Deposit, PagedDepositsResponse, DepositData, LatestDepositResponse } from "./Ecash.types";
export interface EcashReadOnlyInterface {
contractAddress: string;
getBlacklistedAccount: ({
publicKey
}: {
publicKey: string;
}) => Promise<BlacklistedAccountResponse>;
getBlacklistPaged: ({
limit,
startAfter
}: {
limit?: number;
startAfter?: string;
}) => Promise<PagedBlacklistedAccountResponse>;
getRequiredDepositAmount: () => Promise<Coin>;
getDeposit: ({
depositId
}: {
depositId: number;
}) => Promise<DepositResponse>;
getLatestDeposit: () => Promise<LatestDepositResponse>;
getDepositsPaged: ({
limit,
startAfter
}: {
limit?: number;
startAfter?: number;
}) => Promise<PagedDepositsResponse>;
}
export class EcashQueryClient implements EcashReadOnlyInterface {
client: ICosmWasmClient;
contractAddress: string;
constructor(client: ICosmWasmClient, contractAddress: string) {
this.client = client;
this.contractAddress = contractAddress;
this.getBlacklistedAccount = this.getBlacklistedAccount.bind(this);
this.getBlacklistPaged = this.getBlacklistPaged.bind(this);
this.getRequiredDepositAmount = this.getRequiredDepositAmount.bind(this);
this.getDeposit = this.getDeposit.bind(this);
this.getLatestDeposit = this.getLatestDeposit.bind(this);
this.getDepositsPaged = this.getDepositsPaged.bind(this);
}
getBlacklistedAccount = async ({
publicKey
}: {
publicKey: string;
}): Promise<BlacklistedAccountResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_blacklisted_account: {
public_key: publicKey
}
});
};
getBlacklistPaged = async ({
limit,
startAfter
}: {
limit?: number;
startAfter?: string;
}): Promise<PagedBlacklistedAccountResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_blacklist_paged: {
limit,
start_after: startAfter
}
});
};
getRequiredDepositAmount = async (): Promise<Coin> => {
return this.client.queryContractSmart(this.contractAddress, {
get_required_deposit_amount: {}
});
};
getDeposit = async ({
depositId
}: {
depositId: number;
}): Promise<DepositResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_deposit: {
deposit_id: depositId
}
});
};
getLatestDeposit = async (): Promise<LatestDepositResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_latest_deposit: {}
});
};
getDepositsPaged = async ({
limit,
startAfter
}: {
limit?: number;
startAfter?: number;
}): Promise<PagedDepositsResponse> => {
return this.client.queryContractSmart(this.contractAddress, {
get_deposits_paged: {
limit,
start_after: startAfter
}
});
};
}
export interface EcashInterface extends EcashReadOnlyInterface {
contractAddress: string;
sender: string;
depositTicketBookFunds: ({
identityKey
}: {
identityKey: string;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
requestRedemption: ({
commitmentBs58,
numberOfTickets
}: {
commitmentBs58: string;
numberOfTickets: number;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
redeemTickets: ({
gw,
n
}: {
gw: string;
n: number;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
updateAdmin: ({
admin
}: {
admin: string;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
updateDepositValue: ({
newDeposit
}: {
newDeposit: Coin;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
proposeToBlacklist: ({
publicKey
}: {
publicKey: string;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
addToBlacklist: ({
publicKey
}: {
publicKey: string;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
}
export class EcashClient extends EcashQueryClient implements EcashInterface {
client: ISigningCosmWasmClient;
sender: string;
contractAddress: string;
constructor(client: ISigningCosmWasmClient, sender: string, contractAddress: string) {
super(client, contractAddress);
this.client = client;
this.sender = sender;
this.contractAddress = contractAddress;
this.depositTicketBookFunds = this.depositTicketBookFunds.bind(this);
this.requestRedemption = this.requestRedemption.bind(this);
this.redeemTickets = this.redeemTickets.bind(this);
this.updateAdmin = this.updateAdmin.bind(this);
this.updateDepositValue = this.updateDepositValue.bind(this);
this.proposeToBlacklist = this.proposeToBlacklist.bind(this);
this.addToBlacklist = this.addToBlacklist.bind(this);
}
depositTicketBookFunds = async ({
identityKey
}: {
identityKey: string;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
deposit_ticket_book_funds: {
identity_key: identityKey
}
}, fee_, memo_, funds_);
};
requestRedemption = async ({
commitmentBs58,
numberOfTickets
}: {
commitmentBs58: string;
numberOfTickets: number;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
request_redemption: {
commitment_bs58: commitmentBs58,
number_of_tickets: numberOfTickets
}
}, fee_, memo_, funds_);
};
redeemTickets = async ({
gw,
n
}: {
gw: string;
n: number;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
redeem_tickets: {
gw,
n
}
}, fee_, memo_, funds_);
};
updateAdmin = async ({
admin
}: {
admin: string;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
update_admin: {
admin
}
}, fee_, memo_, funds_);
};
updateDepositValue = async ({
newDeposit
}: {
newDeposit: Coin;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
update_deposit_value: {
new_deposit: newDeposit
}
}, fee_, memo_, funds_);
};
proposeToBlacklist = async ({
publicKey
}: {
publicKey: string;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
propose_to_blacklist: {
public_key: publicKey
}
}, fee_, memo_, funds_);
};
addToBlacklist = async ({
publicKey
}: {
publicKey: string;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
add_to_blacklist: {
public_key: publicKey
}
}, fee_, memo_, funds_);
};
}
@@ -0,0 +1,106 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
export type Uint128 = string;
export interface InstantiateMsg {
deposit_amount: Coin;
group_addr: string;
holding_account: string;
multisig_addr: string;
}
export interface Coin {
amount: Uint128;
denom: string;
}
export type ExecuteMsg = {
deposit_ticket_book_funds: {
identity_key: string;
};
} | {
request_redemption: {
commitment_bs58: string;
number_of_tickets: number;
};
} | {
redeem_tickets: {
gw: string;
n: number;
};
} | {
update_admin: {
admin: string;
};
} | {
update_deposit_value: {
new_deposit: Coin;
};
} | {
propose_to_blacklist: {
public_key: string;
};
} | {
add_to_blacklist: {
public_key: string;
};
};
export type QueryMsg = {
get_blacklisted_account: {
public_key: string;
};
} | {
get_blacklist_paged: {
limit?: number | null;
start_after?: string | null;
};
} | {
get_required_deposit_amount: {};
} | {
get_deposit: {
deposit_id: number;
};
} | {
get_latest_deposit: {};
} | {
get_deposits_paged: {
limit?: number | null;
start_after?: number | null;
};
};
export interface MigrateMsg {}
export interface PagedBlacklistedAccountResponse {
accounts: BlacklistedAccount[];
per_page: number;
start_next_after?: string | null;
}
export interface BlacklistedAccount {
info: Blacklisting;
public_key: string;
}
export interface Blacklisting {
finalized_at_height?: number | null;
proposal_id: number;
}
export interface BlacklistedAccountResponse {
account?: Blacklisting | null;
}
export interface DepositResponse {
deposit?: Deposit | null;
id: number;
}
export interface Deposit {
bs58_encoded_ed25519_pubkey: string;
}
export interface PagedDepositsResponse {
deposits: DepositData[];
start_next_after?: number | null;
}
export interface DepositData {
deposit: Deposit;
id: number;
}
export interface LatestDepositResponse {
deposit?: DepositData | null;
}
File diff suppressed because it is too large Load Diff
@@ -1,80 +1,66 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3.
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
export type Decimal = string;
export type Percent = Decimal;
/**
* This instantiates the contract.
*/
export type Uint128 = string;
export interface InstantiateMsg {
current_nym_node_version: string;
epoch_duration: Duration;
epochs_in_interval: number;
initial_rewarding_params: InitialRewardingParams;
interval_operating_cost?: RangedValueForUint128;
key_validity_in_epochs?: number | null;
profit_margin?: RangedValueForPercent;
rewarding_denom: string;
rewarding_validator_address: string;
version_score_params?: VersionScoreFormulaParams;
version_score_weights?: OutdatedVersionWeights;
vesting_contract_address: string;
}
export interface Duration {
nanos: number;
secs: number;
[k: string]: unknown;
}
export interface InitialRewardingParams {
active_set_size: number;
active_set_work_factor: Decimal;
initial_reward_pool: Decimal;
initial_staking_supply: Decimal;
interval_pool_emission: Percent;
rewarded_set_size: number;
rewarded_set_params: RewardedSetParams;
staking_supply_scale_factor: Percent;
sybil_resistance: Percent;
}
export interface RewardedSetParams {
entry_gateways: number;
exit_gateways: number;
mixnodes: number;
standby: number;
}
export interface RangedValueForUint128 {
maximum: Uint128;
minimum: Uint128;
}
export interface RangedValueForPercent {
maximum: Percent;
minimum: Percent;
}
export interface VersionScoreFormulaParams {
penalty: Decimal;
penalty_scaling: Decimal;
}
export interface OutdatedVersionWeights {
major: number;
minor: number;
patch: number;
prerelease: number;
}
export type ExecuteMsg = {
assign_node_layer: {
layer: Layer;
mix_id: number;
};
} | {
create_family: {
label: string;
};
} | {
join_family: {
family_head: FamilyHead;
join_permit: MessageSignature;
};
} | {
leave_family: {
family_head: FamilyHead;
};
} | {
kick_family_member: {
member: string;
};
} | {
create_family_on_behalf: {
label: string;
owner_address: string;
};
} | {
join_family_on_behalf: {
family_head: FamilyHead;
join_permit: MessageSignature;
member_address: string;
};
} | {
leave_family_on_behalf: {
family_head: FamilyHead;
member_address: string;
};
} | {
kick_family_member_on_behalf: {
head_address: string;
member: string;
update_admin: {
admin: string;
};
} | {
update_rewarding_validator_address: {
@@ -82,12 +68,16 @@ export type ExecuteMsg = {
};
} | {
update_contract_state_params: {
updated_parameters: ContractStateParams;
update: ContractStateParamsUpdate;
};
} | {
update_active_set_size: {
active_set_size: number;
update_current_nym_node_semver: {
current_version: string;
};
} | {
update_active_set_distribution: {
force_immediately: boolean;
update: ActiveSetUpdate;
};
} | {
update_rewarding_params: {
@@ -102,24 +92,23 @@ export type ExecuteMsg = {
};
} | {
begin_epoch_transition: {};
} | {
advance_current_epoch: {
expected_active_set_size: number;
new_rewarded_set: LayerAssignment[];
};
} | {
reconcile_epoch_events: {
limit?: number | null;
};
} | {
assign_roles: {
assignment: RoleAssignment;
};
} | {
bond_mixnode: {
cost_params: MixNodeCostParams;
cost_params: NodeCostParams;
mix_node: MixNode;
owner_signature: MessageSignature;
};
} | {
bond_mixnode_on_behalf: {
cost_params: MixNodeCostParams;
cost_params: NodeCostParams;
mix_node: MixNode;
owner: string;
owner_signature: MessageSignature;
@@ -146,12 +135,12 @@ export type ExecuteMsg = {
owner: string;
};
} | {
update_mixnode_cost_params: {
new_costs: MixNodeCostParams;
update_cost_params: {
new_costs: NodeCostParams;
};
} | {
update_mixnode_cost_params_on_behalf: {
new_costs: MixNodeCostParams;
new_costs: NodeCostParams;
owner: string;
};
} | {
@@ -163,6 +152,8 @@ export type ExecuteMsg = {
new_config: MixNodeConfigUpdate;
owner: string;
};
} | {
migrate_mixnode: {};
} | {
bond_gateway: {
gateway: Gateway;
@@ -190,8 +181,24 @@ export type ExecuteMsg = {
owner: string;
};
} | {
delegate_to_mixnode: {
mix_id: number;
migrate_gateway: {
cost_params?: NodeCostParams | null;
};
} | {
bond_nym_node: {
cost_params: NodeCostParams;
node: NymNode;
owner_signature: MessageSignature;
};
} | {
unbond_nym_node: {};
} | {
update_node_config: {
update: NodeConfigUpdate;
};
} | {
delegate: {
node_id: number;
};
} | {
delegate_to_mixnode_on_behalf: {
@@ -199,8 +206,8 @@ export type ExecuteMsg = {
mix_id: number;
};
} | {
undelegate_from_mixnode: {
mix_id: number;
undelegate: {
node_id: number;
};
} | {
undelegate_from_mixnode_on_behalf: {
@@ -208,9 +215,9 @@ export type ExecuteMsg = {
mix_id: number;
};
} | {
reward_mixnode: {
mix_id: number;
performance: Percent;
reward_node: {
node_id: number;
params: NodeRewardingParameters;
};
} | {
withdraw_operator_reward: {};
@@ -220,42 +227,62 @@ export type ExecuteMsg = {
};
} | {
withdraw_delegator_reward: {
mix_id: number;
node_id: number;
};
} | {
withdraw_delegator_reward_on_behalf: {
mix_id: number;
owner: string;
};
} | {
migrate_vested_mix_node: {};
} | {
migrate_vested_delegation: {
mix_id: number;
};
};
export type Layer = "One" | "Two" | "Three";
export type FamilyHead = string;
export type Role = "eg" | "l1" | "l2" | "l3" | "xg" | "stb";
export type MessageSignature = number[];
export type Uint128 = string;
export interface ContractStateParams {
minimum_gateway_pledge: Coin;
minimum_mixnode_delegation?: Coin | null;
minimum_mixnode_pledge: Coin;
export interface ContractStateParamsUpdate {
config_score_params?: ConfigScoreParamsUpdate | null;
delegations_params?: DelegationsParams | null;
operators_params?: OperatorsParamsUpdate | null;
}
export interface ConfigScoreParamsUpdate {
version_score_formula_params?: VersionScoreFormulaParams | null;
version_weights?: OutdatedVersionWeights | null;
}
export interface DelegationsParams {
minimum_delegation?: Coin | null;
}
export interface Coin {
amount: Uint128;
denom: string;
[k: string]: unknown;
}
export interface OperatorsParamsUpdate {
interval_operating_cost?: RangedValueForUint128 | null;
minimum_pledge?: Coin | null;
profit_margin?: RangedValueForPercent | null;
}
export interface ActiveSetUpdate {
entry_gateways: number;
exit_gateways: number;
mixnodes: number;
}
export interface IntervalRewardingParamsUpdate {
active_set_work_factor?: Decimal | null;
interval_pool_emission?: Percent | null;
reward_pool?: Decimal | null;
rewarded_set_size?: number | null;
rewarded_set_params?: RewardedSetParams | null;
staking_supply?: Decimal | null;
staking_supply_scale_factor?: Percent | null;
sybil_resistance_percent?: Percent | null;
}
export interface LayerAssignment {
layer: Layer;
mix_id: number;
export interface RoleAssignment {
nodes: number[];
role: Role;
}
export interface MixNodeCostParams {
export interface NodeCostParams {
interval_operating_cost: Coin;
profit_margin_percent: Percent;
}
@@ -291,32 +318,22 @@ export interface GatewayConfigUpdate {
mix_port: number;
version: string;
}
export interface NymNode {
custom_http_port?: number | null;
host: string;
identity_key: string;
}
export interface NodeConfigUpdate {
custom_http_port?: number | null;
host?: string | null;
restore_default_http_port?: boolean;
}
export interface NodeRewardingParameters {
performance: Percent;
work_factor: Decimal;
}
export type QueryMsg = {
get_all_families_paged: {
limit?: number | null;
start_after?: string | null;
};
} | {
get_all_members_paged: {
limit?: number | null;
start_after?: string | null;
};
} | {
get_family_by_head: {
head: string;
};
} | {
get_family_by_label: {
label: string;
};
} | {
get_family_members_by_head: {
head: string;
};
} | {
get_family_members_by_label: {
label: string;
};
admin: {};
} | {
get_contract_version: {};
} | {
@@ -327,17 +344,19 @@ export type QueryMsg = {
get_state_params: {};
} | {
get_state: {};
} | {
get_current_nym_node_version: {};
} | {
get_nym_node_version_history: {
limit?: number | null;
start_after?: number | null;
};
} | {
get_rewarding_params: {};
} | {
get_epoch_status: {};
} | {
get_current_interval_details: {};
} | {
get_rewarded_set: {
limit?: number | null;
start_after?: number | null;
};
} | {
get_mix_node_bonds: {
limit?: number | null;
@@ -389,8 +408,6 @@ export type QueryMsg = {
get_bonded_mixnode_details_by_identity: {
mix_identity: string;
};
} | {
get_layer_distribution: {};
} | {
get_gateways: {
limit?: number | null;
@@ -405,9 +422,71 @@ export type QueryMsg = {
address: string;
};
} | {
get_mixnode_delegations: {
get_preassigned_gateway_ids: {
limit?: number | null;
mix_id: number;
start_after?: string | null;
};
} | {
get_nym_node_bonds_paged: {
limit?: number | null;
start_after?: number | null;
};
} | {
get_nym_nodes_detailed_paged: {
limit?: number | null;
start_after?: number | null;
};
} | {
get_unbonded_nym_node: {
node_id: number;
};
} | {
get_unbonded_nym_nodes_paged: {
limit?: number | null;
start_after?: number | null;
};
} | {
get_unbonded_nym_nodes_by_owner_paged: {
limit?: number | null;
owner: string;
start_after?: number | null;
};
} | {
get_unbonded_nym_nodes_by_identity_key_paged: {
identity_key: string;
limit?: number | null;
start_after?: number | null;
};
} | {
get_owned_nym_node: {
address: string;
};
} | {
get_nym_node_details: {
node_id: number;
};
} | {
get_nym_node_details_by_identity_key: {
node_identity: string;
};
} | {
get_node_rewarding_details: {
node_id: number;
};
} | {
get_node_stake_saturation: {
node_id: number;
};
} | {
get_role_assignment: {
role: Role;
};
} | {
get_rewarded_set_metadata: {};
} | {
get_node_delegations: {
limit?: number | null;
node_id: number;
start_after?: string | null;
};
} | {
@@ -419,7 +498,7 @@ export type QueryMsg = {
} | {
get_delegation_details: {
delegator: string;
mix_id: number;
node_id: number;
proxy?: string | null;
};
} | {
@@ -432,26 +511,27 @@ export type QueryMsg = {
address: string;
};
} | {
get_pending_mix_node_operator_reward: {
mix_id: number;
get_pending_node_operator_reward: {
node_id: number;
};
} | {
get_pending_delegator_reward: {
address: string;
mix_id: number;
node_id: number;
proxy?: string | null;
};
} | {
get_estimated_current_epoch_operator_reward: {
estimated_performance: Percent;
mix_id: number;
estimated_work?: Decimal | null;
node_id: number;
};
} | {
get_estimated_current_epoch_delegator_reward: {
address: string;
estimated_performance: Percent;
mix_id: number;
proxy?: string | null;
estimated_work?: Decimal | null;
node_id: number;
};
} | {
get_pending_epoch_events: {
@@ -477,10 +557,18 @@ export type QueryMsg = {
get_signing_nonce: {
address: string;
};
} | {
get_key_rotation_state: {};
} | {
get_key_rotation_id: {};
};
export interface MigrateMsg {
unsafe_skip_state_updates?: boolean | null;
vesting_contract_address?: string | null;
}
export interface AdminResponse {
admin?: string | null;
}
export type Addr = string;
export interface PagedAllDelegationsResponse {
delegations: Delegation[];
@@ -490,23 +578,10 @@ export interface Delegation {
amount: Coin;
cumulative_reward_ratio: Decimal;
height: number;
mix_id: number;
node_id: number;
owner: Addr;
proxy?: Addr | null;
}
export interface PagedFamiliesResponse {
families: Family[];
start_next_after?: string | null;
}
export interface Family {
head: FamilyHead;
label: string;
proxy?: string | null;
}
export interface PagedMembersResponse {
members: [string, FamilyHead][];
start_next_after?: string | null;
}
export interface MixnodeDetailsByIdentityResponse {
identity_key: string;
mixnode_details?: MixNodeDetails | null;
@@ -514,12 +589,11 @@ export interface MixnodeDetailsByIdentityResponse {
export interface MixNodeDetails {
bond_information: MixNodeBond;
pending_changes?: PendingMixNodeChanges;
rewarding_details: MixNodeRewarding;
rewarding_details: NodeRewarding;
}
export interface MixNodeBond {
bonding_height: number;
is_unbonding: boolean;
layer: Layer;
mix_id: number;
mix_node: MixNode;
original_pledge: Coin;
@@ -527,10 +601,11 @@ export interface MixNodeBond {
proxy?: Addr | null;
}
export interface PendingMixNodeChanges {
cost_params_change?: number | null;
pledge_change?: number | null;
}
export interface MixNodeRewarding {
cost_params: MixNodeCostParams;
export interface NodeRewarding {
cost_params: NodeCostParams;
delegates: Decimal;
last_rewarded_epoch: number;
operator: Decimal;
@@ -545,9 +620,12 @@ export interface ContractVersion {
export interface ContractBuildInformation {
build_timestamp: string;
build_version: string;
cargo_debug?: string;
cargo_opt_level?: string;
commit_branch: string;
commit_sha: string;
commit_timestamp: string;
contract_name?: string;
rustc_version: string;
}
export interface CurrentIntervalResponse {
@@ -563,11 +641,29 @@ export interface Interval {
epochs_in_interval: number;
id: number;
total_elapsed_epochs: number;
[k: string]: unknown;
}
export interface MixNodeDelegationResponse {
export interface CurrentNymNodeVersionResponse {
version?: HistoricalNymNodeVersionEntry | null;
}
export interface HistoricalNymNodeVersionEntry {
id: number;
version_information: HistoricalNymNodeVersion;
}
export interface HistoricalNymNodeVersion {
difference_since_genesis: TotalVersionDifference;
introduced_at_height: number;
semver: string;
}
export interface TotalVersionDifference {
major: number;
minor: number;
patch: number;
prerelease: number;
}
export interface NodeDelegationResponse {
delegation?: Delegation | null;
mixnode_still_bonded: boolean;
node_still_bonded: boolean;
}
export interface PagedDelegatorDelegationsResponse {
delegations: Delegation[];
@@ -578,7 +674,11 @@ export type EpochState = "in_progress" | {
final_node_id: number;
last_rewarded: number;
};
} | "reconciling_events" | "advancing_epoch";
} | "reconciling_events" | {
role_assignment: {
next: Role;
};
};
export interface EpochStatus {
being_advanced_by: Addr;
state: EpochState;
@@ -590,22 +690,6 @@ export interface EstimatedCurrentEpochRewardResponse {
estimation?: Coin | null;
original_stake?: Coin | null;
}
export interface FamilyByHeadResponse {
family?: Family | null;
head: FamilyHead;
}
export interface FamilyByLabelResponse {
family?: Family | null;
label: string;
}
export interface FamilyMembersByHeadResponse {
head: FamilyHead;
members: string[];
}
export interface FamilyMembersByLabelResponse {
label: string;
members: string[];
}
export interface GatewayBondResponse {
gateway?: GatewayBond | null;
identity: string;
@@ -622,10 +706,12 @@ export interface PagedGatewayResponse {
per_page: number;
start_next_after?: string | null;
}
export interface LayerDistribution {
layer1: number;
layer2: number;
layer3: number;
export interface KeyRotationIdResponse {
rotation_id: number;
}
export interface KeyRotationState {
initial_epoch_id: number;
validity_epochs: number;
}
export interface PagedMixnodeBondsResponse {
nodes: MixNodeBond[];
@@ -637,22 +723,68 @@ export interface PagedMixnodesDetailsResponse {
per_page: number;
start_next_after?: number | null;
}
export interface PagedMixNodeDelegationsResponse {
delegations: Delegation[];
start_next_after?: string | null;
}
export interface MixnodeDetailsResponse {
mix_id: number;
mixnode_details?: MixNodeDetails | null;
}
export interface MixnodeRewardingDetailsResponse {
mix_id: number;
rewarding_details?: MixNodeRewarding | null;
rewarding_details?: NodeRewarding | null;
}
export interface PagedNodeDelegationsResponse {
delegations: Delegation[];
start_next_after?: string | null;
}
export interface NodeRewardingDetailsResponse {
node_id: number;
rewarding_details?: NodeRewarding | null;
}
export interface StakeSaturationResponse {
current_saturation?: Decimal | null;
node_id: number;
uncapped_saturation?: Decimal | null;
}
export interface NumberOfPendingEventsResponse {
epoch_events: number;
interval_events: number;
}
export interface PagedNymNodeBondsResponse {
nodes: NymNodeBond[];
start_next_after?: number | null;
}
export interface NymNodeBond {
bonding_height: number;
is_unbonding: boolean;
node: NymNode;
node_id: number;
original_pledge: Coin;
owner: Addr;
}
export interface NodeDetailsResponse {
details?: NymNodeDetails | null;
node_id: number;
}
export interface NymNodeDetails {
bond_information: NymNodeBond;
pending_changes: PendingNodeChanges;
rewarding_details: NodeRewarding;
}
export interface PendingNodeChanges {
cost_params_change?: number | null;
pledge_change?: number | null;
}
export interface NodeDetailsByIdentityResponse {
details?: NymNodeDetails | null;
identity_key: string;
}
export interface NymNodeVersionHistoryResponse {
history: HistoricalNymNodeVersionEntry[];
start_next_after?: number | null;
}
export interface PagedNymNodeDetailsResponse {
nodes: NymNodeDetails[];
start_next_after?: number | null;
}
export interface GatewayOwnershipResponse {
address: Addr;
gateway?: GatewayBond | null;
@@ -661,32 +793,47 @@ export interface MixOwnershipResponse {
address: Addr;
mixnode_details?: MixNodeDetails | null;
}
export interface NodeOwnershipResponse {
address: Addr;
details?: NymNodeDetails | null;
}
export interface PendingRewardResponse {
amount_earned?: Coin | null;
amount_earned_detailed?: Decimal | null;
amount_staked?: Coin | null;
mixnode_still_fully_bonded: boolean;
node_still_fully_bonded: boolean;
}
export type PendingEpochEventKind = {
delegate: {
amount: Coin;
mix_id: number;
node_id: number;
owner: Addr;
proxy?: Addr | null;
};
} | {
undelegate: {
mix_id: number;
node_id: number;
owner: Addr;
proxy?: Addr | null;
};
} | {
pledge_more: {
nym_node_pledge_more: {
amount: Coin;
node_id: number;
};
} | {
mixnode_pledge_more: {
amount: Coin;
mix_id: number;
};
} | {
decrease_pledge: {
nym_node_decrease_pledge: {
decrease_by: Coin;
node_id: number;
};
} | {
mixnode_decrease_pledge: {
decrease_by: Coin;
mix_id: number;
};
@@ -695,8 +842,12 @@ export type PendingEpochEventKind = {
mix_id: number;
};
} | {
update_active_set_size: {
new_size: number;
unbond_nym_node: {
node_id: number;
};
} | {
update_active_set: {
update: ActiveSetUpdate;
};
};
export interface PendingEpochEventResponse {
@@ -719,7 +870,12 @@ export interface PendingEpochEvent {
export type PendingIntervalEventKind = {
change_mix_cost_params: {
mix_id: number;
new_costs: MixNodeCostParams;
new_costs: NodeCostParams;
};
} | {
change_nym_node_cost_params: {
new_costs: NodeCostParams;
node_id: number;
};
} | {
update_rewarding_params: {
@@ -748,15 +904,34 @@ export interface PendingIntervalEvent {
event: PendingIntervalEventData;
id: number;
}
export type RewardedSetNodeStatus = "active" | "standby";
export interface PagedRewardedSetResponse {
nodes: [number, RewardedSetNodeStatus][];
start_next_after?: number | null;
export interface PreassignedGatewayIdsResponse {
ids: PreassignedId[];
start_next_after?: string | null;
}
export interface PreassignedId {
identity: string;
node_id: number;
}
export interface RolesMetadataResponse {
metadata: RewardedSetMetadata;
}
export interface RewardedSetMetadata {
entry_gateway_metadata: RoleMetadata;
epoch_id: number;
exit_gateway_metadata: RoleMetadata;
fully_assigned: boolean;
layer1_metadata: RoleMetadata;
layer2_metadata: RoleMetadata;
layer3_metadata: RoleMetadata;
standby_metadata: RoleMetadata;
}
export interface RoleMetadata {
highest_id: number;
num_nodes: number;
}
export interface RewardingParams {
active_set_size: number;
interval: IntervalRewardParams;
rewarded_set_size: number;
rewarded_set: RewardedSetParams;
}
export interface IntervalRewardParams {
active_set_work_factor: Decimal;
@@ -769,19 +944,37 @@ export interface IntervalRewardParams {
sybil_resistance: Percent;
}
export type String = string;
export interface EpochAssignmentResponse {
epoch_id: number;
nodes: number[];
}
export type Uint32 = number;
export interface StakeSaturationResponse {
export interface MixStakeSaturationResponse {
current_saturation?: Decimal | null;
mix_id: number;
uncapped_saturation?: Decimal | null;
}
export interface ContractState {
owner: Addr;
owner?: Addr | null;
params: ContractStateParams;
rewarding_denom: string;
rewarding_validator_address: Addr;
vesting_contract_address: Addr;
}
export interface ContractStateParams {
config_score_params: ConfigScoreParams;
delegations_params: DelegationsParams;
operators_params: OperatorsParams;
}
export interface ConfigScoreParams {
version_score_formula_params: VersionScoreFormulaParams;
version_weights: OutdatedVersionWeights;
}
export interface OperatorsParams {
interval_operating_cost: RangedValueForUint128;
minimum_pledge: Coin;
profit_margin: RangedValueForPercent;
}
export interface UnbondedMixnodeResponse {
mix_id: number;
unbonded_info?: UnbondedMixnode | null;
@@ -797,3 +990,17 @@ export interface PagedUnbondedMixnodesResponse {
per_page: number;
start_next_after?: number | null;
}
export interface UnbondedNodeResponse {
details?: UnbondedNymNode | null;
node_id: number;
}
export interface UnbondedNymNode {
identity_key: string;
node_id: number;
owner: Addr;
unbonding_height: number;
}
export interface PagedUnbondedNymNodesResponse {
nodes: UnbondedNymNode[];
start_next_after?: number | null;
}
@@ -1,13 +1,12 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3.
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate";
import { StdFee } from "@cosmjs/amino";
import { InstantiateMsg, ExecuteMsg, FamilyHead, MessageSignature, Uint128, Percent, Decimal, PledgeCap, Coin, MixNodeCostParams, MixNodeConfigUpdate, VestingSpecification, MixNode, Gateway, GatewayConfigUpdate, QueryMsg, Timestamp, Uint64, MigrateMsg, Addr, Account, VestingPeriod, AccountsResponse, BaseVestingAccountInfo, VestingCoinsResponse, AccountVestingCoins, AllDelegationsResponse, VestingDelegation, ContractVersion, ContractBuildInformation, Period, DelegationTimesResponse, NullablePledgeData, PledgeData, OriginalVestingResponse } from "./Vesting.types";
import { GetCw2ContractVersionResponse } from './types';
import { ICosmWasmClient, ISigningCosmWasmClient } from "./baseClient";
import { StdFee } from "@interchainjs/types";
import { InstantiateMsg, ExecuteMsg, Uint128, Percent, Decimal, PledgeCap, MessageSignature, Coin, NodeCostParams, MixNodeConfigUpdate, VestingSpecification, MixNode, Gateway, GatewayConfigUpdate, QueryMsg, Timestamp, Uint64, MigrateMsg, Addr, Account, VestingPeriod, AccountsResponse, BaseVestingAccountInfo, VestingCoinsResponse, AccountVestingCoins, AllDelegationsResponse, VestingDelegation, ContractVersion, ContractBuildInformation, Period, DelegationTimesResponse, NullablePledgeData, PledgeData, OriginalVestingResponse } from "./Vesting.types";
export interface VestingReadOnlyInterface {
contractAddress: string;
getContractVersion: () => Promise<ContractBuildInformation>;
@@ -156,10 +155,9 @@ export interface VestingReadOnlyInterface {
}) => Promise<AllDelegationsResponse>;
}
export class VestingQueryClient implements VestingReadOnlyInterface {
client: CosmWasmClient;
client: ICosmWasmClient;
contractAddress: string;
constructor(client: CosmWasmClient, contractAddress: string) {
constructor(client: ICosmWasmClient, contractAddress: string) {
this.client = client;
this.contractAddress = contractAddress;
this.getContractVersion = this.getContractVersion.bind(this);
@@ -189,7 +187,6 @@ export class VestingQueryClient implements VestingReadOnlyInterface {
this.getDelegationTimes = this.getDelegationTimes.bind(this);
this.getAllDelegations = this.getAllDelegations.bind(this);
}
getContractVersion = async (): Promise<ContractBuildInformation> => {
return this.client.queryContractSmart(this.contractAddress, {
get_contract_version: {}
@@ -501,56 +498,34 @@ export class VestingQueryClient implements VestingReadOnlyInterface {
export interface VestingInterface extends VestingReadOnlyInterface {
contractAddress: string;
sender: string;
createFamily: ({
label
}: {
label: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
joinFamily: ({
familyHead,
joinPermit
}: {
familyHead: FamilyHead;
joinPermit: MessageSignature;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
leaveFamily: ({
familyHead
}: {
familyHead: FamilyHead;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
kickFamilyMember: ({
member
}: {
member: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
trackReward: ({
address,
amount
}: {
address: string;
amount: Coin;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
claimOperatorReward: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
claimOperatorReward: (fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
claimDelegatorReward: ({
mixId
}: {
mixId: number;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
updateMixnodeCostParams: ({
newCosts
}: {
newCosts: MixNodeCostParams;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
newCosts: NodeCostParams;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
updateMixnodeConfig: ({
newConfig
}: {
newConfig: MixNodeConfigUpdate;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
updateMixnetAddress: ({
address
}: {
address: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
delegateToMixnode: ({
amount,
mixId,
@@ -559,14 +534,14 @@ export interface VestingInterface extends VestingReadOnlyInterface {
amount: Coin;
mixId: number;
onBehalfOf?: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
undelegateFromMixnode: ({
mixId,
onBehalfOf
}: {
mixId: number;
onBehalfOf?: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
createAccount: ({
cap,
ownerAddress,
@@ -577,12 +552,12 @@ export interface VestingInterface extends VestingReadOnlyInterface {
ownerAddress: string;
stakingAddress?: string;
vestingSpec?: VestingSpecification;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
withdrawVestedCoins: ({
amount
}: {
amount: Coin;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
trackUndelegation: ({
amount,
mixId,
@@ -591,7 +566,7 @@ export interface VestingInterface extends VestingReadOnlyInterface {
amount: Coin;
mixId: number;
owner: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
bondMixnode: ({
amount,
costParams,
@@ -599,35 +574,35 @@ export interface VestingInterface extends VestingReadOnlyInterface {
ownerSignature
}: {
amount: Coin;
costParams: MixNodeCostParams;
costParams: NodeCostParams;
mixNode: MixNode;
ownerSignature: MessageSignature;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
pledgeMore: ({
amount
}: {
amount: Coin;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
decreasePledge: ({
amount
}: {
amount: Coin;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
unbondMixnode: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
unbondMixnode: (fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
trackUnbondMixnode: ({
amount,
owner
}: {
amount: Coin;
owner: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
trackDecreasePledge: ({
amount,
owner
}: {
amount: Coin;
owner: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
bondGateway: ({
amount,
gateway,
@@ -636,52 +611,59 @@ export interface VestingInterface extends VestingReadOnlyInterface {
amount: Coin;
gateway: Gateway;
ownerSignature: MessageSignature;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
unbondGateway: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
unbondGateway: (fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
trackUnbondGateway: ({
amount,
owner
}: {
amount: Coin;
owner: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
updateGatewayConfig: ({
newConfig
}: {
newConfig: GatewayConfigUpdate;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
transferOwnership: ({
toAddress
}: {
toAddress: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
updateStakingAddress: ({
toAddress
}: {
toAddress?: string;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
updateLockedPledgeCap: ({
address,
cap
}: {
address: string;
cap: PledgeCap;
}, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise<ExecuteResult>;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
trackMigratedMixnode: ({
owner
}: {
owner: string;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
trackMigratedDelegation: ({
mixId,
owner
}: {
mixId: number;
owner: string;
}, fee_?: number | StdFee | "auto", memo_?: string, funds_?: Coin[]) => Promise<any>;
}
export class VestingClient extends VestingQueryClient implements VestingInterface {
client: SigningCosmWasmClient;
client: ISigningCosmWasmClient;
sender: string;
contractAddress: string;
constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) {
constructor(client: ISigningCosmWasmClient, sender: string, contractAddress: string) {
super(client, contractAddress);
this.client = client;
this.sender = sender;
this.contractAddress = contractAddress;
this.createFamily = this.createFamily.bind(this);
this.joinFamily = this.joinFamily.bind(this);
this.leaveFamily = this.leaveFamily.bind(this);
this.kickFamilyMember = this.kickFamilyMember.bind(this);
this.trackReward = this.trackReward.bind(this);
this.claimOperatorReward = this.claimOperatorReward.bind(this);
this.claimDelegatorReward = this.claimDelegatorReward.bind(this);
@@ -706,117 +688,71 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
this.transferOwnership = this.transferOwnership.bind(this);
this.updateStakingAddress = this.updateStakingAddress.bind(this);
this.updateLockedPledgeCap = this.updateLockedPledgeCap.bind(this);
this.trackMigratedMixnode = this.trackMigratedMixnode.bind(this);
this.trackMigratedDelegation = this.trackMigratedDelegation.bind(this);
}
createFamily = async ({
label
}: {
label: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
return await this.client.execute(this.sender, this.contractAddress, {
create_family: {
label
}
}, fee, memo, _funds);
};
joinFamily = async ({
familyHead,
joinPermit
}: {
familyHead: FamilyHead;
joinPermit: MessageSignature;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
return await this.client.execute(this.sender, this.contractAddress, {
join_family: {
family_head: familyHead,
join_permit: joinPermit
}
}, fee, memo, _funds);
};
leaveFamily = async ({
familyHead
}: {
familyHead: FamilyHead;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
return await this.client.execute(this.sender, this.contractAddress, {
leave_family: {
family_head: familyHead
}
}, fee, memo, _funds);
};
kickFamilyMember = async ({
member
}: {
member: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
return await this.client.execute(this.sender, this.contractAddress, {
kick_family_member: {
member
}
}, fee, memo, _funds);
};
trackReward = async ({
address,
amount
}: {
address: string;
amount: Coin;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
track_reward: {
address,
amount
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
claimOperatorReward = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
claimOperatorReward = async (fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
claim_operator_reward: {}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
claimDelegatorReward = async ({
mixId
}: {
mixId: number;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
claim_delegator_reward: {
mix_id: mixId
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
updateMixnodeCostParams = async ({
newCosts
}: {
newCosts: MixNodeCostParams;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
newCosts: NodeCostParams;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
update_mixnode_cost_params: {
new_costs: newCosts
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
updateMixnodeConfig = async ({
newConfig
}: {
newConfig: MixNodeConfigUpdate;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
update_mixnode_config: {
new_config: newConfig
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
updateMixnetAddress = async ({
address
}: {
address: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
update_mixnet_address: {
address
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
delegateToMixnode = async ({
amount,
@@ -826,14 +762,14 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
amount: Coin;
mixId: number;
onBehalfOf?: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
delegate_to_mixnode: {
amount,
mix_id: mixId,
on_behalf_of: onBehalfOf
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
undelegateFromMixnode = async ({
mixId,
@@ -841,13 +777,13 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
}: {
mixId: number;
onBehalfOf?: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
undelegate_from_mixnode: {
mix_id: mixId,
on_behalf_of: onBehalfOf
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
createAccount = async ({
cap,
@@ -859,7 +795,7 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
ownerAddress: string;
stakingAddress?: string;
vestingSpec?: VestingSpecification;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
create_account: {
cap,
@@ -867,18 +803,18 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
staking_address: stakingAddress,
vesting_spec: vestingSpec
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
withdrawVestedCoins = async ({
amount
}: {
amount: Coin;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
withdraw_vested_coins: {
amount
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
trackUndelegation = async ({
amount,
@@ -888,14 +824,14 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
amount: Coin;
mixId: number;
owner: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
track_undelegation: {
amount,
mix_id: mixId,
owner
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
bondMixnode = async ({
amount,
@@ -904,10 +840,10 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
ownerSignature
}: {
amount: Coin;
costParams: MixNodeCostParams;
costParams: NodeCostParams;
mixNode: MixNode;
ownerSignature: MessageSignature;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
bond_mixnode: {
amount,
@@ -915,34 +851,34 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
mix_node: mixNode,
owner_signature: ownerSignature
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
pledgeMore = async ({
amount
}: {
amount: Coin;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
pledge_more: {
amount
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
decreasePledge = async ({
amount
}: {
amount: Coin;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
decrease_pledge: {
amount
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
unbondMixnode = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
unbondMixnode = async (fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
unbond_mixnode: {}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
trackUnbondMixnode = async ({
amount,
@@ -950,13 +886,13 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
}: {
amount: Coin;
owner: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
track_unbond_mixnode: {
amount,
owner
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
trackDecreasePledge = async ({
amount,
@@ -964,13 +900,13 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
}: {
amount: Coin;
owner: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
track_decrease_pledge: {
amount,
owner
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
bondGateway = async ({
amount,
@@ -980,19 +916,19 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
amount: Coin;
gateway: Gateway;
ownerSignature: MessageSignature;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
bond_gateway: {
amount,
gateway,
owner_signature: ownerSignature
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
unbondGateway = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
unbondGateway = async (fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
unbond_gateway: {}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
trackUnbondGateway = async ({
amount,
@@ -1000,46 +936,46 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
}: {
amount: Coin;
owner: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
track_unbond_gateway: {
amount,
owner
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
updateGatewayConfig = async ({
newConfig
}: {
newConfig: GatewayConfigUpdate;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
update_gateway_config: {
new_config: newConfig
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
transferOwnership = async ({
toAddress
}: {
toAddress: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
transfer_ownership: {
to_address: toAddress
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
updateStakingAddress = async ({
toAddress
}: {
toAddress?: string;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
update_staking_address: {
to_address: toAddress
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
updateLockedPledgeCap = async ({
address,
@@ -1047,12 +983,37 @@ export class VestingClient extends VestingQueryClient implements VestingInterfac
}: {
address: string;
cap: PledgeCap;
}, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise<ExecuteResult> => {
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
update_locked_pledge_cap: {
address,
cap
}
}, fee, memo, _funds);
}, fee_, memo_, funds_);
};
}
trackMigratedMixnode = async ({
owner
}: {
owner: string;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
track_migrated_mixnode: {
owner
}
}, fee_, memo_, funds_);
};
trackMigratedDelegation = async ({
mixId,
owner
}: {
mixId: number;
owner: string;
}, fee_: number | StdFee | "auto" = "auto", memo_?: string, funds_?: Coin[]): Promise<any> => {
return await this.client.execute(this.sender, this.contractAddress, {
track_migrated_delegation: {
mix_id: mixId,
owner
}
}, fee_, memo_, funds_);
};
}
@@ -1,5 +1,5 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3.
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
@@ -9,23 +9,6 @@ export interface InstantiateMsg {
mixnet_contract_address: string;
}
export type ExecuteMsg = {
create_family: {
label: string;
};
} | {
join_family: {
family_head: FamilyHead;
join_permit: MessageSignature;
};
} | {
leave_family: {
family_head: FamilyHead;
};
} | {
kick_family_member: {
member: string;
};
} | {
track_reward: {
address: string;
amount: Coin;
@@ -38,7 +21,7 @@ export type ExecuteMsg = {
};
} | {
update_mixnode_cost_params: {
new_costs: MixNodeCostParams;
new_costs: NodeCostParams;
};
} | {
update_mixnode_config: {
@@ -79,7 +62,7 @@ export type ExecuteMsg = {
} | {
bond_mixnode: {
amount: Coin;
cost_params: MixNodeCostParams;
cost_params: NodeCostParams;
mix_node: MixNode;
owner_signature: MessageSignature;
};
@@ -133,9 +116,16 @@ export type ExecuteMsg = {
address: string;
cap: PledgeCap;
};
} | {
track_migrated_mixnode: {
owner: string;
};
} | {
track_migrated_delegation: {
mix_id: number;
owner: string;
};
};
export type FamilyHead = string;
export type MessageSignature = number[];
export type Uint128 = string;
export type Percent = Decimal;
export type Decimal = string;
@@ -144,12 +134,12 @@ export type PledgeCap = {
} | {
absolute: Uint128;
};
export type MessageSignature = number[];
export interface Coin {
amount: Uint128;
denom: string;
[k: string]: unknown;
}
export interface MixNodeCostParams {
export interface NodeCostParams {
interval_operating_cost: Coin;
profit_margin_percent: Percent;
}
@@ -353,9 +343,12 @@ export interface ContractVersion {
export interface ContractBuildInformation {
build_timestamp: string;
build_version: string;
cargo_debug?: string;
cargo_opt_level?: string;
commit_branch: string;
commit_sha: string;
commit_timestamp: string;
contract_name?: string;
rustc_version: string;
}
export type Period = "before" | {
@@ -0,0 +1,200 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import { StdFee, Coin } from '@interchainjs/types';
import { DirectSigner } from '@interchainjs/cosmos';
import { getSmartContractState } from 'interchainjs/cosmwasm/wasm/v1/query.rpc.func';
import { executeContract } from 'interchainjs/cosmwasm/wasm/v1/tx.rpc.func';
import { QuerySmartContractStateRequest, QuerySmartContractStateResponse } from 'interchainjs/cosmwasm/wasm/v1/query';
import { MsgExecuteContract } from 'interchainjs/cosmwasm/wasm/v1/tx';
import { Chain } from '@chain-registry/v2-types';
// Encoding utility functions
const fromUint8Array = <T>(uint8Array: Uint8Array): T => {
const text = new TextDecoder().decode(uint8Array);
return JSON.parse(text);
};
const toUint8Array = (obj: any): Uint8Array => {
const text = JSON.stringify(obj);
return new TextEncoder().encode(text);
};
// Chain registry configuration
// The amount under gasPrice represents gas price per unit
export interface ChainConfig {
chain?: Chain;
gasPrice?: {
denom: string;
amount: string;
};
}
// Gas fee calculation utilities
export const calculateGasFromChain = (chain: Chain, gasAmount: string): StdFee => {
try {
const feeTokens = chain.fees?.feeTokens;
if (feeTokens && feeTokens.length > 0) {
const primaryToken = feeTokens[0];
// v2 chain-registry uses camelCase: averageGasPrice, lowGasPrice, fixedMinGasPrice
const gasPrice = primaryToken.averageGasPrice || primaryToken.lowGasPrice || primaryToken.fixedMinGasPrice || 0.025;
const gasAmountNum = parseInt(gasAmount);
const feeAmount = Math.ceil(gasAmountNum * gasPrice).toString();
return {
amount: [{
denom: primaryToken.denom,
amount: feeAmount
}],
gas: gasAmount
};
}
} catch (error) {
console.warn('Failed to calculate gas from chain registry:', error);
}
// Fallback to default
return { amount: [], gas: gasAmount };
};
// Default gas amount - users can easily change this
export let DEFAULT_GAS_AMOUNT = '200000';
// Allow users to set their preferred default gas amount
export const setDefaultGasAmount = (gasAmount: string): void => {
DEFAULT_GAS_AMOUNT = gasAmount;
};
// Get current default gas amount
export const getDefaultGasAmount = (): string => DEFAULT_GAS_AMOUNT;
export const getAutoGasFee = (chainConfig?: ChainConfig): StdFee => {
const gasAmount = DEFAULT_GAS_AMOUNT;
if (chainConfig?.chain) {
return calculateGasFromChain(chainConfig.chain, gasAmount);
}
if (chainConfig?.gasPrice) {
const gasAmountNum = parseInt(gasAmount);
const gasPriceNum = parseFloat(chainConfig.gasPrice.amount);
const feeAmount = Math.ceil(gasAmountNum * gasPriceNum).toString();
return {
amount: [{
denom: chainConfig.gasPrice.denom,
amount: feeAmount
}],
gas: gasAmount
};
}
// Fallback: no fee tokens, just gas amount
return { amount: [], gas: gasAmount };
};
// InterchainJS interfaces for CosmWasm clients
export interface ICosmWasmClient {
queryContractSmart(contractAddr: string, query: any): Promise<any>;
}
export interface ISigningCosmWasmClient extends ICosmWasmClient {
execute(
sender: string,
contractAddress: string,
msg: any,
fee?: number | StdFee | "auto",
memo?: string,
funds?: Coin[],
chainConfig?: ChainConfig
): Promise<any>;
}
export interface ISigningClient {
signAndBroadcast(
signerAddress: string,
messages: any[],
fee: number | StdFee | "auto",
memo?: string
): Promise<any>;
}
// Helper functions to create InterchainJS clients
export function getCosmWasmClient(rpcEndpoint: string): ICosmWasmClient {
return {
queryContractSmart: async (contractAddr: string, query: any) => {
// Create the request object
const request: QuerySmartContractStateRequest = {
address: contractAddr,
queryData: toUint8Array(query)
};
// Execute the query using InterchainJS
const response: QuerySmartContractStateResponse = await getSmartContractState(rpcEndpoint, request);
// Parse and return the result
return fromUint8Array(response.data);
},
};
}
export function getSigningCosmWasmClient(signingClient: DirectSigner, rpcEndpoint?: string): ISigningCosmWasmClient {
return {
queryContractSmart: async (contractAddr: string, query: any) => {
if (!rpcEndpoint) {
throw new Error('rpcEndpoint is required for queryContractSmart in signing client');
}
const request: QuerySmartContractStateRequest = {
address: contractAddr,
queryData: toUint8Array(query)
};
const response: QuerySmartContractStateResponse = await getSmartContractState(rpcEndpoint, request);
return fromUint8Array(response.data);
},
execute: async (
sender: string,
contractAddress: string,
msg: any,
fee?: number | StdFee | "auto",
memo?: string,
funds?: Coin[],
chainConfig?: ChainConfig
) => {
// Handle fee conversion
let finalFee: StdFee;
if (typeof fee === 'number') {
finalFee = { amount: [], gas: fee.toString() };
} else if (fee === 'auto') {
finalFee = getAutoGasFee(chainConfig);
} else if (fee) {
finalFee = fee;
} else {
finalFee = getAutoGasFee(chainConfig);
}
// Create the message object
const message: MsgExecuteContract = {
sender,
contract: contractAddress,
msg: toUint8Array(msg),
funds: funds || []
};
// Execute the transaction using InterchainJS
const result = await executeContract(
signingClient as any,
sender,
message,
finalFee,
memo || ''
);
return result;
},
};
}
@@ -1,35 +1,48 @@
/**
* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
* This file was automatically generated by @cosmwasm/ts-codegen@1.13.3.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
*/
import * as _0 from './CoconutBandwidth.types';
import * as _1 from './CoconutBandwidth.client';
import * as _2 from './CoconutDkg.types';
import * as _3 from './CoconutDkg.client';
import * as _4 from './Mixnet.types';
import * as _5 from './Mixnet.client';
import * as _6 from './Cw3FlexMultisig.types';
import * as _7 from './Cw3FlexMultisig.client';
import * as _8 from './Cw4Group.types';
import * as _9 from './Cw4Group.client';
import * as _10 from './NameService.types';
import * as _11 from './NameService.client';
import * as _12 from './ServiceProviderDirectory.types';
import * as _13 from './ServiceProviderDirectory.client';
import * as _14 from './Vesting.types';
import * as _15 from './Vesting.client';
export * from './types';
/** @namespace */
import * as _0 from "./Ecash.types";
import * as _1 from "./Ecash.client";
import * as _2 from "./CoconutDkg.types";
import * as _3 from "./CoconutDkg.client";
import * as _4 from "./Mixnet.types";
import * as _5 from "./Mixnet.client";
import * as _6 from "./Cw3FlexMultisig.types";
import * as _7 from "./Cw3FlexMultisig.client";
import * as _8 from "./Cw4Group.types";
import * as _9 from "./Cw4Group.client";
import * as _10 from "./Vesting.types";
import * as _11 from "./Vesting.client";
import * as _12 from "./baseClient";
export namespace contracts {
export const CoconutBandwidth = { ..._0, ..._1 };
export const CoconutDkg = { ..._2, ..._3 };
export const Mixnet = { ..._4, ..._5 };
export const Cw3FlexMultisig = { ..._6, ..._7 };
export const Cw4Group = { ..._8, ..._9 };
export const NameService = { ..._10, ..._11 };
export const ServiceProviderDirectory = { ..._12, ..._13 };
export const Vesting = { ..._14, ..._15 };
}
export const Ecash = {
..._0,
..._1
};
export const CoconutDkg = {
..._2,
..._3
};
export const Mixnet = {
..._4,
..._5
};
export const Cw3FlexMultisig = {
..._6,
..._7
};
export const Cw4Group = {
..._8,
..._9
};
export const Vesting = {
..._10,
..._11
};
export const baseClient = {
..._12
};
}
@@ -1,6 +1,6 @@
{
"name": "@nymproject/sdk-example-plain-html-parcel",
"version": "1.0.4-rc.2",
"version": "1.0.5",
"description": "An example project that uses WASM and plain HTML bundled with Parcel v2",
"license": "Apache-2.0",
"scripts": {
@@ -15,7 +15,7 @@
"tsc:watch": "tsc --watch"
},
"dependencies": {
"@nymproject/sdk": ">=1.2.2-rc.0 || ^1"
"@nymproject/sdk": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"@types/jest": "^27.0.1",
@@ -41,4 +41,4 @@
"private": false,
"browserslist": "> 0.5%, last 2 versions, not dead",
"source": "src/index.html"
}
}
@@ -1,6 +1,6 @@
{
"name": "@nymproject/sdk-example-plain-html",
"version": "1.0.4-rc.2",
"version": "1.0.5",
"description": "An example project that uses WASM and plain HTML",
"license": "Apache-2.0",
"scripts": {
@@ -16,7 +16,7 @@
"tsc:watch": "tsc --watch"
},
"dependencies": {
"@nymproject/sdk": ">=1.2.2-rc.0 || ^1"
"@nymproject/sdk": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"@babel/core": "^7.15.0",
@@ -62,4 +62,4 @@
"webpack-merge": "^5.8.0"
},
"private": false
}
}
@@ -1,6 +1,6 @@
{
"name": "@nymproject/sdk-example-react-webpack-wasm",
"version": "1.0.4-rc.2",
"version": "1.0.5",
"description": "An example project that uses WASM, React, Webpack, Typescript and the Nym theme + components library",
"license": "Apache-2.0",
"scripts": {
@@ -20,7 +20,7 @@
"@mui/lab": "^5.0.0-alpha.72",
"@mui/material": "^5.0.1",
"@mui/styles": "^5.0.1",
"@nymproject/sdk": ">=1.2.2-rc.0 || ^1",
"@nymproject/sdk": ">=1.4.1-rc1 || ^1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
@@ -90,4 +90,4 @@
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
}
@@ -1,6 +1,6 @@
{
"name": "@nymproject/sdk-example-chrome-extension",
"version": "1.0.4-rc.2",
"version": "1.0.5",
"description": "This is an example of how Nym can be used within the context of a Chrome extension.",
"license": "ISC",
"author": "",
@@ -9,7 +9,7 @@
"build": "webpack"
},
"dependencies": {
"@nymproject/sdk": ">=1.2.2-rc.0 || ^1"
"@nymproject/sdk": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"clean-webpack-plugin": "^4.0.0",
@@ -18,4 +18,4 @@
"webpack-cli": "^5.1.4"
},
"private": false
}
}
@@ -1,6 +1,6 @@
{
"name": "@nymproject/sdk-example-firefox-extension",
"version": "1.0.4-rc.2",
"version": "1.0.5",
"description": "This is an example of how Nym can be used within the context of a Firefox extension.",
"license": "ISC",
"author": "",
@@ -9,7 +9,7 @@
"build": "yarn webpack"
},
"dependencies": {
"@nymproject/sdk": ">=1.2.2-rc.0 || ^1"
"@nymproject/sdk": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"copy-webpack-plugin": "^11.0.0",
@@ -18,4 +18,4 @@
"worker-loader": "^3.0.8"
},
"private": false
}
}
@@ -1,6 +1,6 @@
{
"name": "@nymproject/mix-fetch-example-parcel",
"version": "1.0.4-rc.2",
"version": "1.0.5",
"license": "Apache-2.0",
"scripts": {
"build": "parcel build --no-cache --no-content-hash",
@@ -8,9 +8,9 @@
"start": "parcel --no-cache"
},
"dependencies": {
"@nymproject/mix-fetch": ">=1.2.2-rc.0 || ^1",
"@nymproject/mix-fetch": ">=1.4.1-rc1 || ^1",
"parcel": "^2.9.3"
},
"private": false,
"source": "src/index.html"
}
}
@@ -1,6 +1,6 @@
{
"name": "@nymproject/sdk-example-node-tester-plain-html-parcel",
"version": "1.0.4-rc.2",
"version": "1.0.5",
"description": "An example project that uses WASM and plain HTML bundled with Parcel v2",
"license": "Apache-2.0",
"scripts": {
@@ -15,7 +15,7 @@
"tsc:watch": "tsc --watch"
},
"dependencies": {
"@nymproject/sdk": ">=1.2.2-rc.0 || ^1"
"@nymproject/sdk": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"@types/jest": "^27.0.1",
@@ -41,4 +41,4 @@
"private": false,
"browserslist": "> 0.5%, last 2 versions, not dead",
"source": "src/index.html"
}
}
@@ -1,6 +1,6 @@
{
"name": "@nymproject/sdk-example-node-tester-plain-html",
"version": "1.0.4-rc.2",
"version": "1.0.5",
"description": "An example project that uses WASM node tester and plain HTML",
"license": "Apache-2.0",
"scripts": {
@@ -16,7 +16,7 @@
"tsc:watch": "tsc --watch"
},
"dependencies": {
"@nymproject/sdk": ">=1.2.2-rc.0 || ^1"
"@nymproject/sdk": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"@babel/core": "^7.15.0",
@@ -62,4 +62,4 @@
"webpack-merge": "^5.8.0"
},
"private": false
}
}
@@ -1,6 +1,6 @@
{
"name": "@nymproject/sdk-example-node-tester-react",
"version": "1.0.4-rc.2",
"version": "1.0.5",
"description": "An example project that uses WASM node tester and React",
"license": "Apache-2.0",
"scripts": {
@@ -11,10 +11,10 @@
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.14.0",
"@mui/material": "^5.14.0",
"@nymproject/sdk": ">=1.2.2-rc.0 || ^1",
"@nymproject/sdk": ">=1.4.1-rc1 || ^1",
"parcel": "^2.9.3",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"private": false
}
}
@@ -1,6 +1,6 @@
{
"name": "@nymproject/mix-fetch-node",
"version": "1.4.0-rc.0",
"version": "1.4.1-rc0",
"description": "This package is a drop-in replacement for `fetch` in NodeJS to send HTTP requests over the Nym Mixnet.",
"license": "Apache-2.0",
"author": "Nym Technologies SA",
@@ -28,7 +28,7 @@
"tsc": "tsc --noEmit true"
},
"dependencies": {
"@nymproject/mix-fetch-wasm-node": ">=1.2.4-rc.2 || ^1",
"@nymproject/mix-fetch-wasm-node": ">=1.2.5-rc.0 || ^1",
"comlink": "^4.3.1",
"fake-indexeddb": "^5.0.0",
"node-fetch": "^3.3.2",
@@ -1,6 +1,6 @@
{
"name": "@nymproject/mix-fetch-tester-webpack",
"version": "1.0.4-rc.2",
"version": "1.0.5",
"license": "Apache-2.0",
"scripts": {
"build": "webpack build --progress --config webpack.prod.js",
@@ -8,7 +8,7 @@
"start": "webpack serve --progress --port 3000"
},
"dependencies": {
"@nymproject/mix-fetch": ">=1.2.2-rc.0 || ^1"
"@nymproject/mix-fetch": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"@babel/core": "^7.22.10",
@@ -55,4 +55,4 @@
"webpack-merge": "^5.9.0"
},
"private": false
}
}
@@ -1,6 +1,6 @@
{
"name": "@nymproject/mix-fetch-tester-parcel",
"version": "1.0.4-rc.2",
"version": "1.0.5",
"license": "Apache-2.0",
"scripts": {
"build": "npx parcel build --no-cache --no-content-hash",
@@ -8,8 +8,8 @@
"start": "npx parcel --no-cache"
},
"dependencies": {
"@nymproject/mix-fetch": ">=1.2.2-rc.0 || ^1"
"@nymproject/mix-fetch": ">=1.4.1-rc1 || ^1"
},
"private": false,
"source": "../src/index.html"
}
}
@@ -21,6 +21,7 @@ async function main() {
// const addr =
// 'EVdJ66jqpoVzmktVecy5UJxsTCEWo5gMn5zDZR7Hm8jy.GXNpoX7RcYcxKvBkV3dSHqC78WaPuWieweRPWzYqNhh5@GAjhJcrd6f1edaqUkfWCff6zdHoqo756qYrc2TfPuCXJ';
// const addr = '7Y9eyF1p1JmzHnd7TVZufnQHkh93ASc9sRBCFY57ZGr8.F8KPyVMVqFQ5yJC3LqeP2ZC7fukzj9a1T426rjo432yT@q2A2cbooyC16YJzvdYaSMH9X3cSiieZNtfBr8cE8Fi1';
const addr = undefined;
appendOutput('About to set up mixFetch...');
@@ -54,12 +55,12 @@ async function main() {
appendOutput(JSON.stringify(resp, null, 2));
appendOutput(JSON.stringify({ text }, null, 2));
console.log('disconnecting');
await disconnectMixFetch();
console.log('disconnected! all further usages should fail');
// console.log('disconnecting');
// await disconnectMixFetch();
// console.log('disconnected! all further usages should fail');
// get an image
url = 'https://nymtech.net/favicon.svg';
url = 'https://matrix.org/assets/frontpage/github-mark.svg';
resp = await mixFetch(url, args);
console.log({ resp });
const buffer = await resp.arrayBuffer();
@@ -35,7 +35,8 @@ module.exports = mergeWithRules({
{
// copy the WASM files, because webpack doesn't do this automatically even though there are
// `new URL(..., import.meta.url)` statements in the web worker
from: path.resolve(path.dirname(require.resolve('@nymproject/mix-fetch/package.json')), 'dist/esm/*.wasm'),
// from: path.resolve(path.dirname(require.resolve('@nymproject/mix-fetch/package.json')), 'dist/esm/*.wasm'),
from: path.resolve(path.dirname(require.resolve('@nymproject/mix-fetch/package.json')), '*.wasm'),
to: '[name][ext]',
},
],
@@ -1,7 +1,5 @@
const { mergeWithRules } = require('webpack-merge');
const webpack = require('webpack');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const ReactRefreshTypeScript = require('react-refresh-typescript');
const commonConfig = require('./webpack.common');
module.exports = mergeWithRules({
@@ -22,7 +20,7 @@ module.exports = mergeWithRules({
exclude: /node_modules/,
options: {
getCustomTransformers: () => ({
before: [ReactRefreshTypeScript()],
before: [],
}),
// `ts-loader` does not work with HMR unless `transpileOnly` is used.
// If you need type checking, `ForkTsCheckerWebpackPlugin` is an alternative.
@@ -36,8 +34,6 @@ module.exports = mergeWithRules({
],
},
plugins: [
new ReactRefreshWebpackPlugin(),
// this can be included automatically by the dev server, however build mode fails if missing
new webpack.HotModuleReplacementPlugin(),
],
@@ -1,6 +1,6 @@
{
"name": "@nymproject/mix-fetch",
"version": "1.4.0-rc.0",
"version": "1.4.1-rc2",
"description": "This package is a drop-in replacement for `fetch` to send HTTP requests over the Nym Mixnet.",
"license": "Apache-2.0",
"author": "Nym Technologies SA",
@@ -34,7 +34,7 @@
"tsc": "tsc --noEmit true"
},
"dependencies": {
"@nymproject/mix-fetch-wasm": ">=1.2.4-rc.2 || ^1",
"@nymproject/mix-fetch-wasm": "1.4.1-rc2",
"comlink": "^4.3.1"
},
"devDependencies": {
@@ -1,6 +1,6 @@
{
"name": "@nymproject/node-tester",
"version": "1.3.0-rc.0",
"version": "1.3.1",
"description": "This package provides a tester that can send test packets to mixnode that is part of the Nym Mixnet.",
"license": "Apache-2.0",
"author": "Nym Technologies SA",
@@ -25,7 +25,7 @@
"tsc": "tsc --noEmit true"
},
"dependencies": {
"@nymproject/nym-node-tester-wasm": ">=1.2.4-rc.2 || ^1",
"@nymproject/nym-node-tester-wasm": ">=1.2.5-rc.0 || ^1",
"comlink": "^4.3.1"
},
"devDependencies": {
@@ -71,4 +71,4 @@
"private": false,
"type": "module",
"types": "./dist/esm/index.d.ts"
}
}
@@ -1,6 +1,6 @@
{
"name": "@nymproject/nodejs-client",
"version": "1.4.0-rc.0",
"version": "1.4.1-rc0",
"license": "Apache-2.0",
"author": "Nym Technologies SA",
"files": [
@@ -25,7 +25,7 @@
"tsc": "tsc --noEmit true"
},
"dependencies": {
"@nymproject/nym-client-wasm-node": ">=1.2.4-rc.2 || ^1",
"@nymproject/nym-client-wasm-node": ">=1.2.5-rc.0 || ^1",
"comlink": "^4.3.1",
"fake-indexeddb": "^4.0.2",
"rollup-plugin-polyfill": "^4.2.0",
@@ -1,6 +1,6 @@
{
"name": "@nymproject/sdk-react",
"version": "1.4.0-rc.0",
"version": "1.4.1",
"license": "Apache-2.0",
"author": "Nym Technologies SA",
"files": [
@@ -20,7 +20,7 @@
"tsc": "tsc --noEmit true"
},
"dependencies": {
"@nymproject/sdk": ">=1.2.2-rc.0 || ^1"
"@nymproject/sdk": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"@babel/core": "^7.17.5",
@@ -67,4 +67,4 @@
"private": false,
"type": "module",
"types": "./dist/index.d.ts"
}
}
+9 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@nymproject/sdk",
"version": "1.4.0-rc.0",
"version": "1.4.1-rc2",
"license": "Apache-2.0",
"author": "Nym Technologies SA",
"files": [
@@ -30,11 +30,8 @@
"test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache",
"tsc": "tsc --noEmit true"
},
"typeRoots": [
"./node_modules/@types/*"
],
"dependencies": {
"@nymproject/nym-client-wasm": ">=1.2.4-rc.2 || ^1",
"@nymproject/nym-client-wasm": "1.4.1-rc2",
"comlink": "^4.3.1"
},
"devDependencies": {
@@ -54,6 +51,7 @@
"@rollup/plugin-url": "^8.0.1",
"@rollup/plugin-wasm": "^6.1.1",
"@types/jest": "^27.0.1",
"@types/minimatch": "5.1.2",
"@types/node": "^16.7.13",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
@@ -81,7 +79,13 @@
"typedoc": "^0.24.8",
"typescript": "^4.8.4"
},
"resolutions": {
"@types/minimatch": "5.1.2"
},
"private": false,
"type": "module",
"typeRoots": [
"./node_modules/@types/*"
],
"types": "./dist/esm/index.d.ts"
}
@@ -79,7 +79,7 @@ class ClientWrapper {
return undefined;
}
return this.client.self_address();
return this.client.selfAddress();
};
/**
+1 -1
View File
@@ -21,7 +21,7 @@ yarn
yarn build:ci:sdk
# build documentation
yarn docs:prod:build
#yarn docs:prod:build
# turn dev mode off
yarn dev:off
+6 -1
View File
@@ -2,7 +2,12 @@ import fs from 'fs';
const packageJson = JSON.parse(fs.readFileSync('package.json').toString());
const devWorkspace = ['sdk/typescript/packages/**', 'sdk/typescript/examples/**', 'sdk/typescript/codegen/**'];
const devWorkspace = [
'dist/**',
'sdk/typescript/packages/**',
'sdk/typescript/examples/**',
'sdk/typescript/codegen/**',
];
if (!packageJson.workspaces.includes(devWorkspace)) {
// add
packageJson.workspaces.push(...devWorkspace);
+6 -1
View File
@@ -2,7 +2,12 @@ import fs from 'fs';
const packageJson = JSON.parse(fs.readFileSync('package.json').toString());
const devWorkspace = ['sdk/typescript/packages/**', 'sdk/typescript/examples/**', 'sdk/typescript/codegen/**'];
const devWorkspace = [
'dist/**',
'sdk/typescript/packages/**',
'sdk/typescript/examples/**',
'sdk/typescript/codegen/**',
];
// remove
packageJson.workspaces = packageJson.workspaces.filter((w) => !devWorkspace.includes(w));
+14 -14
View File
@@ -23,33 +23,33 @@ cd dist
#react/sdk-react
#)
packages=(
"wasm/client"
"wasm/mix-fetch"
"wasm/node-tester"
"wasm/extension-storage"
#"wasm/client"
#"wasm/mix-fetch"
#"wasm/node-tester"
##"wasm/extension-storage"
"node/wasm/client"
"node/wasm/mix-fetch"
#"node/wasm/client"
##"node/wasm/mix-fetch"
"ts/sdk/mix-fetch/cjs"
"ts/sdk/mix-fetch/cjs-full-fat"
"ts/sdk/mix-fetch/esm"
"ts/sdk/mix-fetch/esm-full-fat"
"ts/sdk/nodejs-client/cjs"
"ts/sdk/mix-fetch-node/cjs"
#"ts/sdk/nodejs-client/cjs"
#"ts/sdk/mix-fetch-node/cjs"
"ts/sdk/node-tester/cjs"
"ts/sdk/node-tester/cjs-full-fat"
"ts/sdk/node-tester/esm"
"ts/sdk/node-tester/esm-full-fat"
#"ts/sdk/node-tester/cjs"
#"ts/sdk/node-tester/cjs-full-fat"
#"ts/sdk/node-tester/esm"
#"ts/sdk/node-tester/esm-full-fat"
"ts/sdk/sdk/cjs"
"ts/sdk/sdk/cjs-full-fat"
"ts/sdk/sdk/esm"
"ts/sdk/sdk/esm-full-fat"
"ts/sdk/contract-clients"
#"ts/sdk/contract-clients"
)
pushd () {
@@ -66,7 +66,7 @@ for item in "${packages[@]}"
do
pushd "$item"
jq -r '. | "📦 " + .version + " " +.name' < package.json
popd
popd
done
echo ""
+4 -2
View File
@@ -226,7 +226,8 @@ mod tests {
error!("{err}");
// this is not an ideal way of checking it, but if test fails due to networking failures
// it should be fine to progress
if err.to_string().contains("nym api request failed") {
let err_str = err.to_string();
if err_str.contains("nym api") || err_str.contains("failed to connect") {
return Ok(());
}
return Err(err);
@@ -291,7 +292,8 @@ mod tests {
error!("{err}");
// this is not an ideal way of checking it, but if test fails due to networking failures
// it should be fine to progress
if err.to_string().contains("nym api request failed") {
let err_str = err.to_string();
if err_str.contains("nym api") || err_str.contains("failed to connect") {
return Ok(());
}
return Err(err);
+13 -5
View File
@@ -1,7 +1,7 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use anyhow::{bail, Context};
use anyhow::{Context, bail};
use semver::{Prerelease, Version};
use std::collections::HashSet;
use std::path::Path;
@@ -72,7 +72,9 @@ pub(crate) fn try_bump_raw_prerelease(raw: &str) -> anyhow::Result<Prerelease> {
impl VersionBumpExt for Version {
fn try_bump_prerelease(&self) -> anyhow::Result<Self> {
if self.pre.is_empty() {
bail!("the current version ({self}) does not have pre-release data set - are you sure you followed the release process correctly?")
bail!(
"the current version ({self}) does not have pre-release data set - are you sure you followed the release process correctly?"
)
}
Ok(Version {
@@ -86,7 +88,9 @@ impl VersionBumpExt for Version {
fn try_bump_patch_without_pre(&self) -> anyhow::Result<Self> {
if !self.pre.is_empty() {
bail!("the current version ({self}) has pre-release data set - are you sure you followed the release process correctly?")
bail!(
"the current version ({self}) has pre-release data set - are you sure you followed the release process correctly?"
)
}
let mut updated = self.clone();
@@ -96,7 +100,9 @@ impl VersionBumpExt for Version {
fn set_initial_release_candidate(&self) -> anyhow::Result<Self> {
if !self.pre.is_empty() {
bail!("the current version ({self}) has pre-release data set - are you sure you followed the release process correctly?")
bail!(
"the current version ({self}) has pre-release data set - are you sure you followed the release process correctly?"
)
}
Ok(Version {
major: self.major,
@@ -109,7 +115,9 @@ impl VersionBumpExt for Version {
fn try_remove_prerelease(&self) -> anyhow::Result<Self> {
if self.pre.is_empty() {
bail!("the current version ({self}) does not have pre-release data set - are you sure you followed the release process correctly?")
bail!(
"the current version ({self}) does not have pre-release data set - are you sure you followed the release process correctly?"
)
}
Ok(Version {
major: self.major,
+2 -2
View File
@@ -3,8 +3,8 @@
use crate::helpers::try_bump_raw_prerelease;
use crate::json_types::DepsSet;
use crate::{json_types, ReleasePackage};
use anyhow::{bail, Context};
use crate::{ReleasePackage, json_types};
use anyhow::{Context, bail};
use semver::{Comparator, Prerelease, Version, VersionReq};
use std::collections::HashSet;
use std::path::{Path, PathBuf};
+1 -1
View File
@@ -4,7 +4,7 @@ authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jedrzej Stuczynski <andrew@nymtech.net>",
]
version = "1.4.0-rc.0"
version = "1.4.1-rc2"
edition = "2021"
keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"]
license = "Apache-2.0"
+2 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "mix-fetch-wasm"
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
version = "1.4.0-rc.0"
version = "1.4.1-rc2"
edition = "2021"
keywords = ["nym", "fetch", "wasm", "webassembly", "privacy"]
license = "Apache-2.0"
@@ -32,6 +32,7 @@ nym-http-api-client = { path = "../../common/http-api-client" }
nym-socks5-requests = { path = "../../common/socks5/requests" }
nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" }
nym-service-providers-common = { path = "../../service-providers/common" }
nym-validator-client = { path = "../../common/client-libs/validator-client", default-features = false }
wasm-client-core = { path = "../../common/wasm/client-core" }
wasm-utils = { path = "../../common/wasm/utils" }
+3 -5
View File
@@ -1,9 +1,7 @@
module go-mix-conn
go 1.23.0
go 1.24.0
toolchain go1.23.3
require golang.org/x/net v0.46.0
require golang.org/x/net v0.38.0
require golang.org/x/text v0.23.0 // indirect
require golang.org/x/text v0.30.0 // indirect
+4
View File
@@ -1,4 +1,8 @@
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
+3 -3
View File
@@ -1,10 +1,10 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::harbourmaster::HarbourMasterApiError;
use crate::RequestId;
use nym_ordered_buffer::OrderedMessageError;
use nym_socks5_requests::ConnectionError;
use nym_validator_client::nym_api::error::NymAPIError;
use thiserror::Error;
use wasm_client_core::error::WasmCoreError;
use wasm_client_core::ClientCoreError;
@@ -22,9 +22,9 @@ pub enum MixFetchError {
NoNetworkRequesters,
#[error("could not query for the service providers: {source}")]
HarbourmasterError {
ValidatorClientError {
#[from]
source: HarbourMasterApiError,
source: NymAPIError,
},
#[error("failed to parse mix fetch config options: {source}")]
+6 -4
View File
@@ -94,10 +94,12 @@ pub fn setup_mix_fetch(opts: MixFetchOpts) -> Promise {
}
future_to_promise(async move {
let network_requester_address =
get_network_requester(opts.base.preferred_network_requester.clone())
.await
.map_promise_err()?;
let network_requester_address = get_network_requester(
opts.nym_api_url.clone(),
opts.base.preferred_network_requester.clone(),
)
.await
.map_promise_err()?;
console_log!("going to use {network_requester_address} network requester");
-59
View File
@@ -1,59 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// this exists inside mix-fetch rather than being made into repo-wide library since it's a temporary solution
// until the API is finalised and endpoints are moved to nym-api
use async_trait::async_trait;
use nym_http_api_client::{ApiClient, HttpClientError, NO_PARAMS};
use serde::Deserialize;
pub use nym_http_api_client::Client;
pub type HarbourMasterApiError = HttpClientError;
mod routes {
pub const API_VERSION: &str = "v1";
pub const SERVICES: &str = "services";
pub const NEW: &str = "new";
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait HarbourMasterApiClientExt: ApiClient {
// since it's a temporary thing don't worry about paging.
async fn get_services_new(&self) -> Result<PagedResult<ServiceNew>, HarbourMasterApiError> {
self.get_json(
&[routes::API_VERSION, routes::SERVICES, routes::NEW],
NO_PARAMS,
)
.await
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl HarbourMasterApiClientExt for Client {}
// https://gitlab.nymte.ch/nym/shipyard-test-and-earn/-/blob/main/harbour-master/src/http/mod.rs#L13
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct PagedResult<T> {
pub page: u32,
pub size: u32,
pub total: i32,
pub items: Vec<T>,
}
// https://gitlab.nymte.ch/nym/shipyard-test-and-earn/-/blob/main/harbour-master/src/http/services.rs#L32
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct ServiceNew {
pub service_provider_client_id: String,
pub ip_address: String,
pub last_successful_ping_utc: String,
pub last_updated_utc: String,
pub routing_score: f32,
}
+21 -9
View File
@@ -2,36 +2,48 @@
// SPDX-License-Identifier: Apache-2.0
use crate::error::MixFetchError;
use crate::harbourmaster;
use crate::harbourmaster::HarbourMasterApiClientExt;
use crate::error::MixFetchError::NoNetworkRequesters;
use nym_http_api_client::Client;
use nym_validator_client::nym_api::NymApiClientExt;
use rand::seq::SliceRandom;
use rand::thread_rng;
use wasm_utils::console_log;
// since this client is temporary (and will be properly integrated into nym-api eventually),
// we're using hardcoded URL for mainnet
const HARBOUR_MASTER: &str = "https://harbourmaster.nymtech.net";
const NYM_API_URL: &str = "https://validator.nymtech.net/api/";
pub(crate) async fn get_network_requester(
nym_api_url: Option<String>,
preferred: Option<String>,
) -> Result<String, MixFetchError> {
if let Some(sp) = preferred {
return Ok(sp);
}
let client = harbourmaster::Client::new_url(HARBOUR_MASTER, None)?;
let providers = client.get_services_new().await?;
let client = Client::new(
url::Url::parse(&nym_api_url.unwrap_or(NYM_API_URL.to_string()))?,
None,
);
let nodes = client.get_all_described_nodes().await?;
let providers: Vec<_> = nodes
.iter()
.filter_map(|node| {
node.description
.network_requester
.clone()
.map(|n| n.address)
})
.collect();
console_log!(
"obtained list of {} service providers on the network",
providers.items.len()
providers.len()
);
// this will only return a `None` if the list is empty
let mut rng = thread_rng();
providers
.items
.choose(&mut rng)
.map(|service| &service.service_provider_client_id)
.ok_or(NoNetworkRequesters)
.cloned()
.ok_or(MixFetchError::NoNetworkRequesters)
}
-2
View File
@@ -14,8 +14,6 @@ mod fetch;
#[cfg(target_arch = "wasm32")]
mod go_bridge;
#[cfg(target_arch = "wasm32")]
mod harbourmaster;
#[cfg(target_arch = "wasm32")]
mod helpers;
#[cfg(target_arch = "wasm32")]
mod request_writer;
+1 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "nym-node-tester-wasm"
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
version = "1.3.0-rc.0"
version = "1.3.1-rc0"
edition = "2021"
keywords = ["nym", "sphinx", "webassembly", "privacy", "tester"]
license = "Apache-2.0"
+2495 -2536
View File
File diff suppressed because it is too large Load Diff