use abstract_interface::{AccountExecFns, RegisteredModule};
use abstract_std::objects::module::ModuleInfo;
use cosmwasm_std::to_json_binary;
use cw_orch::{contract::Contract, prelude::*};
use crate::{account::Account, client::AbstractClientResult, Service};
#[derive(Clone)]
pub struct Application<T: CwEnv, M> {
pub(crate) account: Account<T>,
pub(crate) module: M,
}
impl<Chain: CwEnv, M: InstantiableContract + ContractInstance<Chain>> InstantiableContract
for Application<Chain, M>
{
type InstantiateMsg = M::InstantiateMsg;
}
impl<Chain: CwEnv, M: QueryableContract + ContractInstance<Chain>> QueryableContract
for Application<Chain, M>
{
type QueryMsg = M::QueryMsg;
}
impl<Chain: CwEnv, M: ExecutableContract + ContractInstance<Chain>> ExecutableContract
for Application<Chain, M>
{
type ExecuteMsg = M::ExecuteMsg;
}
impl<Chain: CwEnv, M: MigratableContract + ContractInstance<Chain>> MigratableContract
for Application<Chain, M>
{
type MigrateMsg = M::MigrateMsg;
}
impl<Chain: CwEnv, M: ContractInstance<Chain>> ContractInstance<Chain> for Application<Chain, M> {
fn as_instance(&self) -> &Contract<Chain> {
self.module.as_instance()
}
fn as_instance_mut(&mut self) -> &mut Contract<Chain> {
self.module.as_instance_mut()
}
}
impl<Chain: CwEnv, M: RegisteredModule> Application<Chain, M> {
pub(crate) fn new(account: Account<Chain>, module: M) -> AbstractClientResult<Self> {
account.module_addresses(vec![M::module_id().to_string()])?;
Ok(Self { account, module })
}
pub fn account(&self) -> &Account<Chain> {
&self.account
}
pub fn module<T: RegisteredModule + From<Contract<Chain>>>(&self) -> AbstractClientResult<T> {
self.account.module()
}
pub fn into_service(self) -> Service<Chain, M> {
Service::from(self)
}
}
impl<Chain: CwEnv, M: RegisteredModule + MigratableContract> Application<Chain, M> {
pub fn upgrade(&self, migrate_msg: Option<&M::MigrateMsg>) -> AbstractClientResult<()> {
let module = ModuleInfo::from_id(M::module_id(), M::module_version().into())?;
if !self.account.module_version_installed(module.clone())? {
self.account.abstr_account.upgrade(vec![(
module,
migrate_msg.map(|msg| to_json_binary(msg).unwrap()),
)])?;
}
Ok(())
}
}
impl<Chain: CwEnv, M: ContractInstance<Chain>> Application<Chain, M> {
pub fn authorize_on_adapters(&self, adapter_ids: &[&str]) -> AbstractClientResult<()> {
for module_id in adapter_ids {
self.account
.abstr_account
.update_adapter_authorized_addresses(module_id, vec![self.addr_str()?], vec![])?;
}
Ok(())
}
}