abstract_std/
adapter.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//! # Abstract Api Base
//!
//! `abstract_std::adapter` implements shared functionality that's useful for creating new Abstract adapters.
//!
//! ## Description
//! An Abstract adapter contract is a contract that is allowed to perform actions on a [account](crate::account) contract.
//! It is not migratable and its functionality is shared between users, meaning that all users call the same contract address to perform operations on the Account.
//! The adapter structure is well-suited for implementing standard interfaces to external services like dexes, lending platforms, etc.

use cosmwasm_schema::QueryResponses;
use cosmwasm_std::{Addr, Empty};
use serde::Serialize;

use crate::{
    base::{
        ExecuteMsg as MiddlewareExecMsg, InstantiateMsg as MiddlewareInstantiateMsg,
        QueryMsg as MiddlewareQueryMsg,
    },
    objects::module_version::ModuleDataResponse,
};

pub type ExecuteMsg<Request = Empty> =
    MiddlewareExecMsg<BaseExecuteMsg, AdapterRequestMsg<Request>>;
pub type QueryMsg<ModuleMsg = Empty> = MiddlewareQueryMsg<BaseQueryMsg, ModuleMsg>;
pub type InstantiateMsg<ModuleMsg = Empty> =
    MiddlewareInstantiateMsg<BaseInstantiateMsg, ModuleMsg>;

/// Trait indicates that the type is used as an app message
/// in the [`ExecuteMsg`] enum.
/// Enables [`Into<ExecuteMsg>`] for BOOT fn-generation support.
pub trait AdapterExecuteMsg: Serialize {}
impl<T: AdapterExecuteMsg> From<T> for ExecuteMsg<T> {
    fn from(request: T) -> Self {
        Self::Module(AdapterRequestMsg {
            account_address: None,
            request,
        })
    }
}

impl AdapterExecuteMsg for Empty {}

/// Trait indicates that the type is used as an api message
/// in the [`QueryMsg`] enum.
/// Enables [`Into<QueryMsg>`] for BOOT fn-generation support.
pub trait AdapterQueryMsg: Serialize {}

impl<T: AdapterQueryMsg> From<T> for QueryMsg<T> {
    fn from(module: T) -> Self {
        Self::Module(module)
    }
}

impl AdapterQueryMsg for Empty {}

/// Used by Abstract to instantiate the contract
/// The contract is then registered on the registry contract using [`crate::registry::ExecuteMsg::ProposeModules`].
#[cosmwasm_schema::cw_serde]
pub struct BaseInstantiateMsg {
    pub registry_address: String,
}

impl<RequestMsg> From<BaseExecuteMsg> for MiddlewareExecMsg<BaseExecuteMsg, RequestMsg> {
    fn from(adapter_msg: BaseExecuteMsg) -> Self {
        Self::Base(adapter_msg)
    }
}

impl<RequestMsg, BaseExecMsg> From<AdapterRequestMsg<RequestMsg>>
    for MiddlewareExecMsg<BaseExecMsg, AdapterRequestMsg<RequestMsg>>
{
    fn from(request_msg: AdapterRequestMsg<RequestMsg>) -> Self {
        Self::Module(request_msg)
    }
}

/// An adapter request.
/// If account is None, then the sender must be an Account.
#[cosmwasm_schema::cw_serde]
pub struct AdapterRequestMsg<Request> {
    pub account_address: Option<String>,
    /// The actual request
    pub request: Request,
}

impl<Request: Serialize> AdapterRequestMsg<Request> {
    pub fn new(account_address: Option<String>, request: Request) -> Self {
        Self {
            account_address,
            request,
        }
    }
}

// serde attributes remain it compatible with previous versions in cases where account_address is omitted
#[cosmwasm_schema::cw_serde]
pub struct BaseExecuteMsg {
    /// The account address for which to apply the configuration
    /// If None, the sender must be an Account
    /// If Some, the sender must be a direct or indirect owner (through sub-accounts) of the specified account.
    pub account_address: Option<String>,
    // The actual base message
    pub msg: AdapterBaseMsg,
}

/// Configuration message for the adapter
#[cosmwasm_schema::cw_serde]
pub enum AdapterBaseMsg {
    /// Add or remove authorized addresses
    /// If an authorized address is both in to_add and to_remove, it will be removed.
    UpdateAuthorizedAddresses {
        to_add: Vec<String>,
        to_remove: Vec<String>,
    },
}

/// Query adapter message
#[cosmwasm_schema::cw_serde]
#[derive(QueryResponses, cw_orch::QueryFns)]
pub enum BaseQueryMsg {
    /// Returns [`AdapterConfigResponse`].
    #[returns(AdapterConfigResponse)]
    BaseConfig {},
    /// Returns [`AuthorizedAddressesResponse`].
    #[returns(AuthorizedAddressesResponse)]
    AuthorizedAddresses { account_address: String },
    /// Returns module data
    /// Returns [`ModuleDataResponse`].
    #[returns(ModuleDataResponse)]
    ModuleData {},
}

impl<T> From<BaseQueryMsg> for QueryMsg<T> {
    fn from(base: BaseQueryMsg) -> Self {
        Self::Base(base)
    }
}

#[cosmwasm_schema::cw_serde]
pub struct AdapterConfigResponse {
    pub registry_address: Addr,
    pub ans_host_address: Addr,
    pub dependencies: Vec<String>,
}

#[cosmwasm_schema::cw_serde]
pub struct AuthorizedAddressesResponse {
    /// Contains all authorized addresses
    pub addresses: Vec<Addr>,
}

/// The BaseState contains the main addresses needed for sending and verifying messages
/// Every DApp should use the provided **ans_host** contract for token/contract address resolution.
#[cosmwasm_schema::cw_serde]
pub struct AdapterState {
    /// Code id of abstract contract
    pub code_id: u64,
}