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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//! # 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 [proxy](crate::proxy) 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 api structure is well-suited for implementing standard interfaces to external services like dexes, lending platforms, etc.

use cosmwasm_schema::QueryResponses;
use cosmwasm_std::{Addr, Binary};

use crate::{
    ibc_client::InstalledModuleIdentification,
    manager::{self, ModuleInstallConfig},
    objects::{account::AccountId, module::ModuleInfo, AssetEntry, TruncatedChainId},
};

pub mod state {
    use cw_storage_plus::{Item, Map};

    use super::*;
    use crate::objects::{ans_host::AnsHost, version_control::VersionControlContract};

    /// Maps a chain name to the proxy it uses to interact on this local chain
    pub const CHAIN_PROXIES: Map<&TruncatedChainId, Addr> = Map::new("ccl");
    pub const REVERSE_CHAIN_PROXIES: Map<&Addr, TruncatedChainId> = Map::new("rev-ccl");
    /// Configuration of the IBC host
    pub const CONFIG: Item<Config> = Item::new("cfg");

    // Temporary structure to hold actions to be executed after account creation
    pub const TEMP_ACTION_AFTER_CREATION: Item<ActionAfterCreationCache> = Item::new("act");

    /// The BaseState contains the main addresses needed for sending and verifying messages
    #[cosmwasm_schema::cw_serde]
    pub struct Config {
        /// AnsHost contract struct (address)
        pub ans_host: AnsHost,
        /// Address of the account factory, used to create remote accounts
        pub account_factory: Addr,
        /// Address of the local version control, for retrieving account information
        pub version_control: VersionControlContract,
    }

    #[cosmwasm_schema::cw_serde]
    pub struct ActionAfterCreationCache {
        pub client_proxy_address: String,
        pub account_id: AccountId,
        pub action: HostAction,
        pub chain_name: TruncatedChainId,
    }
}
/// Used by Abstract to instantiate the contract
/// The contract is then registered on the version control contract using [`crate::version_control::ExecuteMsg::ProposeModules`].
#[cosmwasm_schema::cw_serde]
pub struct InstantiateMsg {
    /// Used to easily perform address translation on the app chain
    pub ans_host_address: String,
    /// Used to create remote abstract accounts
    pub account_factory_address: String,
    /// Version control address
    pub version_control_address: String,
}

#[cosmwasm_schema::cw_serde]
pub struct MigrateMsg {}

// ANCHOR: ibc-host-action
#[cosmwasm_schema::cw_serde]
#[non_exhaustive]
pub enum InternalAction {
    /// Registers a new account from a remote chain
    Register {
        name: String,
        description: Option<String>,
        link: Option<String>,
        base_asset: Option<AssetEntry>,
        namespace: Option<String>,
        install_modules: Vec<ModuleInstallConfig>,
    },
}

#[cosmwasm_schema::cw_serde]
#[non_exhaustive]
pub enum HelperAction {
    /// What do we need here ? TODO
    SendAllBack,
}

/// Callable actions on a remote host
#[cosmwasm_schema::cw_serde]
pub enum HostAction {
    Dispatch {
        manager_msgs: Vec<manager::ExecuteMsg>,
    },
    /// Can't be called by an account directly. These are permissioned messages that only the IBC Client is allowed to call by itself.
    Internal(InternalAction),
    /// Some helpers that allow calling dispatch messages faster (for actions that are called regularly)
    Helpers(HelperAction),
}
// ANCHOR_END: ibc-host-action

/// Interface to the Host.
#[cosmwasm_schema::cw_serde]
#[derive(cw_orch::ExecuteFns)]
pub enum ExecuteMsg {
    UpdateOwnership(cw_ownable::Action),
    UpdateConfig {
        ans_host_address: Option<String>,
        account_factory_address: Option<String>,
        version_control_address: Option<String>,
    },
    /// Register the Polytone proxy for a specific chain.
    /// proxy should be a local address (will be validated)
    RegisterChainProxy {
        chain: TruncatedChainId,
        proxy: String,
    },
    /// Remove the Polytone proxy for a specific chain.
    RemoveChainProxy {
        chain: TruncatedChainId,
    },
    // ANCHOR: ibc-host-execute
    /// Allows for remote execution from the Polytone implementation
    #[cw_orch(fn_name("ibc_execute"))]
    Execute {
        account_id: AccountId,
        /// The address of the calling account id. This is used purely for the send-all-back method.
        /// We include it in all messages none-the-less to simplify the users life
        proxy_address: String,
        action: HostAction,
    },
    // ANCHOR_END: ibc-host-execute
    /// Performs an execution on a local module
    ModuleExecute {
        source_module: InstalledModuleIdentification,
        target_module: ModuleInfo,
        msg: Binary,
    },
}

/// Query Host message
#[cosmwasm_schema::cw_serde]
#[derive(QueryResponses, cw_orch::QueryFns)]
pub enum QueryMsg {
    /// Queries the ownership of the ibc client contract
    /// Returns [`cw_ownable::Ownership<Addr>`]
    #[returns(cw_ownable::Ownership<Addr> )]
    Ownership {},
    /// Returns [`ConfigResponse`].
    #[returns(ConfigResponse)]
    Config {},
    /// Lists all the polytone proxy contracts and their respective client chain registered with the host.
    /// Returns [`ClientProxiesResponse`].
    #[returns(ClientProxiesResponse)]
    ClientProxies {
        start_after: Option<String>,
        limit: Option<u32>,
    },
    /// Returns the polytone proxy contract address for a specific client chain.
    /// Returns [`ClientProxyResponse`].
    #[returns(ClientProxyResponse)]
    ClientProxy { chain: String },
    /// Performs an query on a local module
    #[returns(Binary)]
    ModuleQuery {
        target_module: InstalledModuleIdentification,
        msg: Binary,
    },
}

#[cosmwasm_schema::cw_serde]
pub struct ConfigResponse {
    pub ans_host_address: Addr,
    pub account_factory_address: Addr,
    pub version_control_address: Addr,
}

#[cosmwasm_schema::cw_serde]
pub struct ClientProxiesResponse {
    pub chains: Vec<(TruncatedChainId, Addr)>,
}

#[cosmwasm_schema::cw_serde]
pub struct ClientProxyResponse {
    pub proxy: Addr,
}