Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["contracts/*", "packages/ibcmail", "tests"]
resolver = "2"

[workspace.package]
version = "0.2.0"
version = "0.3.0"

[workspace.dependencies]
cosmwasm-std = "1.5.3"
Expand All @@ -12,6 +12,7 @@ cw-controllers = "1.1.2"
cw-storage-plus = "1.2.0"
thiserror = "1.0.50"
cw-paginate = "0.2.1"
cw-item-set = "0.7.1"
schemars = "0.8"
cw-asset = "3.0.0"
cw-semver = { version = "1.0", features = ["serde"] }
Expand All @@ -20,14 +21,16 @@ cw-orch = "0.24.1"
ibcmail = { path = "packages/ibcmail", package = "ibcmail" }
client = { path = "contracts/client", package = "ibcmail-client" }
server = { path = "contracts/server", package = "ibcmail-server" }
abstract-client = "0.23.0"
abstract-app = "0.23.0"
abstract-adapter = "0.23.0"
abstract-interface = "0.23.0"

abstract-client = "=0.23.0"
abstract-app = "=0.23.0"
abstract-adapter = "=0.23.0"
abstract-interface = "0.23.1"

speculoos = "0.11.0"
semver = "1.0"
dotenv = "0.15.0"
env_logger = "0.10.0"
env_logger = "0.11.3"
clap = "4.3.7"
const_format = "0.2.32"

Expand Down
1 change: 0 additions & 1 deletion contracts/client/examples/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
//! $ just publish uni-6 osmo-test-5
//! ```

use abstract_app::objects::module::ModuleVersion;
use abstract_app::objects::namespace::Namespace;
use abstract_client::{AbstractClient, Publisher};
use clap::Parser;
Expand Down
1 change: 1 addition & 0 deletions contracts/client/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{dependencies::MAIL_SERVER_DEP, error::ClientError, handlers, APP_VER
pub type ClientResult<T = Response> = Result<T, ClientError>;

const APP: App = App::new(IBCMAIL_CLIENT_ID, APP_VERSION, None)
.with_instantiate(handlers::instantiate_handler)
.with_execute(handlers::execute_handler)
.with_query(handlers::query_handler)
.with_migrate(handlers::migrate_handler)
Expand Down
8 changes: 6 additions & 2 deletions contracts/client/src/dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use abstract_app::{objects::module::ModuleInfo, std::manager::ModuleInstallConfi
use ibcmail::IBCMAIL_SERVER_ID;

pub const MAIL_SERVER_DEP: StaticDependency =
StaticDependency::new(IBCMAIL_SERVER_ID, &[">=0.0.1"]);
StaticDependency::new(IBCMAIL_SERVER_ID, &[">=0.3.0"]);

#[cfg(feature = "interface")]
impl<Chain: cw_orch::environment::CwEnv> abstract_app::abstract_interface::DependencyCreation
Expand All @@ -21,6 +21,10 @@ impl<Chain: cw_orch::environment::CwEnv> abstract_app::abstract_interface::Depen
None,
);

Ok(vec![adapter_install_config])
// The IBC client is depended upon by the server
let ibc_client =
ModuleInstallConfig::new(ModuleInfo::from_id_latest("abstract:ibc-client")?, None);

Ok(vec![adapter_install_config, ibc_client])
}
}
121 changes: 82 additions & 39 deletions contracts/client/src/handlers/execute.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
use crate::{
contract::{App, ClientResult},
error::ClientError,
msg::ClientExecuteMsg,
};
use abstract_app::objects::TruncatedChainId;
use abstract_app::{
sdk::ModuleRegistryInterface,
traits::{AbstractResponse, AccountIdentification},
};
use base64::prelude::*;
use cosmwasm_std::{ensure_eq, CosmosMsg, Deps, DepsMut, Env, MessageInfo};
use cosmwasm_std::{ensure_eq, Addr, CosmosMsg, Deps, DepsMut, Env, MessageInfo};
use ibcmail::client::state::SENT_STATUS;
use ibcmail::{
client::{
state::{RECEIVED, SENT},
ClientApp,
},
server::api::{MailServer, ServerInterface},
IbcMailMessage, Message, Recipient, Route, Sender, IBCMAIL_SERVER_ID,
};

use crate::{
contract::{App, ClientResult},
error::ClientError,
msg::ClientExecuteMsg,
ClientMetadata, DeliveryStatus, Header, MailMessage, MessageHash, ReceivedMessage, Recipient,
Sender, IBCMAIL_SERVER_ID,
};

// # ANCHOR: execute_handler
Expand All @@ -29,10 +30,15 @@ pub fn execute_handler(
msg: ClientExecuteMsg,
) -> ClientResult {
match msg {
ClientExecuteMsg::SendMessage { message, route } => {
send_msg(deps, env, info, message, route, app)
ClientExecuteMsg::SendMessage {
message,
recipient,
metadata,
} => send_msg(deps, env, info, app, message, recipient, metadata),
ClientExecuteMsg::ReceiveMessage(message) => receive_msg(deps, info, app, message),
ClientExecuteMsg::UpdateDeliveryStatus { id, status } => {
update_delivery_status(deps, info, app, id, status)
}
ClientExecuteMsg::ReceiveMessage(message) => receive_msg(deps, info, message, app),
}
}
// # ANCHOR_END: execute_handler
Expand All @@ -42,60 +48,97 @@ fn send_msg(
deps: DepsMut,
env: Env,
_info: MessageInfo,
msg: Message,
route: Option<Route>,
app: ClientApp,
message: MailMessage,
recipient: Recipient,
metadata: Option<ClientMetadata>,
) -> ClientResult {
// validate basic fields of message, construct message to send to server
let to_hash = format!("{:?}{:?}{:?}", env.block.time, msg.subject, msg.recipient);
let to_hash = format!("{:?}{:?}{:?}", env.block.time, message.subject, recipient);
let hash = <sha2::Sha256 as sha2::Digest>::digest(to_hash);
let base_64_hash = BASE64_STANDARD.encode(hash);
let to_send = IbcMailMessage {

let sender = Sender::account(
app.account_id(deps.as_ref()).unwrap(),
Some(TruncatedChainId::new(&env)),
);
let version = app.version().to_string();

let client_header = Header {
sender,
recipient,
id: base_64_hash,
sender: Sender::account(
app.account_id(deps.as_ref()).unwrap(),
Some(TruncatedChainId::new(&env)),
),
message: Message {
recipient: msg.recipient,
subject: msg.subject,
body: msg.body,
},
version,
timestamp: env.block.time,
version: app.version().to_string(),
reply_to: None,
};

SENT.save(deps.storage, to_send.id.clone(), &to_send)?;
SENT.save(
deps.storage,
client_header.id.clone(),
&(message.clone(), client_header.clone()),
)?;

let server: MailServer<_> = app.mail_server(deps.as_ref());
let route_msg: CosmosMsg = server.process_msg(to_send, route)?;
let route_msg: CosmosMsg = server.process_msg(message, client_header, metadata)?;

Ok(app.response("send").add_message(route_msg))
}
// # ANCHOR_END: send_msg

/// Receive a message from the server
// # ANCHOR: receive_msg
fn receive_msg(deps: DepsMut, info: MessageInfo, msg: IbcMailMessage, app: App) -> ClientResult {
fn receive_msg(
deps: DepsMut,
info: MessageInfo,
app: App,
received: ReceivedMessage,
) -> ClientResult {
ensure_server_sender(deps.as_ref(), &app, info.sender)?;
ensure_correct_recipient(deps.as_ref(), &received.header.recipient, &app)?;

let msg_id = received.header.id.clone();
RECEIVED.save(deps.storage, msg_id.clone(), &received)?;

Ok(app
.response("received")
.add_attribute("message_id", &msg_id))
}
// # ANCHOR_END: receive_msg

fn update_delivery_status(
deps: DepsMut,
info: MessageInfo,
app: App,
id: MessageHash,
status: DeliveryStatus,
) -> ClientResult {
ensure_server_sender(deps.as_ref(), &app, info.sender)?;

// ensure that the message exists
SENT.load(deps.storage, id.clone())
.map_err(|_| ClientError::MessageNotFound(id.clone()))?;
SENT_STATUS.save(deps.storage, id.clone(), &status)?;

Ok(app
.response("update_msg_status")
.add_attribute("message_id", &id)
.add_attribute("status", status.to_string()))
}

fn ensure_server_sender(deps: Deps, app: &ClientApp, sender: Addr) -> Result<(), ClientError> {
let sender_module = app
.module_registry(deps.as_ref())?
.module_info(info.sender)
.module_registry(deps)?
.module_info(sender)
.map_err(|_| ClientError::NotMailServer {})?;

ensure_eq!(
sender_module.info.id(),
IBCMAIL_SERVER_ID,
ClientError::NotMailServer {}
);

ensure_correct_recipient(deps.as_ref(), &msg.message.recipient, &app)?;

RECEIVED.save(deps.storage, msg.id.clone(), &msg)?;

Ok(app
.response("received")
.add_attribute("message_id", &msg.id))
Ok(())
}
// # ANCHOR_END: receive_msg

fn ensure_correct_recipient(
deps: Deps,
Expand Down
24 changes: 24 additions & 0 deletions contracts/client/src/handlers/instantiate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::{
contract::{App, ClientResult},
CLIENT_FEATURES,
};
use abstract_app::traits::AbstractResponse;
use cosmwasm_std::{DepsMut, Env, MessageInfo};
use ibcmail::client::msg::ClientInstantiateMsg;
use ibcmail::client::state::FEATURES;

pub fn instantiate_handler(
deps: DepsMut,
_env: Env,
info: MessageInfo,
app: App,
_msg: ClientInstantiateMsg,
) -> ClientResult {
for feature in CLIENT_FEATURES {
FEATURES.save(deps.storage, feature.to_string(), &true)?;
}

Ok(app
.response("instantiate")
.add_attribute("features", CLIENT_FEATURES.join(",")))
}
4 changes: 3 additions & 1 deletion contracts/client/src/handlers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
pub mod execute;
pub mod instantiate;
pub mod migrate;
pub mod query;

pub use crate::handlers::{
execute::execute_handler, migrate::migrate_handler, query::query_handler,
execute::execute_handler, instantiate::instantiate_handler, migrate::migrate_handler,
query::query_handler,
};
Loading