abstract_sdk/base/endpoints.rs
1//! # Endpoints
2//! This module provides endpoints for a base contract.
3//! Each endpoint is a trait that can be implemented by a base contract to support a specific endpoint.
4//!
5//! > *If you're not familiar with the concept of endpoints/entry points, please read the [CosmWasm documentation](https://book.cosmwasm.com/basics/entry-points.html).*
6//!
7//! Endpoints are similar to CosmWasm's entry points but are more opinionated and standardized.
8//! We'll go over all the available endpoints and their functionality and use-cases. But first, let's go over the message format expected by an Abstract module.
9//!
10//! ## Message format
11//! Each Abstract module accepts a fixed message format that can be customized by the developer to add their own functionality.
12//!
13//! The base message format is defined [here](abstract_std::base) as follows:
14//! ```rust
15//! use abstract_std::ibc::IbcResponseMsg;
16//! use cosmwasm_std::Empty;
17//!
18//! /// EndpointMsg to the Base.
19//! #[cosmwasm_schema::cw_serde]
20//! pub enum ExecuteMsg<BaseMsg, ModuleMsg, ReceiveMsg = Empty> {
21//! /// A base configuration message.
22//! Base(BaseMsg),
23//! /// An app request.
24//! Module(ModuleMsg),
25//! /// IbcReceive to process IBC callbacks
26//! IbcCallback(IbcResponseMsg),
27//! /// Receive endpoint for CW20 / external service integrations
28//! Receive(ReceiveMsg),
29//! }
30//!
31//! #[cosmwasm_schema::cw_serde]
32//! pub struct InstantiateMsg<BaseMsg, ModuleMsg = Empty> {
33//! /// base instantiate msg
34//! pub base: BaseMsg,
35//! /// custom instantiate msg
36//! pub app: ModuleMsg,
37//! }
38//!
39//! #[cosmwasm_schema::cw_serde]
40//! pub enum QueryMsg<BaseMsg, ModuleMsg = Empty> {
41//! /// A query message to the base.
42//! Base(BaseMsg),
43//! /// Custom query
44//! Module(ModuleMsg),
45//! }
46//!
47//! #[cosmwasm_schema::cw_serde]
48//! pub struct MigrateMsg<BaseMsg = Empty, ModuleMsg = Empty> {
49//! /// base migrate msg
50//! pub base: BaseMsg,
51//! /// custom migrate msg
52//! pub app: ModuleMsg,
53//! }
54//!
55//! ```
56//! Every `Base` variant or field is implemented by the base contract such as the [App](https://crates.io/crates/abstract-app) and [API](https://crates.io/crates/abstract-adapter) contracts.
57//! These contracts then expose a type that requires the missing `App` variant types to be provided. The rust type system
58//! is then smart enough to accept the correct message type for each custom endpoint.
59//!
60//! Lets have a look at the available endpoints.
61//!
62//! ## Execute
63//! The execute endpoint is the most common endpoint. A base contract implements it to handle its `Base` variant messages and forwards `App` or `Receive` variant messages to a custom execute handler.
64//! Here's the implementation for the App contract:
65//!
66//!
67//! ```rust,ignore
68//! use abstract_sdk::std::app::{ExecuteMsg, AppExecuteMsg};
69//! use abstract_app::{AppContract, AppError};
70//! # use abstract_sdk::base::ExecuteEndpoint;
71//! # use cosmwasm_std::{DepsMut, Env, MessageInfo, Response};
72//! # use schemars::JsonSchema;
73//! # use serde::Serialize;
74//!
75//! impl <Error: From<cosmwasm_std::StdError> + From<AppError> + 'static, CustomExecMsg: Serialize + JsonSchema + AppExecuteMsg, CustomInitMsg, CustomQueryMsg, CustomMigrateMsg, SudoMsg: Serialize + JsonSchema >
76//! ExecuteEndpoint for AppContract <Error, CustomInitMsg, CustomExecMsg, CustomQueryMsg, CustomMigrateMsg, SudoMsg > {
77//!
78//! // Expected entrypoint ExecuteMsg type, imported from abstract_std.
79//! // As you can see from the type definition, the `AppContract` accepts a custom `AppExecuteMsg`
80//! // type that is inserted into the expected execute message.
81//! type ExecuteMsg = ExecuteMsg<CustomExecMsg>;
82//!
83//! fn execute(
84//! self,
85//! deps: DepsMut,
86//! env: Env,
87//! info: MessageInfo,
88//! msg: Self::ExecuteMsg,
89//! ) -> Result<Response, Error> {
90//! // match message on base message format with help of the type system
91//! match msg {
92//! ExecuteMsg::Base(exec_msg) => self
93//! .base_execute(deps, env, info, exec_msg)
94//! .map_err(From::from),
95//! // handle the other messages with a custom handler set by the developer
96//! // by passing `self` to the handlers we expose all the features and Adapters that the base contract provides through the SDK.
97//! ExecuteMsg::App(request) => self.execute_handler()?(deps, env, info, self, request),
98//! ExecuteMsg::IbcCallback(msg) => self.ibc_callback(deps, env, info, msg),
99//!
100//! }
101//! }
102//! }
103//! ```
104//! Two variants reside in the ExecuteMsg enum:
105//!
106//! #### IbcCallback
107//! The IbcCallback endpoint is used to handle IBC responses that indicate that a certain IBC action has been completed.
108//!
109//!
110//! ## Instantiate
111//! The instantiate endpoint is used to initialize a base contract. It has a field for a custom `App` message that is passed to the instantiate handler.
112//!
113//! ## Query
114//! The query endpoint is used to query a contract. It is similar to the execute endpoint but it also forwards custom `App` variant queries.
115//!
116//! ## Migrate
117//! Same as the instantiate endpoint but for migrating a contract.
118//!
119//! ## Reply
120//! The reply endpoint is used to handle internal replies. Each reply handler is matched with a reply-id. Both are supplied to the contract builder.
121//!
122//! ## Sudo
123//! The sudo endpoint can only be called by the chain's governance address.
124
125mod execute;
126mod ibc_callback;
127mod instantiate;
128pub(crate) mod migrate;
129mod modules_ibc;
130mod query;
131mod reply;
132mod sudo;
133
134// Provide endpoints under ::base::traits::
135pub use execute::{CustomExecuteHandler, ExecuteEndpoint};
136pub use ibc_callback::IbcCallbackEndpoint;
137pub use instantiate::InstantiateEndpoint;
138pub use migrate::MigrateEndpoint;
139pub use modules_ibc::ModuleIbcEndpoint;
140pub use query::QueryEndpoint;
141pub use reply::ReplyEndpoint;
142pub use sudo::SudoEndpoint;