use crate::{
sender::{Sender, SenderBuilder, SenderOptions},
DaemonAsyncBuilder,
};
use crate::{DaemonState, RUNTIME};
use bitcoin::secp256k1::All;
use cw_orch_core::environment::ChainInfoOwned;
use super::{super::error::DaemonError, core::Daemon};
#[derive(Clone, Default)]
pub struct DaemonBuilder {
pub(crate) chain: Option<ChainInfoOwned>,
pub(crate) handle: Option<tokio::runtime::Handle>,
pub(crate) deployment_id: Option<String>,
pub(crate) overwrite_grpc_url: Option<String>,
pub(crate) gas_denom: Option<String>,
pub(crate) gas_fee: Option<f64>,
pub(crate) state_path: Option<String>,
pub(crate) state: Option<DaemonState>,
pub(crate) write_on_change: Option<bool>,
pub(crate) sender: Option<SenderBuilder<All>>,
pub(crate) sender_options: SenderOptions,
}
impl DaemonBuilder {
pub fn chain(&mut self, chain: impl Into<ChainInfoOwned>) -> &mut Self {
self.chain = Some(chain.into());
self
}
pub fn deployment_id(&mut self, deployment_id: impl Into<String>) -> &mut Self {
self.deployment_id = Some(deployment_id.into());
self
}
pub fn handle(&mut self, handle: &tokio::runtime::Handle) -> &mut Self {
self.handle = Some(handle.clone());
self
}
pub fn mnemonic(&mut self, mnemonic: impl ToString) -> &mut Self {
self.sender = Some(SenderBuilder::Mnemonic(mnemonic.to_string()));
self
}
pub fn sender(&mut self, wallet: Sender<All>) -> &mut Self {
self.sender = Some(SenderBuilder::Sender(wallet));
self
}
pub fn authz_granter(&mut self, granter: impl ToString) -> &mut Self {
self.sender_options.set_authz_granter(granter.to_string());
self
}
pub fn fee_granter(&mut self, granter: impl ToString) -> &mut Self {
self.sender_options.set_fee_granter(granter.to_string());
self
}
pub fn hd_index(&mut self, index: u32) -> &mut Self {
self.sender_options.hd_index = Some(index);
self
}
pub fn grpc_url(&mut self, url: &str) -> &mut Self {
self.overwrite_grpc_url = Some(url.to_string());
self
}
pub fn gas(&mut self, gas_denom: Option<&str>, gas_fee: Option<f64>) -> &mut Self {
self.gas_denom = gas_denom.map(ToString::to_string);
self.gas_fee = gas_fee.map(Into::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
}
#[allow(unused)]
pub(crate) fn state_path(&mut self, path: impl ToString) -> &mut Self {
self.state_path = Some(path.to_string());
self
}
pub fn build(&self) -> Result<Daemon, DaemonError> {
let rt_handle = self
.handle
.clone()
.unwrap_or_else(|| RUNTIME.handle().clone());
let mut chain = self
.chain
.clone()
.ok_or(DaemonError::BuilderMissing("chain information".into()))?;
overwrite_fee(&mut chain, self.gas_denom.clone(), self.gas_fee);
overwrite_grpc_url(&mut chain, self.overwrite_grpc_url.clone());
let mut builder = self.clone();
builder.chain = Some(chain);
let daemon = rt_handle.block_on(DaemonAsyncBuilder::from(builder).build())?;
Ok(Daemon { rt_handle, daemon })
}
}
fn overwrite_fee(chain: &mut ChainInfoOwned, denom: Option<String>, amount: Option<f64>) {
if let Some(denom) = denom {
chain.gas_denom = denom.to_string()
}
chain.gas_price = amount.unwrap_or(chain.gas_price);
}
fn overwrite_grpc_url(chain: &mut ChainInfoOwned, grpc_url: Option<String>) {
if let Some(grpc_url) = grpc_url {
chain.grpc_urls = vec![grpc_url.to_string()]
}
}
#[cfg(test)]
mod test {
use cw_orch_core::environment::TxHandler;
use cw_orch_networks::networks::OSMOSIS_1;
use crate::DaemonBuilder;
pub const DUMMY_MNEMONIC:&str = "chapter wrist alcohol shine angry noise mercy simple rebel recycle vehicle wrap morning giraffe lazy outdoor noise blood ginger sort reunion boss crowd dutch";
#[test]
#[serial_test::serial]
fn grpc_override() {
let mut chain = OSMOSIS_1;
chain.grpc_urls = &[];
let daemon = DaemonBuilder::default()
.chain(chain)
.mnemonic(DUMMY_MNEMONIC)
.grpc_url(OSMOSIS_1.grpc_urls[0])
.build()
.unwrap();
assert_eq!(daemon.daemon.sender.chain_info.grpc_urls.len(), 1);
assert_eq!(
daemon.daemon.sender.chain_info.grpc_urls[0],
OSMOSIS_1.grpc_urls[0].to_string(),
);
}
#[test]
#[serial_test::serial]
fn fee_amount_override() {
let fee_amount = 1.3238763;
let daemon = DaemonBuilder::default()
.chain(OSMOSIS_1)
.mnemonic(DUMMY_MNEMONIC)
.gas(None, Some(fee_amount))
.build()
.unwrap();
println!("chain {:?}", daemon.daemon.sender.chain_info);
assert_eq!(daemon.daemon.sender.chain_info.gas_price, fee_amount);
}
#[test]
#[serial_test::serial]
fn fee_denom_override() {
let token = "my_token";
let daemon = DaemonBuilder::default()
.chain(OSMOSIS_1)
.mnemonic(DUMMY_MNEMONIC)
.gas(Some(token), None)
.build()
.unwrap();
assert_eq!(daemon.daemon.sender.chain_info.gas_denom, token.to_string());
}
#[test]
#[serial_test::serial]
fn fee_override() {
let fee_amount = 1.3238763;
let token = "my_token";
let daemon = DaemonBuilder::default()
.chain(OSMOSIS_1)
.mnemonic(DUMMY_MNEMONIC)
.gas(Some(token), Some(fee_amount))
.build()
.unwrap();
assert_eq!(daemon.daemon.sender.chain_info.gas_denom, token.to_string());
assert_eq!(daemon.daemon.sender.chain_info.gas_price, fee_amount);
}
#[test]
#[serial_test::serial]
fn hd_index_re_generates_sender() -> anyhow::Result<()> {
let daemon = DaemonBuilder::default()
.chain(OSMOSIS_1)
.mnemonic(DUMMY_MNEMONIC)
.build()
.unwrap();
let indexed_daemon = daemon.rebuild().hd_index(56).build().unwrap();
assert_ne!(
daemon.sender().to_string(),
indexed_daemon.sender().to_string()
);
Ok(())
}
}