Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: New command - staking #227

Merged
merged 54 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
54ef498
start
Jul 19, 2023
e2f3af7
added Withdraw, WithdrawAll
Jul 19, 2023
5d00339
added Unstake, UnstakeAll
Jul 19, 2023
7089c69
refactored Withdraw, WithdrawAll
Jul 22, 2023
538253c
added ViewBalance
Jul 22, 2023
2ac06dc
added ValidatorList
Jul 28, 2023
17fd266
refactored
Jul 28, 2023
5f5d1e2
fixed
Jul 28, 2023
39ccfb7
refactored
Jul 28, 2023
bca4e17
added delegated stake for view_account_summary
Jul 28, 2023
3f6b8ef
refactored get_validator_list()
Jul 29, 2023
e8fd341
refactored delegated_stake
Jul 29, 2023
9ddcb47
fixed
Jul 29, 2023
13f1b7b
added Stake, StakeAll
Aug 2, 2023
d94aade
added Deposit, DepositAndStake
Aug 2, 2023
9ad54aa
fixed <non-printable data (0 B)>
Aug 2, 2023
629d0d4
Merge branch 'master' into staking
FroVolod Aug 23, 2023
6acc1cb
Merge branch 'master' into staking
FroVolod Sep 3, 2023
b2646c8
updated to "order networks selection ..." #225
Sep 3, 2023
cc04fe1
added validators url
Sep 3, 2023
66d3b40
Merge branch 'master' into staking
FroVolod Sep 3, 2023
0d7e3b8
Merge branch 'master' into staking
FroVolod Sep 4, 2023
3591c95
Merge branch 'master' into staking
FroVolod Sep 9, 2023
d461b41
fixed unstake message
Sep 10, 2023
4e9af99
Merge branch 'master' into staking
FroVolod Sep 25, 2023
d93fedf
updated to "near-gas"
Sep 26, 2023
e8fbce9
clippy
Sep 26, 2023
70b7eaf
Merge branch 'master' into staking
FroVolod Sep 29, 2023
4fef7c4
updated: interactive-clap = "0.2.5"
Sep 30, 2023
3241e84
Merge branch 'master' into staking
FroVolod Oct 6, 2023
49809df
Merge remote-tracking branch 'origin/master' into staking
Oct 18, 2023
dbf79fc
refactor: optimized and simplified the delegated stake fetching
frol Oct 22, 2023
e6ba1ff
refactor: serde_json::to_vec() instead of .to_string().into_bytes()
Oct 22, 2023
cf8cfb6
Update src/commands/staking/delegate/unstake.rs
FroVolod Oct 22, 2023
4d92ff3
refactored get_validator_list()
Oct 23, 2023
1ebba51
refactored
Oct 24, 2023
1645264
updated input_account_id()
Oct 24, 2023
205d93a
refactored get_validator_list()
Oct 25, 2023
3038d61
added get_used_delegated_validator_list()
Oct 25, 2023
2e7a484
updated GUIDE
Oct 25, 2023
770796d
Update src/commands/staking/delegate/mod.rs
FroVolod Oct 26, 2023
2998e10
renamed Delegate to Delegation
Oct 26, 2023
fa9a653
fixed GUIDE
Oct 26, 2023
33abbb2
fixed GUIDE
Oct 26, 2023
d40363f
docs: Updated the GUIDE
frol Oct 26, 2023
7461a4f
updated StakeDelegationCommand
Oct 26, 2023
877098c
fixed GUIDE
Oct 26, 2023
8559cbc
updated view-balance
Oct 26, 2023
829144a
updated get_used_delegated_validator_list()
Oct 27, 2023
dde9cb8
updated cargo.lock
Oct 30, 2023
371bdf5
Merge remote-tracking branch 'origin/master' into staking
Oct 30, 2023
60f7e5c
fixed GUIDES
frol Oct 31, 2023
07960bb
refactor: common.rs
frol Oct 31, 2023
45c34d1
refactor: Refactored success messages and the `from_previous_context`
frol Oct 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 98 additions & 6 deletions src/commands/account/view_account_summary/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use color_eyre::eyre::Context;
use futures::StreamExt;

use crate::common::JsonRpcClientExt;
use crate::common::RpcQueryResponseExt;
use crate::common::{CallResultExt, JsonRpcClientExt, RpcQueryResponseExt};

#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(input_context = crate::GlobalContext)]
Expand All @@ -27,8 +27,9 @@ impl ViewAccountSummaryContext {

let on_after_getting_block_reference_callback: crate::network_view_at_block::OnAfterGettingBlockReferenceCallback = std::sync::Arc::new({
move |network_config, block_reference| {
let rpc_query_response = network_config
.json_rpc_client()
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!(
Expand All @@ -38,8 +39,7 @@ impl ViewAccountSummaryContext {
})?;
let account_view = rpc_query_response.account_view()?;

let access_key_list = network_config
.json_rpc_client()
let access_key_list = json_rpc_client
.blocking_call_view_access_key_list(
&account_id,
block_reference.clone(),
Expand All @@ -52,10 +52,38 @@ impl ViewAccountSummaryContext {
})?
.access_key_list_view()?;

let validators_stake = crate::common::get_validators_stake(&json_rpc_client)?;

let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()?;
let chunk_size = 15;
let concurrency = 10;

let delegated_stake: std::collections::HashMap<near_primitives::types::AccountId, crate::common::NearBalance> = runtime
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the delegated stake for account_id can be viewed on validators and proposals. I need help to view the delegated stake in the validator whitelist.

.block_on(
futures::stream::iter(validators_stake
.iter()
.collect::<Vec<_>>()
.chunks(chunk_size),
)
.map(|validators| async {
get_delegated_stake(&json_rpc_client, block_reference, &account_id, validators).await
})
.buffer_unordered(concurrency)
.collect::<Vec<Result<_, _>>>(),
)
.into_iter()
.try_fold(std::collections::HashMap::new(), |mut acc, x| {
acc.extend(x?);
Ok::<_, color_eyre::eyre::Error>(acc)
})?;

crate::common::display_account_info(
&rpc_query_response.block_hash,
&rpc_query_response.block_height,
&account_id,
delegated_stake,
&account_view,
&access_key_list.keys,
);
Expand Down Expand Up @@ -85,3 +113,67 @@ impl ViewAccountSummary {
)
}
}

async fn get_delegated_stake(
json_rpc_client: &near_jsonrpc_client::JsonRpcClient,
block_reference: &near_primitives::types::BlockReference,
account_id: &near_primitives::types::AccountId,
validators: &[(&near_primitives::types::AccountId, &u128)],
) -> color_eyre::Result<
std::collections::HashMap<near_primitives::types::AccountId, crate::common::NearBalance>,
> {
let mut validators_stake: std::collections::HashMap<
near_primitives::types::AccountId,
crate::common::NearBalance,
> = std::collections::HashMap::new();
for (validator_id, _) in validators {
let validator_id = *validator_id;
let user_staked_balance =
get_user_staked_balance(json_rpc_client, block_reference, validator_id, account_id)
.await
.ok();
let balance = if let Some(balance) = user_staked_balance {
if balance == 0 {
continue;
} else {
balance
}
} else {
continue;
};
validators_stake.insert(
validator_id.clone(),
crate::common::NearBalance::from_yoctonear(balance),
);
}
Ok(validators_stake)
}

async fn get_user_staked_balance(
json_rpc_client: &near_jsonrpc_client::JsonRpcClient,
block_reference: &near_primitives::types::BlockReference,
validator_account_id: &near_primitives::types::AccountId,
account_id: &near_primitives::types::AccountId,
) -> color_eyre::eyre::Result<u128> {
Ok(json_rpc_client
.call(near_jsonrpc_client::methods::query::RpcQueryRequest {
block_reference: block_reference.clone(),
request: near_primitives::views::QueryRequest::CallFunction {
account_id: validator_account_id.clone(),
method_name: "get_account_staked_balance".to_string(),
args: near_primitives::types::FunctionArgs::from(
serde_json::json!({
"account_id": account_id,
})
.to_string()
.into_bytes(),
),
},
})
.await
.wrap_err("Failed to fetch query for view method: 'get_account_staked_balance'")?
.call_result()?
.parse_result_from_json::<String>()
.wrap_err("Failed to parse return value of view function call for String.")?
.parse::<u128>()?)
}
6 changes: 6 additions & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use strum::{EnumDiscriminants, EnumIter, EnumMessage};
pub mod account;
mod config;
mod contract;
mod staking;
mod tokens;
mod transaction;

Expand All @@ -25,6 +26,11 @@ pub enum TopLevelCommand {
))]
/// Use this for token actions: send or view balances of NEAR, FT, or NFT
Tokens(self::tokens::TokensCommands),
#[strum_discriminants(strum(
message = "staking - Manage staking: view, add and withdraw stake"
))]
/// Use this for manage staking: view, add and withdraw stake
Staking(self::staking::Staking),
#[strum_discriminants(strum(
message = "contract - Manage smart-contracts: deploy code, call functions"
))]
Expand Down
88 changes: 88 additions & 0 deletions src/commands/staking/delegate/deposit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use std::str::FromStr;

#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(input_context = super::DelegateStakeContext)]
#[interactive_clap(output_context = DepositContext)]
pub struct Deposit {
/// Enter the attached amount to be deposited into the predecessor's internal account (example: 10NEAR or 0.5near or 10000yoctonear):
amount: crate::common::NearBalance,
#[interactive_clap(skip_default_input_arg)]
/// What is the signer account ID?
signer_account_id: crate::types::account_id::AccountId,
#[interactive_clap(named_arg)]
/// Select network
network_config: crate::network_for_transaction::NetworkForTransactionArgs,
}

#[derive(Clone)]
pub struct DepositContext(crate::commands::ActionContext);

impl DepositContext {
pub fn from_previous_context(
previous_context: super::DelegateStakeContext,
scope: &<Deposit as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
) -> color_eyre::eyre::Result<Self> {
let signer = scope.signer_account_id.clone();
let signer_id: near_primitives::types::AccountId = scope.signer_account_id.clone().into();
let validator_account_id = previous_context.validator_account_id.clone();
let amount = scope.amount.clone();

let on_after_getting_network_callback: crate::commands::OnAfterGettingNetworkCallback =
std::sync::Arc::new(move |_network_config| {
Ok(crate::commands::PrepopulatedTransaction {
signer_id: signer_id.clone(),
receiver_id: previous_context.validator_account_id.clone(),
actions: vec![near_primitives::transaction::Action::FunctionCall(
near_primitives::transaction::FunctionCallAction {
method_name: "deposit".to_string(),
args: serde_json::json!({}).to_string().into_bytes(),
gas: crate::common::NearGas::from_str("300 TeraGas")
.unwrap()
.inner,
deposit: amount.to_yoctonear(),
},
)],
})
});

let amount = scope.amount.clone();
let on_after_sending_transaction_callback: crate::transaction_signature_options::OnAfterSendingTransactionCallback = std::sync::Arc::new(
move |outcome_view, _network_config| {
if let near_primitives::views::FinalExecutionStatus::SuccessValue(_) = outcome_view.status {
eprintln!(
"<{signer}> has successfully deposited {amount} on <{validator_account_id}>.",
);
}
Ok(())
},
);
Ok(Self(crate::commands::ActionContext {
global_context: previous_context.global_context,
on_after_getting_network_callback,
on_before_signing_callback: std::sync::Arc::new(
|_prepolulated_unsinged_transaction, _network_config| Ok(()),
),
on_before_sending_transaction_callback: std::sync::Arc::new(
|_signed_transaction, _network_config, _message| Ok(()),
),
on_after_sending_transaction_callback,
}))
}
}

impl From<DepositContext> for crate::commands::ActionContext {
fn from(item: DepositContext) -> Self {
item.0
}
}

impl Deposit {
pub fn input_signer_account_id(
context: &super::DelegateStakeContext,
) -> color_eyre::eyre::Result<Option<crate::types::account_id::AccountId>> {
crate::common::input_signer_account_id_from_used_account_list(
&context.global_context.config.credentials_home_dir,
"What is the signer account ID?",
)
}
}
88 changes: 88 additions & 0 deletions src/commands/staking/delegate/deposit_and_stake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use std::str::FromStr;

#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(input_context = super::DelegateStakeContext)]
#[interactive_clap(output_context = DepositAndStakeContext)]
pub struct DepositAndStake {
/// Enter the attached amount to be deposited and then staked into the predecessor's internal account (example: 10NEAR or 0.5near or 10000yoctonear):
amount: crate::common::NearBalance,
#[interactive_clap(skip_default_input_arg)]
/// What is the signer account ID?
signer_account_id: crate::types::account_id::AccountId,
#[interactive_clap(named_arg)]
/// Select network
network_config: crate::network_for_transaction::NetworkForTransactionArgs,
}

#[derive(Clone)]
pub struct DepositAndStakeContext(crate::commands::ActionContext);

impl DepositAndStakeContext {
pub fn from_previous_context(
previous_context: super::DelegateStakeContext,
scope: &<DepositAndStake as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
) -> color_eyre::eyre::Result<Self> {
let signer = scope.signer_account_id.clone();
let signer_id: near_primitives::types::AccountId = scope.signer_account_id.clone().into();
let validator_account_id = previous_context.validator_account_id.clone();
let amount = scope.amount.clone();

let on_after_getting_network_callback: crate::commands::OnAfterGettingNetworkCallback =
std::sync::Arc::new(move |_network_config| {
Ok(crate::commands::PrepopulatedTransaction {
signer_id: signer_id.clone(),
receiver_id: previous_context.validator_account_id.clone(),
actions: vec![near_primitives::transaction::Action::FunctionCall(
near_primitives::transaction::FunctionCallAction {
method_name: "deposit_and_stake".to_string(),
args: serde_json::json!({}).to_string().into_bytes(),
gas: crate::common::NearGas::from_str("300 TeraGas")
.unwrap()
.inner,
deposit: amount.to_yoctonear(),
},
)],
})
});

let amount = scope.amount.clone();
let on_after_sending_transaction_callback: crate::transaction_signature_options::OnAfterSendingTransactionCallback = std::sync::Arc::new(
move |outcome_view, _network_config| {
if let near_primitives::views::FinalExecutionStatus::SuccessValue(_) = outcome_view.status {
eprintln!(
"<{signer}> has successfully deposited and staked {amount} on <{validator_account_id}>.",
);
}
Ok(())
},
);
Ok(Self(crate::commands::ActionContext {
global_context: previous_context.global_context,
on_after_getting_network_callback,
on_before_signing_callback: std::sync::Arc::new(
|_prepolulated_unsinged_transaction, _network_config| Ok(()),
),
on_before_sending_transaction_callback: std::sync::Arc::new(
|_signed_transaction, _network_config, _message| Ok(()),
),
on_after_sending_transaction_callback,
}))
}
}

impl From<DepositAndStakeContext> for crate::commands::ActionContext {
fn from(item: DepositAndStakeContext) -> Self {
item.0
}
}

impl DepositAndStake {
pub fn input_signer_account_id(
context: &super::DelegateStakeContext,
) -> color_eyre::eyre::Result<Option<crate::types::account_id::AccountId>> {
crate::common::input_signer_account_id_from_used_account_list(
&context.global_context.config.credentials_home_dir,
"What is the signer account ID?",
)
}
}
Loading
Loading