use std::io::{self, Error, ErrorKind};
use crate::p as api_p;
use avalanche_types::{
avax,
ids::node,
key,
platformvm::{self, add_validator},
secp256k1fx,
};
use chrono::{DateTime, Utc};
use log::info;
impl<T> crate::wallet::Wallet<T>
where
T: key::ReadOnly + key::SignOnly + Clone,
{
pub async fn add_validator(
&self,
node_id: node::Id,
stake_amount: u64,
validate_start: DateTime<Utc>,
validate_end: DateTime<Utc>,
validate_reward_fee_percent: u32,
) -> io::Result<()> {
let already_validator = self.is_validator(&node_id).await?;
if already_validator {
return Err(Error::new(
ErrorKind::InvalidInput,
format!("node ID {} is already a validator", node_id),
));
}
info!("checking balance");
let cur_balance_p = self.get_balance_p().await?;
let add_validator_fee = 0_u64;
if cur_balance_p > stake_amount + add_validator_fee {
return Err(Error::new(
ErrorKind::InvalidInput,
format!("key address {} (balance {} nano-AVAX, network {}) does not have enough to cover stake amount + fee {}", self.p_address, cur_balance_p, self.network_name, stake_amount + add_validator_fee),
));
};
info!("checking stake inputs and outputs");
let (ins, unlocked_outs, locked_outs, signers) =
self.stake(stake_amount, add_validator_fee).await?;
let mut tx = add_validator::Tx {
unsigned_tx: avax::BaseTx {
network_id: self.network_id,
blockchain_id: self.p_chain_id,
transferable_outputs: Some(unlocked_outs),
transferable_inputs: Some(ins),
..Default::default()
},
validator: platformvm::Validator {
node_id,
start: validate_start.timestamp() as u64,
end: validate_end.timestamp() as u64,
weight: stake_amount,
},
stake_transferable_outputs: Some(locked_outs),
rewards_owner: secp256k1fx::OutputOwners {
locktime: 0,
threshold: 1,
addrs: vec![self.short_address.clone()],
},
shares: validate_reward_fee_percent * 10000,
..Default::default()
};
println!();
println!();
println!();
println!();
println!();
println!();
info!("signing tx");
tx.sign(signers)?;
println!();
println!();
println!();
let b = tx.unsigned_tx.metadata.unwrap().bytes;
let hb = hex::encode(&b);
let resp = api_p::issue_tx(&self.http_rpc_endpoint, &hb).await?;
info!("sent tx {:?}", resp);
println!();
println!();
println!();
println!();
println!();
println!();
println!();
println!();
println!();
Ok(())
}
}