Compare commits

...

9 Commits

Author SHA1 Message Date
benedetta davico ac12455f97 add comment 2025-05-27 16:35:51 +02:00
benedetta davico 1c6db86259 Merge pull request #5803 from nymtech/benny/change-rust-version
change rust version to fix ci
2025-05-27 12:11:13 +02:00
benedetta davico e126c1f7f1 Update publish-nym-binaries.yml 2025-05-27 11:45:53 +02:00
benedetta davico 31772019cd Update ci-contracts.yml 2025-05-27 11:44:01 +02:00
benedettadavico 5369e5eab9 update changelog 2025-05-27 10:03:22 +02:00
Andrej Mihajlov 2e634c59a7 Merge pull request #5801 from nymtech/am/backport-pr-5779 2025-05-26 21:03:29 +02:00
jmwample d7383d74f3 more relaxed usage of reqwest accept-encoding 2025-05-26 17:54:19 +02:00
dynco-nym e98d60d7ce Add node_bonded field to delegations (#5759)
* Add node_bonded field to delegations
- clarifies whether the delegation is to a bonded or unbonded node
- include delegations to unbonded nodes in the returned list

* PR feedback
2025-05-19 15:18:41 +02:00
benedettadavico f47650d6c8 bump binary versions 2025-05-16 13:03:37 +02:00
16 changed files with 168 additions and 88 deletions
+2 -1
View File
@@ -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
+1 -1
View File
@@ -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
+52
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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"
+1 -1
View File
@@ -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 }
+11 -12
View File
@@ -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
View File
@@ -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
+5 -5
View File
@@ -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]
+4
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nymvisor"
version = "0.1.20"
version = "0.1.21"
authors.workspace = true
repository.workspace = true
homepage.workspace = true