abstract_client/
service.rs

1//! # Represents Abstract Service
2//!
3//! [`Service`] represents a module registered in registry
4
5use std::marker::PhantomData;
6
7use abstract_interface::{RegisteredModule, Registry};
8use abstract_std::objects::{module::ModuleInfo, module_reference::ModuleReference};
9use cw_orch::{contract::Contract, prelude::*};
10
11use crate::{client::AbstractClientResult, Application};
12
13/// A `Service` represents a contract registered in registry.
14///
15/// `Service`s should be created from [`Application`]s using the `into_service` method.
16/// They can then be registered using the `service.deploy()` method.
17//
18// It implements cw-orch traits of the module itself, so you can call its methods directly from the service struct.
19#[derive(Clone)]
20pub struct Service<T: CwEnv, M> {
21    module: M,
22    chain: PhantomData<T>,
23}
24
25/// Allows to access the module's methods directly from the service struct
26impl<Chain: CwEnv, M: InstantiableContract + ContractInstance<Chain>> InstantiableContract
27    for Service<Chain, M>
28{
29    type InstantiateMsg = M::InstantiateMsg;
30}
31
32impl<Chain: CwEnv, M: QueryableContract + ContractInstance<Chain>> QueryableContract
33    for Service<Chain, M>
34{
35    type QueryMsg = M::QueryMsg;
36}
37
38impl<Chain: CwEnv, M: ExecutableContract + ContractInstance<Chain>> ExecutableContract
39    for Service<Chain, M>
40{
41    type ExecuteMsg = M::ExecuteMsg;
42}
43
44impl<Chain: CwEnv, M: ContractInstance<Chain>> ContractInstance<Chain> for Service<Chain, M> {
45    fn as_instance(&self) -> &Contract<Chain> {
46        self.module.as_instance()
47    }
48
49    fn as_instance_mut(&mut self) -> &mut Contract<Chain> {
50        self.module.as_instance_mut()
51    }
52}
53
54impl<Chain: CwEnv, M: RegisteredModule + From<Contract<Chain>>> Service<Chain, M> {
55    /// Get module interface installed from registry
56    pub(crate) fn new(registry: &Registry<Chain>) -> AbstractClientResult<Self> {
57        // The module must be in registry and service
58        let module_reference: ModuleReference = registry
59            .module(ModuleInfo::from_id(
60                M::module_id(),
61                abstract_std::objects::module::ModuleVersion::Version(
62                    M::module_version().to_owned(),
63                ),
64            )?)?
65            .reference;
66        let ModuleReference::Service(service_addr) = module_reference else {
67            return Err(crate::AbstractClientError::ExpectedService {});
68        };
69
70        // Ensure using correct address
71        let contract = Contract::new(M::module_id(), registry.environment().clone());
72        contract.set_address(&service_addr);
73
74        Ok(Self {
75            module: contract.into(),
76            chain: PhantomData {},
77        })
78    }
79}
80
81impl<T: CwEnv, M> From<Application<T, M>> for Service<T, M> {
82    fn from(value: Application<T, M>) -> Self {
83        Self {
84            module: value.module,
85            chain: PhantomData::<T> {},
86        }
87    }
88}