Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ac12455f97 | |||
| 1c6db86259 | |||
| e126c1f7f1 | |||
| 31772019cd | |||
| 5369e5eab9 | |||
| 2e634c59a7 | |||
| d7383d74f3 | |||
| e98d60d7ce | |||
| f47650d6c8 |
@@ -27,7 +27,8 @@ jobs:
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
# pinned due to issues building contracts
|
||||
toolchain: 1.86.0
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
toolchain: 1.86.0
|
||||
override: true
|
||||
|
||||
- name: Build all binaries
|
||||
|
||||
@@ -4,6 +4,58 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2025.10-brie] (2025-05-27)
|
||||
|
||||
- Backport PR 5779 ([#5801])
|
||||
- Expanded Accept Encoding for `reqwest` ([#5779])
|
||||
- Teach HttpClientError how to report its status code and timeout ([#5770])
|
||||
- Skip refreshing the topology on startup as we already have an initial set ([#5768])
|
||||
- Fetch the topology from the nym-api concurrently ([#5767])
|
||||
- feat: use bincode by default in NymApiClient + remove feature-lock ([#5761])
|
||||
- Instrument create_request ([#5760])
|
||||
- Add node_bonded field to delegations ([#5759])
|
||||
- build(deps): bump mikefarah/yq from 4.45.1 to 4.45.4 ([#5758])
|
||||
- Raw route submissions ([#5756])
|
||||
- feat: expires header for `/active` nym-api responses ([#5755])
|
||||
- Decrease default average packet delay to 15 ms ([#5754])
|
||||
- build(deps): bump the patch-updates group across 1 directory with 12 updates ([#5753])
|
||||
- Remove pretty_env_logger and switch remaining crates to use tracing ([#5749])
|
||||
- Update pretty_env_logger to latest to not depend on unmaintained crate atty ([#5748])
|
||||
- Upgrade prometheus crate to fix security warning ([#5747])
|
||||
- Downgrade deranged crate to 0.4.0 ([#5746])
|
||||
- feat: nym-api bincode + yaml support ([#5745])
|
||||
- fix parallel feature in ecash crate with send + sync ([#5744])
|
||||
- Remove old test directory - Update validator docker ([#5743])
|
||||
- [Feature] `RememberMe` is the new don't `ForgetMe` ([#5742])
|
||||
- build(deps): bump ammonia from 4.0.0 to 4.1.0 ([#5739])
|
||||
- build(deps): bump base-x from 3.0.9 to 3.0.11 in /testnet-faucet ([#5737])
|
||||
- build(deps): bump http-proxy-middleware from 2.0.8 to 2.0.9 ([#5730])
|
||||
|
||||
[#5801]: https://github.com/nymtech/nym/pull/5801
|
||||
[#5779]: https://github.com/nymtech/nym/pull/5779
|
||||
[#5770]: https://github.com/nymtech/nym/pull/5770
|
||||
[#5768]: https://github.com/nymtech/nym/pull/5768
|
||||
[#5767]: https://github.com/nymtech/nym/pull/5767
|
||||
[#5761]: https://github.com/nymtech/nym/pull/5761
|
||||
[#5760]: https://github.com/nymtech/nym/pull/5760
|
||||
[#5759]: https://github.com/nymtech/nym/pull/5759
|
||||
[#5758]: https://github.com/nymtech/nym/pull/5758
|
||||
[#5756]: https://github.com/nymtech/nym/pull/5756
|
||||
[#5755]: https://github.com/nymtech/nym/pull/5755
|
||||
[#5754]: https://github.com/nymtech/nym/pull/5754
|
||||
[#5753]: https://github.com/nymtech/nym/pull/5753
|
||||
[#5749]: https://github.com/nymtech/nym/pull/5749
|
||||
[#5748]: https://github.com/nymtech/nym/pull/5748
|
||||
[#5747]: https://github.com/nymtech/nym/pull/5747
|
||||
[#5746]: https://github.com/nymtech/nym/pull/5746
|
||||
[#5745]: https://github.com/nymtech/nym/pull/5745
|
||||
[#5744]: https://github.com/nymtech/nym/pull/5744
|
||||
[#5743]: https://github.com/nymtech/nym/pull/5743
|
||||
[#5742]: https://github.com/nymtech/nym/pull/5742
|
||||
[#5739]: https://github.com/nymtech/nym/pull/5739
|
||||
[#5737]: https://github.com/nymtech/nym/pull/5737
|
||||
[#5730]: https://github.com/nymtech/nym/pull/5730
|
||||
|
||||
## [2025.9-appenzeller] (2025-05-13)
|
||||
|
||||
- build(deps): bump clap from 4.5.36 to 4.5.37 in the patch-updates group ([#5722])
|
||||
|
||||
Generated
+7
-7
@@ -4782,7 +4782,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "nym-api"
|
||||
version = "1.1.57"
|
||||
version = "1.1.59"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -5036,7 +5036,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-cli"
|
||||
version = "1.1.55"
|
||||
version = "1.1.56"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.22.1",
|
||||
@@ -5118,7 +5118,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-client"
|
||||
version = "1.1.55"
|
||||
version = "1.1.56"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"clap",
|
||||
@@ -6122,7 +6122,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-requester"
|
||||
version = "1.1.56"
|
||||
version = "1.1.57"
|
||||
dependencies = [
|
||||
"addr",
|
||||
"anyhow",
|
||||
@@ -6172,7 +6172,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-node"
|
||||
version = "1.11.0"
|
||||
version = "1.12.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
@@ -6568,7 +6568,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.55"
|
||||
version = "1.1.56"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"clap",
|
||||
@@ -7173,7 +7173,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nymvisor"
|
||||
version = "0.1.20"
|
||||
version = "0.1.21"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.55"
|
||||
version = "1.1.56"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.55"
|
||||
version = "1.1.56"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
|
||||
@@ -13,7 +13,7 @@ license.workspace = true
|
||||
[dependencies]
|
||||
async-trait = { workspace = true }
|
||||
bincode = { workspace = true }
|
||||
reqwest = { workspace = true, features = ["json", "gzip"] }
|
||||
reqwest = { workspace = true, features = ["json", "gzip", "deflate", "brotli", "zstd"] }
|
||||
http.workspace = true
|
||||
url = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
|
||||
@@ -288,14 +288,18 @@ impl ClientBuilder {
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let reqwest_client_builder = {
|
||||
let r = reqwest::ClientBuilder::new();
|
||||
|
||||
// Note this is extra as the `gzip` feature for `reqwest` crate should be enabled which
|
||||
// `"Enable[s] auto gzip decompression by checking the Content-Encoding response header."`
|
||||
// Note: I believe the manual enable calls for the compression methods are extra
|
||||
// as the various compression features for `reqwest` crate should be enabled
|
||||
// just by including the feature which:
|
||||
// `"Enable[s] auto decompression by checking the Content-Encoding response header."`
|
||||
//
|
||||
// I am going to leave it here anyways so that gzip decompression is attempted even if
|
||||
// that feature is removed.
|
||||
r.gzip(true)
|
||||
// I am going to leave these here anyways so that removing a decompression method
|
||||
// from the features list will throw an error if it is not also removed here.
|
||||
reqwest::ClientBuilder::new()
|
||||
.gzip(true)
|
||||
.deflate(true)
|
||||
.brotli(true)
|
||||
.zstd(true)
|
||||
};
|
||||
|
||||
ClientBuilder {
|
||||
@@ -559,11 +563,6 @@ impl ApiClientCore for Client {
|
||||
|
||||
let mut request = self.reqwest_client.request(method.clone(), url);
|
||||
|
||||
// Indicate that compressed responses are preferred, but if not supported other encodings are fine.
|
||||
// TODO: Down the road we can be more selective about adding this, but it's inclusion here guarantees
|
||||
// that we use compression when available.
|
||||
request = request.header(reqwest::header::ACCEPT_ENCODING, "gzip;q=1.0, *;q=0.5");
|
||||
|
||||
if let Some(body) = json_body {
|
||||
request = request.json(body);
|
||||
}
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
[package]
|
||||
name = "nym-api"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.57"
|
||||
version = "1.1.59"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
rust-version.workspace = true
|
||||
|
||||
@@ -108,13 +108,13 @@ impl AddressInfoCache {
|
||||
address: account_id.to_string(),
|
||||
balance: balance.into(),
|
||||
delegations: delegation_data
|
||||
.delegations()
|
||||
.into_iter()
|
||||
.map(|d| NyxAccountDelegationDetails {
|
||||
delegated: d.amount,
|
||||
height: d.height,
|
||||
node_id: d.node_id,
|
||||
proxy: d.proxy,
|
||||
delegated: d.details().amount.clone(),
|
||||
height: d.details().height,
|
||||
node_id: d.details().node_id,
|
||||
proxy: d.details().proxy.clone(),
|
||||
node_bonded: d.is_node_bonded(),
|
||||
})
|
||||
.collect(),
|
||||
accumulated_rewards,
|
||||
|
||||
@@ -8,10 +8,9 @@ use crate::{
|
||||
};
|
||||
use cosmwasm_std::{Coin, Decimal};
|
||||
use nym_mixnet_contract_common::NodeRewarding;
|
||||
use nym_topology::NodeId;
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use tracing::warn;
|
||||
use tracing::error;
|
||||
|
||||
pub(crate) struct AddressDataCollector {
|
||||
nyxd_client: crate::nyxd::Client,
|
||||
@@ -56,18 +55,18 @@ impl AddressDataCollector {
|
||||
Ok(balance)
|
||||
}
|
||||
|
||||
pub(crate) async fn get_delegations(&mut self) -> AxumResult<AddressDelegationInfo> {
|
||||
pub(crate) async fn get_delegations(&mut self) -> AxumResult<Vec<AddressDelegationInfo>> {
|
||||
let og_delegations = self
|
||||
.nyxd_client
|
||||
.get_all_delegator_delegations(&self.account_id)
|
||||
.await?;
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|delegation| (delegation.node_id, delegation))
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
let delegated_to_nodes = og_delegations
|
||||
.iter()
|
||||
.map(|d| d.node_id)
|
||||
.collect::<HashSet<_>>();
|
||||
let mut node_delegation_info = Vec::new();
|
||||
|
||||
let nym_nodes = self
|
||||
let delegated_to_nodes_bonded = self
|
||||
.nym_contract_cache
|
||||
.all_cached_nym_nodes()
|
||||
.await
|
||||
@@ -85,61 +84,75 @@ impl AddressDataCollector {
|
||||
// add to totals
|
||||
self.total_value += pending_operator_reward;
|
||||
}
|
||||
if delegated_to_nodes.contains(&node_details.node_id()) {
|
||||
Some((
|
||||
node_details.node_id(),
|
||||
// avoid cloning node data which we don't need
|
||||
(
|
||||
node_details.rewarding_details.clone(),
|
||||
node_details.is_unbonding(),
|
||||
),
|
||||
))
|
||||
if let Some(delegation) = og_delegations.get(&node_details.node_id()) {
|
||||
node_delegation_info.push(AddressDelegationInfo {
|
||||
details: delegation.clone(),
|
||||
node_reward_info: NodeBondStatus::Bonded {
|
||||
rewarding_info: node_details.rewarding_details.to_owned(),
|
||||
unbonding: node_details.is_unbonding(),
|
||||
},
|
||||
});
|
||||
|
||||
Some(node_details.node_id())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<HashMap<_, _>>();
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
Ok(AddressDelegationInfo {
|
||||
delegations: og_delegations,
|
||||
delegated_to_nodes: nym_nodes,
|
||||
})
|
||||
for (node_id, delegation) in og_delegations {
|
||||
if !delegated_to_nodes_bonded.contains(&node_id) {
|
||||
node_delegation_info.push(AddressDelegationInfo {
|
||||
details: delegation.clone(),
|
||||
node_reward_info: NodeBondStatus::UnBonded,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Ok(node_delegation_info)
|
||||
}
|
||||
|
||||
pub(crate) async fn calculate_rewards(
|
||||
&mut self,
|
||||
delegation_data: &AddressDelegationInfo,
|
||||
delegation_data: &Vec<AddressDelegationInfo>,
|
||||
) -> AxumResult<Vec<NyxAccountDelegationRewardDetails>> {
|
||||
let mut accumulated_rewards = Vec::new();
|
||||
for delegation in delegation_data.delegations.iter() {
|
||||
let node_id = &delegation.node_id;
|
||||
for delegation in delegation_data {
|
||||
let node_id = delegation.details.node_id;
|
||||
|
||||
if let Some((rewarding_details, is_unbonding)) =
|
||||
delegation_data.delegated_to_nodes.get(node_id)
|
||||
{
|
||||
match rewarding_details.determine_delegation_reward(delegation) {
|
||||
Ok(delegation_reward) => {
|
||||
let reward = NyxAccountDelegationRewardDetails {
|
||||
node_id: delegation.node_id,
|
||||
rewards: decimal_to_coin(delegation_reward, &self.base_denom),
|
||||
amount_staked: delegation.amount.clone(),
|
||||
node_still_fully_bonded: !is_unbonding,
|
||||
};
|
||||
// 4. sum the rewards and delegations
|
||||
self.total_delegations += delegation.amount.amount.u128();
|
||||
self.total_value += delegation.amount.amount.u128();
|
||||
self.total_value += reward.rewards.amount.u128();
|
||||
self.claimable_rewards += reward.rewards.amount.u128();
|
||||
match &delegation.node_reward_info {
|
||||
NodeBondStatus::Bonded {
|
||||
rewarding_info,
|
||||
unbonding,
|
||||
} => {
|
||||
match rewarding_info.determine_delegation_reward(&delegation.details) {
|
||||
Ok(delegation_reward) => {
|
||||
let reward = NyxAccountDelegationRewardDetails {
|
||||
node_id,
|
||||
rewards: decimal_to_coin(delegation_reward, &self.base_denom),
|
||||
amount_staked: delegation.details.amount.clone(),
|
||||
node_still_fully_bonded: !unbonding,
|
||||
};
|
||||
// 4. sum the rewards and delegations
|
||||
self.total_delegations += delegation.details.amount.amount.u128();
|
||||
self.total_value += delegation.details.amount.amount.u128();
|
||||
self.total_value += reward.rewards.amount.u128();
|
||||
self.claimable_rewards += reward.rewards.amount.u128();
|
||||
|
||||
accumulated_rewards.push(reward);
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"Couldn't determine delegations for {} on node {}: {}",
|
||||
&self.account_id, node_id, err
|
||||
)
|
||||
accumulated_rewards.push(reward);
|
||||
}
|
||||
Err(err) => {
|
||||
error!(
|
||||
"Couldn't determine delegations for {} on node {}: {}",
|
||||
&self.account_id, node_id, err
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
NodeBondStatus::UnBonded => {
|
||||
// directory cache doesn't store node details required to
|
||||
// calculate rewarding for unbonded nodes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,17 +184,27 @@ impl AddressDataCollector {
|
||||
}
|
||||
|
||||
pub(crate) struct AddressDelegationInfo {
|
||||
delegations: Vec<nym_mixnet_contract_common::Delegation>,
|
||||
delegated_to_nodes: HashMap<NodeId, RewardAndBondInfo>,
|
||||
details: nym_mixnet_contract_common::Delegation,
|
||||
node_reward_info: NodeBondStatus,
|
||||
}
|
||||
|
||||
impl AddressDelegationInfo {
|
||||
pub(crate) fn delegations(self) -> Vec<nym_mixnet_contract_common::Delegation> {
|
||||
self.delegations
|
||||
pub(crate) fn details(&self) -> &nym_mixnet_contract_common::Delegation {
|
||||
&self.details
|
||||
}
|
||||
|
||||
pub(crate) fn is_node_bonded(&self) -> bool {
|
||||
matches!(self.node_reward_info, NodeBondStatus::Bonded { .. })
|
||||
}
|
||||
}
|
||||
|
||||
type RewardAndBondInfo = (NodeRewarding, bool);
|
||||
pub(crate) enum NodeBondStatus {
|
||||
Bonded {
|
||||
rewarding_info: NodeRewarding,
|
||||
unbonding: bool,
|
||||
},
|
||||
UnBonded,
|
||||
}
|
||||
|
||||
fn decimal_to_coin(decimal: Decimal, denom: impl Into<String>) -> Coin {
|
||||
Coin::new(decimal.to_uint_floor(), denom)
|
||||
@@ -189,6 +212,7 @@ fn decimal_to_coin(decimal: Decimal, denom: impl Into<String>) -> Coin {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -21,6 +21,7 @@ pub struct NyxAccountDelegationDetails {
|
||||
pub height: u64,
|
||||
#[schema(value_type = Option<String>)]
|
||||
pub proxy: Option<Addr>,
|
||||
pub node_bonded: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, utoipa::ToSchema, utoipa::ToResponse)]
|
||||
@@ -41,6 +42,9 @@ pub struct NyxAccountDetails {
|
||||
#[schema(value_type = CoinSchema)]
|
||||
pub total_value: Coin,
|
||||
pub delegations: Vec<NyxAccountDelegationDetails>,
|
||||
/// Shows rewards from delegations to **currently** bonded nodes.
|
||||
/// Rewards from nodes that user delegated to, but were later unbonded,
|
||||
/// are claimable, but not shown here.
|
||||
pub accumulated_rewards: Vec<NyxAccountDelegationRewardDetails>,
|
||||
#[schema(value_type = String)]
|
||||
pub total_delegations: Coin,
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-node"
|
||||
version = "1.11.0"
|
||||
version = "1.12.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[package]
|
||||
name = "nym-network-requester"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.56"
|
||||
version = "1.1.57"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version = "1.70"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-cli"
|
||||
version = "1.1.55"
|
||||
version = "1.1.56"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nymvisor"
|
||||
version = "0.1.20"
|
||||
version = "0.1.21"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
Reference in New Issue
Block a user