Files
nym/common/credential-proxy/src/shared_state/required_deposit_cache.rs
T
Jędrzej Stuczyński 6581ebf235 feat: multiple deposit prices (#6608)
* added reduced pricing handling logic

* admin methods for setting the whitelist of reduced price accounts

* updated client traits

* query to get all whitelisted accounts

* query for getting detailed deposit statistics

* fixes

* set initial whitelisted accounts in the migration

* stop transferring tokens to the holding account after redemption

* stop gateways from creating redemption multisig proposals

* make sure credential-proxy uses reduced deposits when available

* cargo fmt

* update deposit handler to allow EITHER default price or reduced price

this will allow non-breaking upgrades of NS and credential proxy

* removed use of unstable rust features

* rebuilt contract schema

* correct license timestamp
2026-03-26 16:02:19 +00:00

89 lines
2.4 KiB
Rust

// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::error::CredentialProxyError;
use crate::shared_state::nyxd_client::ChainClient;
use nym_validator_client::nyxd::Coin;
use nym_validator_client::nyxd::contract_traits::EcashQueryClient;
use std::sync::Arc;
use time::OffsetDateTime;
use tokio::sync::RwLock;
use tracing::{info, warn};
pub struct CachedDeposit {
valid_until: OffsetDateTime,
required_amount: Coin,
}
impl CachedDeposit {
const MAX_VALIDITY: time::Duration = time::Duration::MINUTE;
fn is_valid(&self) -> bool {
self.valid_until > OffsetDateTime::now_utc()
}
fn update(&mut self, required_amount: Coin) {
self.valid_until = OffsetDateTime::now_utc() + Self::MAX_VALIDITY;
self.required_amount = required_amount;
}
}
impl Default for CachedDeposit {
fn default() -> Self {
CachedDeposit {
valid_until: OffsetDateTime::UNIX_EPOCH,
required_amount: Coin {
amount: u128::MAX,
denom: "unym".to_string(),
},
}
}
}
#[derive(Clone, Default)]
pub struct RequiredDepositCache {
inner: Arc<RwLock<CachedDeposit>>,
}
impl RequiredDepositCache {
pub async fn get_or_update(
&self,
chain_client: &ChainClient,
) -> Result<Coin, CredentialProxyError> {
let read_guard = self.inner.read().await;
if read_guard.is_valid() {
return Ok(read_guard.required_amount.clone());
}
// update cache
drop(read_guard);
let address = chain_client.address().await;
info!("checking deposit required by {address}");
let mut write_guard = self.inner.write().await;
let read_permit = chain_client.query_chain().await;
let reduced = read_permit
.get_reduced_deposit_amount(address.to_string())
.await?;
let deposit_amount = match reduced {
Some(reduced) => {
info!("we're permitted to use reduced price");
reduced
}
None => {
warn!(
"using default deposit value {address} is not whitelisted for price reduction"
);
read_permit.get_default_deposit_amount().await?
}
};
let nym_coin: Coin = deposit_amount.into();
write_guard.update(nym_coin.clone());
Ok(nym_coin)
}
}