use abstract_core::{
self,
objects::{
pool_id::UncheckedPoolAddress, PoolMetadata, UncheckedChannelEntry, UncheckedContractEntry,
},
};
use abstract_interface::{Abstract, ExecuteMsgFns};
use cw_asset::AssetInfoUnchecked;
use cw_orch::{deploy::Deploy, environment::CwEnv};
use crate::{
client::{AbstractClient, AbstractClientResult},
Environment,
};
use self::cw20_builder::Cw20Builder;
impl<Chain: CwEnv> AbstractClient<Chain> {
pub fn builder(chain: Chain) -> AbstractClientBuilder<Chain> {
AbstractClientBuilder::new(chain)
}
pub fn cw20_builder(
&self,
name: impl Into<String>,
symbol: impl Into<String>,
decimals: u8,
) -> Cw20Builder<Chain> {
Cw20Builder::new(self.environment(), name.into(), symbol.into(), decimals)
}
}
pub struct AbstractClientBuilder<Chain: CwEnv> {
chain: Chain,
contracts: Vec<(UncheckedContractEntry, String)>,
assets: Vec<(String, AssetInfoUnchecked)>,
channels: Vec<(UncheckedChannelEntry, String)>,
pools: Vec<(UncheckedPoolAddress, PoolMetadata)>,
}
impl<Chain: CwEnv> AbstractClientBuilder<Chain> {
pub(crate) fn new(chain: Chain) -> Self {
Self {
chain,
contracts: vec![],
assets: vec![],
channels: vec![],
pools: vec![],
}
}
pub fn contract(
&mut self,
contract_entry: UncheckedContractEntry,
address: impl Into<String>,
) -> &mut Self {
self.contracts.push((contract_entry, address.into()));
self
}
pub fn contracts(&mut self, contracts: Vec<(UncheckedContractEntry, String)>) -> &mut Self {
self.contracts = contracts;
self
}
pub fn asset(&mut self, name: impl Into<String>, asset_info: AssetInfoUnchecked) -> &mut Self {
self.assets.push((name.into(), asset_info));
self
}
pub fn assets(&mut self, assets: Vec<(String, AssetInfoUnchecked)>) -> &mut Self {
self.assets = assets;
self
}
pub fn channel(
&mut self,
channel_entry: UncheckedChannelEntry,
channel_value: impl Into<String>,
) -> &mut Self {
self.channels.push((channel_entry, channel_value.into()));
self
}
pub fn channels(&mut self, channels: Vec<(UncheckedChannelEntry, String)>) -> &mut Self {
self.channels = channels;
self
}
pub fn pool(
&mut self,
pool_address: UncheckedPoolAddress,
pool_metadata: PoolMetadata,
) -> &mut Self {
self.pools.push((pool_address, pool_metadata));
self
}
pub fn pools(&mut self, pools: Vec<(UncheckedPoolAddress, PoolMetadata)>) -> &mut Self {
self.pools = pools;
self
}
pub fn build(&self) -> AbstractClientResult<AbstractClient<Chain>> {
let abstr = Abstract::deploy_on(self.chain.clone(), self.chain.sender().into_string())?;
self.update_ans(&abstr)?;
AbstractClient::new(self.chain.clone())
}
fn update_ans(&self, abstr: &Abstract<Chain>) -> AbstractClientResult<()> {
abstr
.ans_host
.update_contract_addresses(self.contracts.clone(), vec![])?;
abstr
.ans_host
.update_asset_addresses(self.assets.clone(), vec![])?;
abstr
.ans_host
.update_channels(self.channels.clone(), vec![])?;
abstr.ans_host.update_pools(self.pools.clone(), vec![])?;
Ok(())
}
}
pub mod cw20_builder {
pub use cw20::{msg::Cw20ExecuteMsgFns, *};
pub use cw20_base::msg::{InstantiateMarketingInfo, QueryMsgFns as Cw20QueryMsgFns};
pub use cw_plus_interface::cw20_base::Cw20Base;
use cosmwasm_std::Addr;
use cw_orch::{
environment::CwEnv,
prelude::{CwOrchInstantiate, CwOrchUpload},
};
use cw_plus_interface::cw20_base::InstantiateMsg;
use crate::client::AbstractClientResult;
pub struct Cw20Builder<Chain: CwEnv> {
chain: Chain,
name: String,
symbol: String,
decimals: u8,
initial_balances: Vec<Cw20Coin>,
mint: Option<MinterResponse>,
marketing: Option<InstantiateMarketingInfo>,
admin: Option<Addr>,
}
impl<Chain: CwEnv> Cw20Builder<Chain> {
pub(crate) fn new(chain: Chain, name: String, symbol: String, decimals: u8) -> Self {
Self {
chain,
name,
symbol,
decimals,
initial_balances: vec![],
mint: None,
marketing: None,
admin: None,
}
}
pub fn initial_balance(&mut self, initial_balance: Cw20Coin) -> &mut Self {
self.initial_balances.push(initial_balance);
self
}
pub fn initial_balances(&mut self, initial_balances: Vec<Cw20Coin>) -> &mut Self {
self.initial_balances = initial_balances;
self
}
pub fn mint(&mut self, mint: MinterResponse) -> &mut Self {
self.mint = Some(mint);
self
}
pub fn marketing(&mut self, marketing: InstantiateMarketingInfo) -> &mut Self {
self.marketing = Some(marketing);
self
}
pub fn admin(&mut self, admin: impl Into<String>) -> &mut Self {
self.admin = Some(Addr::unchecked(admin.into()));
self
}
pub fn instantiate_with_id(&self, id: &str) -> AbstractClientResult<Cw20Base<Chain>> {
let cw20 = Cw20Base::new(id, self.chain.clone());
cw20.upload()?;
cw20.instantiate(
&InstantiateMsg {
decimals: self.decimals,
mint: self.mint.clone(),
symbol: self.symbol.clone(),
name: self.name.clone(),
initial_balances: self.initial_balances.clone(),
marketing: self.marketing.clone(),
},
self.admin.as_ref(),
None,
)?;
Ok(cw20)
}
}
}