abstract_polytone_note/
contract.rs

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