use core::time::Duration;
use eyre::eyre;
use std::fs;
use std::process::{Command, Stdio};
use std::str;
use std::thread::sleep;
use crate::chain::exec::simple_exec;
use crate::error::Error;
use crate::types::process::ChildProcess;
use crate::util::file::pipe_to_file;
pub fn initialize(chain_id: &str, command_path: &str, home_path: &str) -> Result<(), Error> {
simple_exec(
chain_id,
command_path,
&[
"--home",
home_path,
"--chain-id",
chain_id,
"init",
chain_id,
],
)?;
Ok(())
}
pub fn add_wallet(
chain_id: &str,
command_path: &str,
home_path: &str,
wallet_id: &str,
) -> Result<String, Error> {
let output = simple_exec(
chain_id,
command_path,
&[
"--home",
home_path,
"keys",
"add",
wallet_id,
"--keyring-backend",
"test",
"--output",
"json",
],
)?;
if output.stdout.is_empty() {
Ok(output.stderr)
} else {
Ok(output.stdout)
}
}
pub fn add_genesis_account(
chain_id: &str,
command_path: &str,
home_path: &str,
wallet_address: &str,
amounts: &[String],
) -> Result<(), Error> {
let amounts_str = itertools::join(amounts, ",");
simple_exec(
chain_id,
command_path,
&[
"--home",
home_path,
"add-genesis-account",
wallet_address,
&amounts_str,
],
)?;
Ok(())
}
pub fn add_genesis_validator(
chain_id: &str,
command_path: &str,
home_path: &str,
wallet_id: &str,
amount: &str,
) -> Result<(), Error> {
simple_exec(
chain_id,
command_path,
&[
"--home",
home_path,
"gentx",
wallet_id,
"--keyring-backend",
"test",
"--chain-id",
chain_id,
amount,
],
)?;
Ok(())
}
pub fn collect_gen_txs(chain_id: &str, command_path: &str, home_path: &str) -> Result<(), Error> {
simple_exec(
chain_id,
command_path,
&["--home", home_path, "collect-gentxs"],
)?;
Ok(())
}
pub fn start_chain(
command_path: &str,
home_path: &str,
rpc_listen_address: &str,
grpc_listen_address: &str,
extra_start_args: &[&str],
) -> Result<ChildProcess, Error> {
let base_args = [
"--home",
home_path,
"start",
"--pruning",
"nothing",
"--grpc.address",
grpc_listen_address,
"--rpc.laddr",
rpc_listen_address,
];
let mut args: Vec<&str> = base_args.to_vec();
args.extend(extra_start_args.iter());
let mut child = Command::new(command_path)
.args(&args)
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
let stdout = child
.stdout
.take()
.ok_or_else(|| eyre!("expected stdout to be present in child process"))?;
let stderr = child
.stderr
.take()
.ok_or_else(|| eyre!("expected stderr to be present in child process"))?;
let stderr_path = format!("{home_path}/stdout.log");
let stdout_path = format!("{home_path}/stderr.log");
pipe_to_file(stdout, &stdout_path)?;
pipe_to_file(stderr, &stderr_path)?;
sleep(Duration::from_millis(1000));
let status = child
.try_wait()
.map_err(|e| eyre!("error try waiting for child status: {}", e))?;
match status {
None => Ok(ChildProcess::new(child)),
Some(status) => {
let stdout_output = fs::read_to_string(stdout_path)?;
let stderr_output = fs::read_to_string(stderr_path)?;
Err(eyre!(
"expected full node process to be running, but it exited immediately with exit status {} and output: {}\n{}",
status,
stdout_output,
stderr_output,
).into())
}
}
}