polytone_note/
contract.rs

1#[cfg(not(feature = "library"))]
2use cosmwasm_std::entry_point;
3use cosmwasm_std::{
4    to_binary, Binary, Deps, DepsMut, Env, IbcMsg, IbcTimeout, MessageInfo, Response, StdResult,
5};
6use cw2::set_contract_version;
7use polytone::callbacks::CallbackRequestType;
8use polytone::{accounts, callbacks, ibc};
9
10use crate::error::ContractError;
11
12use crate::ibc::ERR_GAS_NEEDED;
13use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, Pair, QueryMsg};
14use crate::state::{increment_sequence_number, BLOCK_MAX_GAS, CHANNEL, CONNECTION_REMOTE_PORT};
15
16const CONTRACT_NAME: &str = "crates.io:polytone-note";
17const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
18
19#[cfg_attr(not(feature = "library"), entry_point)]
20pub fn instantiate(
21    deps: DepsMut,
22    _env: Env,
23    _info: MessageInfo,
24    msg: InstantiateMsg,
25) -> Result<Response, ContractError> {
26    set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
27
28    if msg.block_max_gas.u64() <= ERR_GAS_NEEDED {
29        return Err(ContractError::GasLimitsMismatch);
30    }
31
32    BLOCK_MAX_GAS.save(deps.storage, &msg.block_max_gas.u64())?;
33
34    let mut response = Response::default()
35        .add_attribute("method", "instantiate")
36        .add_attribute("block_max_gas", msg.block_max_gas);
37
38    if let Some(Pair {
39        connection_id,
40        remote_port,
41    }) = msg.pair
42    {
43        response = response
44            .add_attribute("pair_connection", connection_id.to_string())
45            .add_attribute("pair_port", remote_port.to_string());
46        CONNECTION_REMOTE_PORT.save(deps.storage, &(connection_id, remote_port))?;
47    };
48
49    Ok(response)
50}
51
52#[cfg_attr(not(feature = "library"), entry_point)]
53pub fn execute(
54    deps: DepsMut,
55    env: Env,
56    info: MessageInfo,
57    msg: ExecuteMsg,
58) -> Result<Response, ContractError> {
59    let (msg, callback, timeout_seconds, request_type) = match msg {
60        ExecuteMsg::Execute {
61            msgs,
62            callback,
63            timeout_seconds,
64        } => (
65            ibc::Msg::Execute { msgs },
66            callback,
67            timeout_seconds,
68            CallbackRequestType::Execute,
69        ),
70        ExecuteMsg::Query {
71            msgs,
72            callback,
73            timeout_seconds,
74        } => (
75            ibc::Msg::Query { msgs },
76            Some(callback),
77            timeout_seconds,
78            CallbackRequestType::Query,
79        ),
80    };
81
82    let channel_id = CHANNEL
83        .may_load(deps.storage)?
84        .ok_or(ContractError::NoPair)?;
85
86    let sequence_number = increment_sequence_number(deps.storage, channel_id.clone())?;
87
88    callbacks::request_callback(
89        deps.storage,
90        deps.api,
91        channel_id.clone(),
92        sequence_number,
93        info.sender.clone(),
94        callback,
95        request_type,
96    )?;
97
98    accounts::on_send_packet(
99        deps.storage,
100        channel_id.clone(),
101        sequence_number,
102        &info.sender,
103    )?;
104
105    Ok(Response::default()
106        .add_attribute("method", "execute")
107        .add_message(IbcMsg::SendPacket {
108            channel_id,
109            data: to_binary(&ibc::Packet {
110                sender: info.sender.into_string(),
111                msg,
112            })
113            .expect("msgs are known to be serializable"),
114            timeout: IbcTimeout::with_timestamp(env.block.time.plus_seconds(timeout_seconds.u64())),
115        }))
116}
117
118#[cfg_attr(not(feature = "library"), entry_point)]
119pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
120    match msg {
121        QueryMsg::ActiveChannel => to_binary(&CHANNEL.may_load(deps.storage)?),
122        QueryMsg::Pair => to_binary(&CONNECTION_REMOTE_PORT.may_load(deps.storage)?.map(
123            |(connection_id, remote_port)| Pair {
124                connection_id,
125                remote_port,
126            },
127        )),
128        QueryMsg::RemoteAddress { local_address } => to_binary(&accounts::query_account(
129            deps.storage,
130            deps.api.addr_validate(&local_address)?,
131        )?),
132        QueryMsg::BlockMaxGas => to_binary(&BLOCK_MAX_GAS.load(deps.storage)?),
133    }
134}
135
136#[cfg_attr(not(feature = "library"), entry_point)]
137pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result<Response, ContractError> {
138    match msg {
139        MigrateMsg::WithUpdate { block_max_gas } => {
140            if block_max_gas.u64() <= ERR_GAS_NEEDED {
141                return Err(ContractError::GasLimitsMismatch);
142            }
143
144            BLOCK_MAX_GAS.save(deps.storage, &block_max_gas.u64())?;
145            Ok(Response::default()
146                .add_attribute("method", "migrate_with_update")
147                .add_attribute("block_max_gas", block_max_gas))
148        }
149    }
150}