use std::sync::Arc;
use crate::{
log::print_if_log_disabled,
network_config,
senders::{builder::SenderBuilder, CosmosOptions, CosmosWalletKey},
DaemonAsyncBase, DaemonBuilder, DaemonStateFile, Wallet,
};
use super::{error::DaemonError, state::DaemonState};
use cw_orch_core::environment::ChainInfoOwned;
pub const DEFAULT_DEPLOYMENT: &str = "default";
#[derive(Clone)]
pub struct DaemonAsyncBuilder {
pub(crate) chain: ChainInfoOwned,
pub(crate) deployment_id: Option<String>,
pub(crate) state_path: Option<String>,
pub(crate) state: Option<DaemonState>,
pub(crate) write_on_change: Option<bool>,
pub(crate) is_test: bool,
pub(crate) load_network: bool,
pub(crate) mnemonic: Option<String>,
}
impl DaemonAsyncBuilder {
pub fn new(chain: impl Into<ChainInfoOwned>) -> Self {
Self {
chain: chain.into(),
deployment_id: None,
state_path: None,
state: None,
write_on_change: None,
mnemonic: None,
is_test: false,
load_network: true,
}
}
pub fn deployment_id(&mut self, deployment_id: impl Into<String>) -> &mut Self {
self.deployment_id = Some(deployment_id.into());
self
}
pub fn state(&mut self, state: DaemonState) -> &mut Self {
self.state = Some(state);
self
}
pub fn write_on_change(&mut self, write_on_change: bool) -> &mut Self {
self.write_on_change = Some(write_on_change);
self
}
pub fn mnemonic(&mut self, mnemonic: impl Into<String>) -> &mut Self {
self.mnemonic = Some(mnemonic.into());
self
}
pub fn chain(&mut self, chain: impl Into<ChainInfoOwned>) -> &mut Self {
self.chain = chain.into();
self
}
pub fn is_test(&mut self, is_test: bool) -> &mut Self {
self.is_test = is_test;
self
}
pub fn load_network(&mut self, load_network: bool) -> &mut Self {
self.load_network = load_network;
self
}
#[allow(unused)]
pub(crate) fn state_path(&mut self, path: impl ToString) -> &mut Self {
self.state_path = Some(path.to_string());
self
}
pub async fn build(&self) -> Result<DaemonAsyncBase<Wallet>, DaemonError> {
let mut chain_info = self.chain.clone();
if self.load_network {
if let Some(network_config) = network_config::read_network_config(&chain_info.chain_id)
{
chain_info = chain_info.overwrite_with(network_config)
}
}
let chain_info = Arc::new(chain_info);
let state = self.build_state(chain_info.clone())?;
let options = CosmosOptions {
key: self.mnemonic.as_ref().map_or(CosmosWalletKey::Env, |m| {
CosmosWalletKey::Mnemonic(m.clone())
}),
..Default::default()
};
let sender = options.build(&chain_info).await?;
let daemon = DaemonAsyncBase::new(sender, state);
print_if_log_disabled()?;
Ok(daemon)
}
pub async fn build_sender<T: SenderBuilder>(
&self,
sender_options: T,
) -> Result<DaemonAsyncBase<T::Sender>, DaemonError> {
let mut chain_info = self.chain.clone();
if self.load_network {
if let Some(network_config) = network_config::read_network_config(&chain_info.chain_id)
{
chain_info = chain_info.overwrite_with(network_config)
}
}
let chain_info = Arc::new(chain_info);
let state = self.build_state(chain_info.clone())?;
let sender = sender_options
.build(&chain_info)
.await
.map_err(Into::into)?;
let daemon = DaemonAsyncBase::new(sender, state);
print_if_log_disabled()?;
Ok(daemon)
}
fn build_state(&self, chain_info: Arc<ChainInfoOwned>) -> Result<DaemonState, DaemonError> {
let deployment_id = self
.deployment_id
.clone()
.unwrap_or(DEFAULT_DEPLOYMENT.to_string());
let state = match &self.state {
Some(state) => {
let mut state = state.clone();
state.chain_data = chain_info;
state.deployment_id = deployment_id;
if let Some(write_on_change) = self.write_on_change {
state.write_on_change = write_on_change;
}
if let DaemonStateFile::FullAccess { json_file_state } = &state.json_state {
let mut json_file_lock = json_file_state.lock().unwrap();
json_file_lock.prepare(&state.chain_data.chain_id, &state.deployment_id);
if state.write_on_change {
json_file_lock.force_write();
}
}
state
}
None => {
let json_file_path = match &self.state_path {
Some(path) => path.clone(),
None => {
if self.is_test {
crate::gen_temp_file_path()
.into_os_string()
.into_string()
.unwrap()
} else {
DaemonState::state_file_path()?
}
}
};
DaemonState::new(
json_file_path,
&chain_info,
deployment_id,
false,
self.write_on_change.unwrap_or(true),
)?
}
};
Ok(state)
}
}
impl From<DaemonBuilder> for DaemonAsyncBuilder {
fn from(value: DaemonBuilder) -> Self {
DaemonAsyncBuilder {
chain: value.chain,
deployment_id: value.deployment_id,
state: value.state,
state_path: value.state_path,
write_on_change: value.write_on_change,
mnemonic: value.mnemonic,
is_test: value.is_test,
load_network: value.load_network,
}
}
}