Files
nym/contracts/vesting/src/queries.rs
T
Jędrzej Stuczyński 4fb63d8892 Feature/vesting delegation amount query (#3229)
* moved queries and transactions out of contract.rs

* added queries for vesting delegation details

* nyxd_client support
2023-04-05 09:22:43 +01:00

358 lines
12 KiB
Rust

// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::errors::ContractError;
use crate::storage;
use crate::storage::{account_from_address, BlockTimestampSecs, ACCOUNTS, DELEGATIONS, MIX_DENOM};
use crate::traits::VestingAccount;
use crate::vesting::Account;
use contracts_common::ContractBuildInformation;
use cosmwasm_std::{Coin, Deps, Env, Order, StdResult, Timestamp, Uint128};
use cw_storage_plus::Bound;
use mixnet_contract_common::MixId;
use vesting_contract_common::{
AccountVestingCoins, AccountsResponse, AllDelegationsResponse, BaseVestingAccountInfo,
DelegationTimesResponse, OriginalVestingResponse, Period, PledgeData, VestingCoinsResponse,
VestingDelegation,
};
/// Get current vesting period for a given [crate::vesting::Account].
pub fn try_get_current_vesting_period(
address: &str,
deps: Deps<'_>,
env: Env,
) -> Result<Period, ContractError> {
let account = account_from_address(address, deps.storage, deps.api)?;
account.get_current_vesting_period(env.block.time)
}
/// Loads mixnode bond from vesting contract storage.
pub fn try_get_mixnode(address: &str, deps: Deps<'_>) -> Result<Option<PledgeData>, ContractError> {
let account = account_from_address(address, deps.storage, deps.api)?;
account.load_mixnode_pledge(deps.storage)
}
/// Loads gateway bond from vesting contract storage.
pub fn try_get_gateway(address: &str, deps: Deps<'_>) -> Result<Option<PledgeData>, ContractError> {
let account = account_from_address(address, deps.storage, deps.api)?;
account.load_gateway_pledge(deps.storage)
}
pub fn try_get_account(address: &str, deps: Deps<'_>) -> Result<Account, ContractError> {
account_from_address(address, deps.storage, deps.api)
}
/// Gets build information of this contract.
pub fn get_contract_version() -> ContractBuildInformation {
// as per docs
// env! macro will expand to the value of the named environment variable at
// compile time, yielding an expression of type `&'static str`
ContractBuildInformation {
build_timestamp: env!("VERGEN_BUILD_TIMESTAMP").to_string(),
build_version: env!("VERGEN_BUILD_SEMVER").to_string(),
commit_sha: option_env!("VERGEN_GIT_SHA").unwrap_or("NONE").to_string(),
commit_timestamp: option_env!("VERGEN_GIT_COMMIT_TIMESTAMP")
.unwrap_or("NONE")
.to_string(),
commit_branch: option_env!("VERGEN_GIT_BRANCH")
.unwrap_or("NONE")
.to_string(),
rustc_version: env!("VERGEN_RUSTC_SEMVER").to_string(),
}
}
pub fn try_get_all_accounts(
deps: Deps<'_>,
start_after: Option<String>,
limit: Option<u32>,
) -> Result<AccountsResponse, ContractError> {
let limit = limit.unwrap_or(150).min(250) as usize;
let start = start_after
.map(|raw| deps.api.addr_validate(&raw).map(Bound::exclusive))
.transpose()?;
let accounts = ACCOUNTS
.range(deps.storage, start, None, Order::Ascending)
.take(limit)
.map(|res| {
res.map(|(_, account)| BaseVestingAccountInfo {
account_id: account.storage_key(),
owner: account.owner_address,
})
})
.collect::<StdResult<Vec<_>>>()?;
let start_next_after = accounts.last().map(|acc| acc.owner.clone());
Ok(AccountsResponse {
accounts,
start_next_after,
})
}
pub fn try_get_all_accounts_vesting_coins(
deps: Deps<'_>,
env: Env,
start_after: Option<String>,
limit: Option<u32>,
) -> Result<VestingCoinsResponse, ContractError> {
let limit = limit.unwrap_or(150).min(250) as usize;
let start = start_after
.map(|raw| deps.api.addr_validate(&raw).map(Bound::exclusive))
.transpose()?;
let accounts = ACCOUNTS
.range(deps.storage, start, None, Order::Ascending)
.take(limit)
.map(|res| {
res.map(|(_, account)| {
account
.get_vesting_coins(None, &env, deps.storage)
.map(|still_vesting| AccountVestingCoins {
account_id: account.storage_key(),
owner: account.owner_address,
still_vesting,
})
})
})
.collect::<StdResult<Result<Vec<_>, _>>>()??;
let start_next_after = accounts.last().map(|acc| acc.owner.clone());
Ok(VestingCoinsResponse {
accounts,
start_next_after,
})
}
/// Gets currently locked coins, see [crate::traits::VestingAccount::locked_coins]
pub fn try_get_locked_coins(
vesting_account_address: &str,
block_time: Option<Timestamp>,
env: Env,
deps: Deps<'_>,
) -> Result<Coin, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
account.locked_coins(block_time, &env, deps.storage)
}
/// Returns currently locked coins, see [crate::traits::VestingAccount::spendable_coins]
pub fn try_get_spendable_coins(
vesting_account_address: &str,
block_time: Option<Timestamp>,
env: Env,
deps: Deps<'_>,
) -> Result<Coin, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
account.spendable_coins(block_time, &env, deps.storage)
}
/// Returns coins that have vested, see [crate::traits::VestingAccount::get_vested_coins]
pub fn try_get_vested_coins(
vesting_account_address: &str,
block_time: Option<Timestamp>,
env: Env,
deps: Deps<'_>,
) -> Result<Coin, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
account.get_vested_coins(block_time, &env, deps.storage)
}
/// Returns coins that are vesting, see [crate::traits::VestingAccount::get_vesting_coins]
pub fn try_get_vesting_coins(
vesting_account_address: &str,
block_time: Option<Timestamp>,
env: Env,
deps: Deps<'_>,
) -> Result<Coin, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
account.get_vesting_coins(block_time, &env, deps.storage)
}
/// See [crate::traits::VestingAccount::get_start_time]
pub fn try_get_start_time(
vesting_account_address: &str,
deps: Deps<'_>,
) -> Result<Timestamp, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
Ok(account.get_start_time())
}
/// See [crate::traits::VestingAccount::get_end_time]
pub fn try_get_end_time(
vesting_account_address: &str,
deps: Deps<'_>,
) -> Result<Timestamp, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
Ok(account.get_end_time())
}
/// See [crate::traits::VestingAccount::get_original_vesting]
pub fn try_get_original_vesting(
vesting_account_address: &str,
deps: Deps<'_>,
) -> Result<OriginalVestingResponse, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
account.get_original_vesting()
}
pub fn try_get_historical_vesting_staking_reward(
vesting_account_address: &str,
deps: Deps<'_>,
) -> Result<Coin, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
account.get_historical_vested_staking_rewards(deps.storage)
}
pub fn try_get_spendable_vested_coins(
vesting_account_address: &str,
deps: Deps<'_>,
env: Env,
) -> Result<Coin, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
account.spendable_vested_coins(None, &env, deps.storage)
}
pub fn try_get_spendable_reward_coins(
vesting_account_address: &str,
deps: Deps<'_>,
env: Env,
) -> Result<Coin, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
account.spendable_reward_coins(None, &env, deps.storage)
}
pub fn try_get_delegated_coins(
vesting_account_address: &str,
deps: Deps<'_>,
) -> Result<Coin, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
let denom = MIX_DENOM.load(deps.storage)?;
let amount = account.total_delegations(deps.storage)?;
Ok(Coin { denom, amount })
}
pub fn try_get_pledged_coins(
vesting_account_address: &str,
deps: Deps<'_>,
) -> Result<Coin, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
let denom = MIX_DENOM.load(deps.storage)?;
let amount = account.total_pledged(deps.storage)?;
Ok(Coin { denom, amount })
}
pub fn try_get_staked_coins(
vesting_account_address: &str,
deps: Deps<'_>,
) -> Result<Coin, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
let denom = MIX_DENOM.load(deps.storage)?;
let amount = account.total_staked(deps.storage)?;
Ok(Coin { denom, amount })
}
pub fn try_get_withdrawn_coins(
vesting_account_address: &str,
deps: Deps<'_>,
) -> Result<Coin, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
let denom = MIX_DENOM.load(deps.storage)?;
let amount = account.load_withdrawn(deps.storage)?;
Ok(Coin { denom, amount })
}
/// Returns timestamps at which delegations were made
pub fn try_get_delegation_times(
deps: Deps<'_>,
vesting_account_address: &str,
mix_id: MixId,
) -> Result<DelegationTimesResponse, ContractError> {
let owner = deps.api.addr_validate(vesting_account_address)?;
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
let delegation_timestamps =
storage::load_delegation_timestamps((account.storage_key(), mix_id), deps.storage)?;
Ok(DelegationTimesResponse {
owner,
account_id: account.storage_key(),
mix_id,
delegation_timestamps,
})
}
pub fn try_get_all_delegations(
deps: Deps<'_>,
start_after: Option<(u32, MixId, BlockTimestampSecs)>,
limit: Option<u32>,
) -> Result<AllDelegationsResponse, ContractError> {
let limit = limit.unwrap_or(100).min(200) as usize;
let start = start_after.map(Bound::exclusive);
let delegations = DELEGATIONS
.range(deps.storage, start, None, Order::Ascending)
.map(|kv| {
kv.map(
|((account_id, mix_id, block_timestamp), amount)| VestingDelegation {
account_id,
mix_id,
block_timestamp,
amount,
},
)
})
.collect::<StdResult<Vec<_>>>()?;
let start_next_after = if delegations.len() < limit {
None
} else {
delegations
.last()
.map(|delegation| delegation.storage_key())
};
Ok(AllDelegationsResponse {
delegations,
start_next_after,
})
}
pub fn try_get_delegation(
deps: Deps<'_>,
vesting_account_address: &str,
mix_id: MixId,
block_timestamp_secs: BlockTimestampSecs,
) -> Result<VestingDelegation, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
let storage_key = (account.storage_key(), mix_id, block_timestamp_secs);
let delegation_amount = DELEGATIONS.load(deps.storage, storage_key)?;
Ok(VestingDelegation {
account_id: account.storage_key(),
mix_id,
block_timestamp: block_timestamp_secs,
amount: delegation_amount,
})
}
pub fn try_get_delegation_amount(
deps: Deps<'_>,
vesting_account_address: &str,
mix_id: MixId,
) -> Result<Coin, ContractError> {
let account = account_from_address(vesting_account_address, deps.storage, deps.api)?;
let amount = DELEGATIONS
.prefix((account.storage_key(), mix_id))
.range(deps.storage, None, None, Order::Ascending)
.map(|kv_res| kv_res.map(|kv| kv.1))
.try_fold(Uint128::zero(), |acc, x_res| x_res.map(|x| x + acc))?;
let denom = MIX_DENOM.load(deps.storage)?;
Ok(Coin { denom, amount })
}