Skip to content

Commit

Permalink
feat: Added loading indicators for "staking" group commands (#356)
Browse files Browse the repository at this point in the history
  • Loading branch information
FroVolod authored Jun 25, 2024
1 parent fdb92bf commit 50afeee
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 106 deletions.
196 changes: 113 additions & 83 deletions src/commands/account/view_account_summary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,89 +28,7 @@ impl ViewAccountSummaryContext {
let account_id: near_primitives::types::AccountId = scope.account_id.clone().into();

move |network_config, block_reference| {
let json_rpc_client = network_config.json_rpc_client();

let rpc_query_response = json_rpc_client
.blocking_call_view_account(&account_id.clone(), block_reference.clone())
.wrap_err_with(|| {
format!(
"Failed to fetch query ViewAccount for account <{}> on network <{}>",
account_id,
network_config.network_name
)
})?;
let account_view = rpc_query_response.account_view()?;

let access_key_list = network_config
.json_rpc_client()
.blocking_call_view_access_key_list(&account_id, block_reference.clone())
.map_err(|err| {
tracing::warn!("Failed to fetch query ViewAccessKeyList for account <{}> on network <{}>: {:#}",
account_id,
network_config.network_name,
err
);
})
.ok()
.and_then(
|query_response| query_response.access_key_list_view().map_err(|err| {
tracing::warn!("Failed to parse ViewAccessKeyList for account <{}> on network <{}>: {:#}",
account_id,
network_config.network_name,
err
);
})
.ok()
);

let historically_delegated_validators = network_config.fastnear_url.as_ref()
.and_then(|fastnear_url| crate::common::fetch_historically_delegated_staking_pools(fastnear_url, &account_id).ok());
let validators = if let Some(validators) = historically_delegated_validators {
validators
} else if let Some(staking_pools_factory_account_id) = &network_config.staking_pools_factory_account_id {
crate::common::fetch_currently_active_staking_pools(&json_rpc_client, staking_pools_factory_account_id)?
} else {
Default::default()
};

let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()?;
let concurrency = 10;
let delegated_stake: std::collections::BTreeMap<near_primitives::types::AccountId, near_token::NearToken> = runtime
.block_on(
futures::stream::iter(validators)
.map(|validator_account_id| async {
let balance = get_delegated_staked_balance(&json_rpc_client, block_reference, &validator_account_id, &account_id).await?;
Ok::<_, color_eyre::eyre::Report>((
validator_account_id,
balance,
))
})
.buffer_unordered(concurrency)
.filter(|balance_result| futures::future::ready(
if let Ok((_, balance)) = balance_result {
!balance.is_zero()
} else {
true
}
))
.try_collect(),
)?;

let optional_account_profile = get_account_profile(&account_id, network_config, block_reference).ok().flatten();

crate::common::display_account_info(
&rpc_query_response.block_hash,
&rpc_query_response.block_height,
&account_id,
&delegated_stake,
&account_view,
access_key_list.as_ref(),
optional_account_profile.as_ref()
);

Ok(())
get_account_inquiry(&account_id, network_config, block_reference)
}
});
Ok(Self(crate::network_view_at_block::ArgsForViewContext {
Expand Down Expand Up @@ -138,6 +56,118 @@ impl ViewAccountSummary {
}
}

#[tracing::instrument(name = "Receiving an inquiry about your account ...", skip_all)]
fn get_account_inquiry(
account_id: &near_primitives::types::AccountId,
network_config: &crate::config::NetworkConfig,
block_reference: &near_primitives::types::BlockReference,
) -> crate::CliResult {
let json_rpc_client = network_config.json_rpc_client();

let rpc_query_response = json_rpc_client
.blocking_call_view_account(account_id, block_reference.clone())
.wrap_err_with(|| {
format!(
"Failed to fetch query ViewAccount for account <{}> on network <{}>",
account_id, network_config.network_name
)
})?;
let account_view = rpc_query_response.account_view()?;

let access_key_list = network_config
.json_rpc_client()
.blocking_call_view_access_key_list(account_id, block_reference.clone())
.map_err(|err| {
tracing::warn!(
"Failed to fetch query ViewAccessKeyList for account <{}> on network <{}>: {:#}",
account_id,
network_config.network_name,
err
);
})
.ok()
.and_then(|query_response| {
query_response
.access_key_list_view()
.map_err(|err| {
tracing::warn!(
"Failed to parse ViewAccessKeyList for account <{}> on network <{}>: {:#}",
account_id,
network_config.network_name,
err
);
})
.ok()
});

let historically_delegated_validators =
network_config
.fastnear_url
.as_ref()
.and_then(|fastnear_url| {
crate::common::fetch_historically_delegated_staking_pools(fastnear_url, account_id)
.ok()
});
let validators = if let Some(validators) = historically_delegated_validators {
validators
} else if let Some(staking_pools_factory_account_id) =
&network_config.staking_pools_factory_account_id
{
crate::common::fetch_currently_active_staking_pools(
&json_rpc_client,
staking_pools_factory_account_id,
)?
} else {
Default::default()
};

let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()?;
let concurrency = 10;
let delegated_stake: std::collections::BTreeMap<
near_primitives::types::AccountId,
near_token::NearToken,
> = runtime.block_on(
futures::stream::iter(validators)
.map(|validator_account_id| async {
let balance = get_delegated_staked_balance(
&json_rpc_client,
block_reference,
&validator_account_id,
account_id,
)
.await?;
Ok::<_, color_eyre::eyre::Report>((validator_account_id, balance))
})
.buffer_unordered(concurrency)
.filter(|balance_result| {
futures::future::ready(if let Ok((_, balance)) = balance_result {
!balance.is_zero()
} else {
true
})
})
.try_collect(),
)?;

let optional_account_profile = get_account_profile(account_id, network_config, block_reference)
.ok()
.flatten();

crate::common::display_account_info(
&rpc_query_response.block_hash,
&rpc_query_response.block_height,
account_id,
&delegated_stake,
&account_view,
access_key_list.as_ref(),
optional_account_profile.as_ref(),
);

Ok(())
}

#[tracing::instrument(
name = "Receiving the delegated staked balance from validator",
skip_all
Expand Down
84 changes: 64 additions & 20 deletions src/commands/staking/delegate/view_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ pub struct ViewBalance {
pub struct ViewBalanceContext(crate::network_view_at_block::ArgsForViewContext);

impl ViewBalanceContext {
#[tracing::instrument(
name = "View the delegated stake balance for your account ...",
skip_all
)]
pub fn from_previous_context(
previous_context: super::StakeDelegationContext,
scope: &<ViewBalance as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
Expand All @@ -33,22 +29,8 @@ impl ViewBalanceContext {

let on_after_getting_block_reference_callback: crate::network_view_at_block::OnAfterGettingBlockReferenceCallback = std::sync::Arc::new({

move |network_config, block_reference| {
let user_staked_balance: u128 = get_user_staked_balance(network_config, block_reference, &validator_account_id, &account_id)?;
let user_unstaked_balance: u128 = get_user_unstaked_balance(network_config, block_reference, &validator_account_id, &account_id)?;
let user_total_balance: u128 = get_user_total_balance(network_config, block_reference, &validator_account_id, &account_id)?;
let withdrawal_availability_message = match is_account_unstaked_balance_available_for_withdrawal(network_config, &validator_account_id, &account_id)? {
true if user_unstaked_balance > 0 => "(available for withdrawal)",
false if user_unstaked_balance > 0 => "(not available for withdrawal in the current epoch)",
_ => ""
};

eprintln!("Delegated stake balance with validator <{validator_account_id}> by <{account_id}>:");
eprintln!(" Staked balance: {:>38}", near_token::NearToken::from_yoctonear(user_staked_balance).to_string());
eprintln!(" Unstaked balance: {:>38} {withdrawal_availability_message}", near_token::NearToken::from_yoctonear(user_unstaked_balance).to_string());
eprintln!(" Total balance: {:>38}", near_token::NearToken::from_yoctonear(user_total_balance).to_string());

Ok(())
move |network_config: &crate::config::NetworkConfig, block_reference: &near_primitives::types::BlockReference| {
calculation_delegated_stake_balance(&account_id, &validator_account_id, network_config, block_reference)
}
});
Ok(Self(crate::network_view_at_block::ArgsForViewContext {
Expand All @@ -73,6 +55,64 @@ impl ViewBalance {
}
}

#[tracing::instrument(
name = "Calculation of the delegated stake balance for your account ...",
skip_all
)]
fn calculation_delegated_stake_balance(
account_id: &near_primitives::types::AccountId,
validator_account_id: &near_primitives::types::AccountId,
network_config: &crate::config::NetworkConfig,
block_reference: &near_primitives::types::BlockReference,
) -> crate::CliResult {
let user_staked_balance: u128 = get_user_staked_balance(
network_config,
block_reference,
validator_account_id,
account_id,
)?;
let user_unstaked_balance: u128 = get_user_unstaked_balance(
network_config,
block_reference,
validator_account_id,
account_id,
)?;
let user_total_balance: u128 = get_user_total_balance(
network_config,
block_reference,
validator_account_id,
account_id,
)?;
let withdrawal_availability_message =
match is_account_unstaked_balance_available_for_withdrawal(
network_config,
validator_account_id,
account_id,
)? {
true if user_unstaked_balance > 0 => "(available for withdrawal)",
false if user_unstaked_balance > 0 => {
"(not available for withdrawal in the current epoch)"
}
_ => "",
};

eprintln!("Delegated stake balance with validator <{validator_account_id}> by <{account_id}>:");
eprintln!(
" Staked balance: {:>38}",
near_token::NearToken::from_yoctonear(user_staked_balance).to_string()
);
eprintln!(
" Unstaked balance: {:>38} {withdrawal_availability_message}",
near_token::NearToken::from_yoctonear(user_unstaked_balance).to_string()
);
eprintln!(
" Total balance: {:>38}",
near_token::NearToken::from_yoctonear(user_total_balance).to_string()
);

Ok(())
}

#[tracing::instrument(name = "Getting the staked balance for the user ...", skip_all)]
pub fn get_user_staked_balance(
network_config: &crate::config::NetworkConfig,
Expand Down Expand Up @@ -157,6 +197,10 @@ pub fn get_user_total_balance(
.parse::<u128>()?)
}

#[tracing::instrument(
name = "Getting account unstaked balance available for withdrawal ...",
skip_all
)]
pub fn is_account_unstaked_balance_available_for_withdrawal(
network_config: &crate::config::NetworkConfig,
validator_account_id: &near_primitives::types::AccountId,
Expand Down
6 changes: 6 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,10 @@ pub fn get_delegated_validator_list_from_mainnet(
.collect())
}

#[tracing::instrument(
name = "Retrieving a list of delegated validators from \"mainnet\" ...",
skip_all
)]
pub fn get_used_delegated_validator_list(
config: &crate::config::Config,
) -> color_eyre::eyre::Result<VecDeque<near_primitives::types::AccountId>> {
Expand Down Expand Up @@ -1548,6 +1552,7 @@ struct StakingResponse {
pools: Vec<StakingPool>,
}

#[tracing::instrument(name = "Getting historically delegated staking pools ...", skip_all)]
pub fn fetch_historically_delegated_staking_pools(
fastnear_url: &url::Url,
account_id: &near_primitives::types::AccountId,
Expand All @@ -1563,6 +1568,7 @@ pub fn fetch_historically_delegated_staking_pools(
.collect())
}

#[tracing::instrument(name = "Getting currently active staking pools ...", skip_all)]
pub fn fetch_currently_active_staking_pools(
json_rpc_client: &near_jsonrpc_client::JsonRpcClient,
staking_pools_factory_account_id: &near_primitives::types::AccountId,
Expand Down
3 changes: 0 additions & 3 deletions src/network_view_at_block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ pub struct Now;
pub struct NowContext;

impl NowContext {
#[tracing::instrument(name = "Receiving an inquiry about your account ...", skip_all)]
pub fn from_previous_context(
previous_context: NetworkViewAtBlockArgsContext,
_scope: &<Now as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
Expand All @@ -115,7 +114,6 @@ pub struct AtBlockHeight {
pub struct AtBlockHeightContext;

impl AtBlockHeightContext {
#[tracing::instrument(name = "Receiving an inquiry about your account ...", skip_all)]
pub fn from_previous_context(
previous_context: NetworkViewAtBlockArgsContext,
scope: &<AtBlockHeight as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
Expand All @@ -142,7 +140,6 @@ pub struct BlockIdHash {
pub struct BlockIdHashContext;

impl BlockIdHashContext {
#[tracing::instrument(name = "Receiving an inquiry about your account ...", skip_all)]
pub fn from_previous_context(
previous_context: NetworkViewAtBlockArgsContext,
scope: &<BlockIdHash as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
Expand Down

0 comments on commit 50afeee

Please sign in to comment.