ghost-eye/src/network/predefined_txs.rs
Uncle Stretch 10b8337f8d
withdraw unbonded functionality added
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-02-11 16:09:34 +03:00

272 lines
8.6 KiB
Rust

use color_eyre::Result;
use subxt::{
ext::sp_core::{sr25519::Pair, Pair as PairT},
tx::{PairSigner, TxProgress},
OnlineClient,
};
use tokio::sync::mpsc::UnboundedSender;
use crate::{
action::Action,
casper::{CasperConfig, CasperExtrinsicParamsBuilder},
casper_network::{self, runtime_types},
types::{ActionLevel, ActionTarget},
};
pub async fn transfer_balance(
action_tx: &UnboundedSender<Action>,
api: &OnlineClient<CasperConfig>,
sender: &[u8; 32],
receiver: &[u8; 32],
amount: &u128,
maybe_nonce: Option<&mut u32>,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
let receiver_id = subxt::utils::MultiAddress::Id(subxt::utils::AccountId32::from(*receiver));
let transfer_tx = casper_network::tx().balances().transfer_allow_death(receiver_id, *amount);
inner_sign_and_submit_then_watch(
action_tx,
api,
sender,
maybe_nonce,
Box::new(transfer_tx),
"transfer",
ActionTarget::WalletLog,
).await
}
pub async fn bond_extra(
action_tx: &UnboundedSender<Action>,
api: &OnlineClient<CasperConfig>,
sender: &[u8; 32],
amount: &u128,
maybe_nonce: Option<&mut u32>,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
let bond_extra_tx = casper_network::tx().staking().bond_extra(*amount);
inner_sign_and_submit_then_watch(
action_tx,
api,
sender,
maybe_nonce,
Box::new(bond_extra_tx),
"bond extra",
ActionTarget::ValidatorLog,
).await
}
pub async fn bond(
action_tx: &UnboundedSender<Action>,
api: &OnlineClient<CasperConfig>,
sender: &[u8; 32],
amount: &u128,
maybe_nonce: Option<&mut u32>,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
// auto-stake everything by now
let reward_destination = casper_network::runtime_types::pallet_staking::RewardDestination::Staked;
let bond_tx = casper_network::tx().staking().bond(*amount, reward_destination);
inner_sign_and_submit_then_watch(
action_tx,
api,
sender,
maybe_nonce,
Box::new(bond_tx),
"bond",
ActionTarget::ValidatorLog,
).await
}
pub async fn payout_stakers(
action_tx: &UnboundedSender<Action>,
api: &OnlineClient<CasperConfig>,
sender: &[u8; 32],
stash: &[u8; 32],
era_index: u32,
maybe_nonce: Option<&mut u32>,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
let stash_id = subxt::utils::AccountId32::from(*stash);
let payout_stakers_tx = casper_network::tx().staking().payout_stakers(stash_id, era_index);
inner_sign_and_submit_then_watch(
action_tx,
api,
sender,
maybe_nonce,
Box::new(payout_stakers_tx),
"payout stakers",
ActionTarget::ValidatorLog,
).await
}
pub async fn set_keys(
action_tx: &UnboundedSender<Action>,
api: &OnlineClient<CasperConfig>,
sender: &[u8; 32],
hashed_keys_str: &String,
maybe_nonce: Option<&mut u32>,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
let (gran_key, babe_key, audi_key, slow_key) = {
let s = hashed_keys_str.trim_start_matches("0x");
(
hex::decode(&s[0..64]).unwrap().as_slice().try_into().unwrap(),
hex::decode(&s[64..128]).unwrap().as_slice().try_into().unwrap(),
hex::decode(&s[128..192]).unwrap().as_slice().try_into().unwrap(),
hex::decode(&s[192..256]).unwrap().as_slice().try_into().unwrap(),
)
};
let session_keys = runtime_types::casper_runtime::opaque::SessionKeys {
grandpa: runtime_types::sp_consensus_grandpa::app::Public(gran_key),
babe: runtime_types::sp_consensus_babe::app::Public(babe_key),
authority_discovery: runtime_types::sp_authority_discovery::app::Public(audi_key),
slow_clap: runtime_types::ghost_slow_clap::sr25519::app_sr25519::Public(slow_key),
};
// it seems like there is no check for the second paramter, that's why
// we it can be anything. For example empty vector.
let set_keys_tx = casper_network::tx().session().set_keys(session_keys, Vec::new());
inner_sign_and_submit_then_watch(
action_tx,
api,
sender,
maybe_nonce,
Box::new(set_keys_tx),
"set keys",
ActionTarget::ValidatorLog,
).await
}
pub async fn validate(
action_tx: &UnboundedSender<Action>,
api: &OnlineClient<CasperConfig>,
sender: &[u8; 32],
percent: u32,
maybe_nonce: Option<&mut u32>,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
let validator_prefs = casper_network::runtime_types::pallet_staking::ValidatorPrefs {
commission: runtime_types::sp_arithmetic::per_things::Perbill(percent),
blocked: percent >= 1_000_000_000u32,
};
let validate_tx = casper_network::tx().staking().validate(validator_prefs);
inner_sign_and_submit_then_watch(
action_tx,
api,
sender,
maybe_nonce,
Box::new(validate_tx),
"validate",
ActionTarget::ValidatorLog,
).await
}
pub async fn chill(
action_tx: &UnboundedSender<Action>,
api: &OnlineClient<CasperConfig>,
sender: &[u8; 32],
maybe_nonce: Option<&mut u32>,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
let chill_tx = casper_network::tx().staking().chill();
inner_sign_and_submit_then_watch(
action_tx,
api,
sender,
maybe_nonce,
Box::new(chill_tx),
"chill",
ActionTarget::ValidatorLog,
).await
}
pub async fn unbond(
action_tx: &UnboundedSender<Action>,
api: &OnlineClient<CasperConfig>,
sender: &[u8; 32],
amount: &u128,
maybe_nonce: Option<&mut u32>,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
let unbond_tx = casper_network::tx().staking().unbond(*amount);
inner_sign_and_submit_then_watch(
action_tx,
api,
sender,
maybe_nonce,
Box::new(unbond_tx),
"unbond",
ActionTarget::ValidatorLog,
).await
}
pub async fn rebond(
action_tx: &UnboundedSender<Action>,
api: &OnlineClient<CasperConfig>,
sender: &[u8; 32],
amount: &u128,
maybe_nonce: Option<&mut u32>,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
let rebond_tx = casper_network::tx().staking().rebond(*amount);
inner_sign_and_submit_then_watch(
action_tx,
api,
sender,
maybe_nonce,
Box::new(rebond_tx),
"rebond",
ActionTarget::ValidatorLog,
).await
}
pub async fn withdraw_unbonded(
action_tx: &UnboundedSender<Action>,
api: &OnlineClient<CasperConfig>,
sender: &[u8; 32],
spans: &u32,
maybe_nonce: Option<&mut u32>,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
let withdraw_unbonded_tx = casper_network::tx().staking().withdraw_unbonded(*spans);
inner_sign_and_submit_then_watch(
action_tx,
api,
sender,
maybe_nonce,
Box::new(withdraw_unbonded_tx),
"withdraw unbonded",
ActionTarget::ValidatorLog,
).await
}
async fn inner_sign_and_submit_then_watch(
action_tx: &UnboundedSender<Action>,
api: &OnlineClient<CasperConfig>,
sender: &[u8; 32],
mut maybe_nonce: Option<&mut u32>,
tx_call: Box<dyn subxt::tx::Payload>,
tx_name: &str,
target: ActionTarget,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
let signer = PairSigner::<CasperConfig, Pair>::new(Pair::from_seed(sender));
let tx_params = match maybe_nonce {
Some(ref mut nonce) => {
**nonce = nonce.saturating_add(1);
CasperExtrinsicParamsBuilder::new()
.nonce(nonce.saturating_sub(1) as u64)
.build()
},
None => CasperExtrinsicParamsBuilder::new().build(),
};
match api
.tx()
.sign_and_submit_then_watch(&tx_call, &signer, tx_params)
.await {
Ok(tx_progress) => {
action_tx.send(Action::EventLog(
format!("{tx_name} transaction {} sent", tx_progress.extrinsic_hash()),
ActionLevel::Info,
target))?;
Ok(tx_progress)
},
Err(err) => {
action_tx.send(Action::EventLog(
format!("error during {tx_name} transaction: {err}"),
ActionLevel::Error,
target))?;
Err(err.into())
}
}
}