Skip to content

Commit

Permalink
simplified ping-pong
Browse files Browse the repository at this point in the history
  • Loading branch information
Buckram123 committed Oct 31, 2024
1 parent 601c538 commit 66ea405
Show file tree
Hide file tree
Showing 23 changed files with 651 additions and 7 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ cw-asset = { version = "4.0.0" }
abstract-app = { version = "0.24.1" }
abstract-adapter = { version = "0.24.1" }
abstract-standalone = { version = "0.24.1" }
abstract-interface = { version = "0.24.1" }
abstract-client = { version = "0.24.1" }
cw-orch = { version = "0.27.0" }
{% if include_ibc_app %}
Expand Down
1 change: 0 additions & 1 deletion contracts/{{adapter_name}}/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ const_format = { workspace = true }

# Dependencies for interface
cw-orch = { workspace = true }
abstract-interface = { workspace = true }

# Dependencies for bins
clap = { workspace = true, optional = true, features = ["derive"] }
Expand Down
1 change: 0 additions & 1 deletion contracts/{{app_name}}/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ const_format = { workspace = true }

# Dependencies for interface
cw-orch = { workspace = true }
abstract-interface = { workspace = true }

# Dependencies for bins
clap = { workspace = true, optional = true, features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion contracts/{{app_name}}/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ abstract_app::cw_orch_interface!(APP, {{app_name | upper_camel_case}}, {{app_nam
// TODO: add to docmuentation
// https://linear.app/abstract-sdk/issue/ABS-414/add-documentation-on-dependencycreation-trait
#[cfg(not(target_arch = "wasm32"))]
impl<Chain: cw_orch::environment::CwEnv> abstract_interface::DependencyCreation
impl<Chain: cw_orch::environment::CwEnv> abstract_app::abstract_interface::DependencyCreation
for crate::{{app_name | upper_camel_case}}Interface<Chain>
{
type DependenciesConfig = cosmwasm_std::Empty;
Expand Down
50 changes: 50 additions & 0 deletions contracts/{{ibc_app_name}}/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[package]
name = "ping-pong"
version = "0.1.0"
edition = "2021"

[features]
default = ["export"]
export = []
daemon-bin = [
"cw-orch/daemon",
"dep:clap",
"dep:abstract-client",
"dep:dotenv",
"dep:env_logger",
]
schema = ["abstract-app/schema"]

[lib]
crate-type = ["cdylib", "rlib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cosmwasm-std = { workspace = true }
cosmwasm-schema = { workspace = true }
cw-controllers = { workspace = true }
cw-storage-plus = { workspace = true }
thiserror = { workspace = true }
schemars = { workspace = true }
cw-asset = { workspace = true }
abstract-app = { workspace = true }
abstract-ibc-client = { version = "0.24.1", default-features = false }
const_format = { workspace = true }

# Dependencies for interface
cw-orch = { workspace = true }
abstract-interface = { workspace = true }

# Dependencies for bins
clap = { workspace = true, optional = true, features = ["derive"] }
abstract-client = { workspace = true, features = [
"interchain",
], optional = true }
dotenv = { workspace = true, optional = true }
env_logger = { workspace = true, optional = true }

[dev-dependencies]
cw-orch-interchain = { workspace = true, features = ["daemon"] }
cw-orch = { workspace = true, features = ["daemon"] }
abstract-client = { workspace = true, features = ["interchain"] }
env_logger = "0.11"
9 changes: 9 additions & 0 deletions contracts/{{ibc_app_name}}/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "MyIbcApp",
"description": "IBC app description.",
"website": "",
"docs": "",
"type": "app",
"icon": "GiTrade",
"enabled": true
}
65 changes: 65 additions & 0 deletions contracts/{{ibc_app_name}}/src/bin/publish.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//! Publishes the module to the Abstract platform by uploading it and registering it on the app store.
//!
//! Info: The mnemonic used to register the module must be the same as the owner of the account that claimed the namespace.
//!
//! ## Example
//!
//! ```bash
//! $ just publish test-app uni-6 osmo-test-5
//! ```
use ping_pong::PING_PONG_ID;

use abstract_app::objects::namespace::Namespace;
use abstract_client::{AbstractClient, Publisher};
use clap::Parser;
use cw_orch::{anyhow, daemon::networks::parse_network, prelude::*, tokio::runtime::Runtime};
use ping_pong::PingPongInterface;

fn publish(networks: Vec<ChainInfo>) -> anyhow::Result<()> {
// run for each requested network
for network in networks {
// Setup
let rt = Runtime::new()?;
let chain = DaemonBuilder::new(network).handle(rt.handle()).build()?;

let app_namespace = Namespace::from_id(PING_PONG_ID)?;

// Create an [`AbstractClient`]
let abstract_client: AbstractClient<Daemon> = AbstractClient::new(chain.clone())?;

// Get the [`Publisher`] that owns the namespace, otherwise create a new one and claim the namespace
let publisher: Publisher<_> = abstract_client
.account_builder()
.namespace(app_namespace)
.build()?
.publisher()?;

if publisher.account().owner()? != chain.sender_addr() {
panic!("The current sender can not publish to this namespace. Please use the wallet that owns the Account that owns the Namespace.")
}

// Publish the App to the Abstract Platform
publisher.publish_app::<PingPongInterface<Daemon>>()?;
}
Ok(())
}

#[derive(Parser, Default, Debug)]
#[command(author, version, about, long_about = None)]
struct Arguments {
/// Network Id to publish on
#[arg(short, long, value_delimiter = ' ', num_args = 1..)]
network_ids: Vec<String>,
}

fn main() {
dotenv::dotenv().ok();
env_logger::init();
let args = Arguments::parse();
let networks = args
.network_ids
.iter()
.map(|n| parse_network(n).unwrap())
.collect();
publish(networks).unwrap();
}
13 changes: 13 additions & 0 deletions contracts/{{ibc_app_name}}/src/bin/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use cosmwasm_schema::remove_schemas;
use ping_pong::contract::PingPong;
use std::env::current_dir;
use std::fs::create_dir_all;

fn main() {
let mut out_dir = current_dir().unwrap();
out_dir.push("schema");
create_dir_all(&out_dir).unwrap();
remove_schemas(&out_dir).unwrap();

PingPong::export_schema(&out_dir);
}
60 changes: 60 additions & 0 deletions contracts/{{ibc_app_name}}/src/contract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use abstract_app::{objects::dependency::StaticDependency, std::IBC_CLIENT, AppContract};
use cosmwasm_std::Response;

use crate::{
error::PingPongError,
handlers, ibc,
msg::{AppMigrateMsg, PingPongExecuteMsg, PingPongInstantiateMsg, PingPongQueryMsg},
APP_VERSION, PING_PONG_ID,
};

/// The type of the result returned by your app's entry points.
pub type PingPongResult<T = Response> = Result<T, PingPongError>;

/// The type of the app that is used to build your app and access the Abstract SDK features.
pub type PingPong = AppContract<
PingPongError,
PingPongInstantiateMsg,
PingPongExecuteMsg,
PingPongQueryMsg,
AppMigrateMsg,
>;

const APP: PingPong = PingPong::new(PING_PONG_ID, APP_VERSION, None)
.with_instantiate(handlers::instantiate_handler)
.with_execute(handlers::execute_handler)
.with_query(handlers::query_handler)
.with_dependencies(&[StaticDependency::new(
IBC_CLIENT,
&[abstract_ibc_client::contract::CONTRACT_VERSION],
)])
.with_module_ibc(ibc::receive_module_ibc)
.with_ibc_callback(ibc::ibc_callback);

// Export handlers
#[cfg(feature = "export")]
abstract_app::export_endpoints!(APP, PingPong);

abstract_app::cw_orch_interface!(APP, PingPong, PingPongInterface);

#[cfg(not(target_arch = "wasm32"))]
use abstract_app::std::account::ModuleInstallConfig;
#[cfg(not(target_arch = "wasm32"))]
impl<Chain: cw_orch::environment::CwEnv> abstract_app::abstract_interface::DependencyCreation
for crate::PingPongInterface<Chain>
{
type DependenciesConfig = cosmwasm_std::Empty;

fn dependency_install_configs(
_configuration: Self::DependenciesConfig,
) -> Result<Vec<ModuleInstallConfig>, abstract_app::abstract_interface::AbstractInterfaceError>
{
Ok(vec![ModuleInstallConfig::new(
abstract_app::objects::module::ModuleInfo::from_id(
IBC_CLIENT,
abstract_ibc_client::contract::CONTRACT_VERSION.into(),
)?,
None,
)])
}
}
32 changes: 32 additions & 0 deletions contracts/{{ibc_app_name}}/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use abstract_app::{
objects::module::ModuleInfo, sdk::AbstractSdkError, std::AbstractError,
AppError as AbstractAppError,
};
use cosmwasm_std::StdError;
use cw_asset::AssetError;
use cw_controllers::AdminError;
use thiserror::Error;

#[derive(Error, Debug, PartialEq)]
pub enum PingPongError {
#[error(transparent)]
Std(#[from] StdError),

#[error(transparent)]
Abstract(#[from] AbstractError),

#[error(transparent)]
AbstractSdk(#[from] AbstractSdkError),

#[error(transparent)]
Asset(#[from] AssetError),

#[error(transparent)]
Admin(#[from] AdminError),

#[error(transparent)]
DappError(#[from] AbstractAppError),

#[error("Caller module is not a PingPong: {source_module}")]
UnauthorizedIbc { source_module: ModuleInfo },
}
49 changes: 49 additions & 0 deletions contracts/{{ibc_app_name}}/src/handlers/execute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use abstract_app::{
objects::TruncatedChainId,
sdk::{IbcClient, IbcInterface},
std::ibc::Callback,
traits::AbstractResponse,
};
use cosmwasm_std::{CosmosMsg, DepsMut, Env, MessageInfo};

use crate::{
contract::{PingPong, PingPongResult},
msg::{PingPongCallbackMsg, PingPongExecuteMsg, PingPongIbcMsg},
};

pub fn execute_handler(
deps: DepsMut,
env: Env,
_info: MessageInfo,
module: PingPong,
msg: PingPongExecuteMsg,
) -> PingPongResult {
match msg {
PingPongExecuteMsg::Ping { opponent_chain } => {
ping_pong(deps, &env, opponent_chain, module)
}
}
}

pub(crate) fn ping_pong(
deps: DepsMut,
env: &Env,
opponent_chain: TruncatedChainId,
module: PingPong,
) -> PingPongResult {
// # ANCHOR: ibc_client
let self_module_info = module.module_info()?;
let ibc_client: IbcClient<_> = module.ibc_client(deps.as_ref(), env);
let ibc_action: CosmosMsg = ibc_client.module_ibc_action(
opponent_chain.clone(),
self_module_info,
// Start by playing a Ping
&PingPongIbcMsg::Ping {},
Some(Callback::new(&PingPongCallbackMsg::Pinged {
opponent_chain,
})?),
)?;
// # ANCHOR_END: ibc_client

Ok(module.response("ping").add_message(ibc_action))
}
16 changes: 16 additions & 0 deletions contracts/{{ibc_app_name}}/src/handlers/instantiate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use cosmwasm_std::{DepsMut, Env, MessageInfo, Response};

use crate::{
contract::{PingPong, PingPongResult},
msg::PingPongInstantiateMsg,
};

pub fn instantiate_handler(
_deps: DepsMut,
_env: Env,
_info: MessageInfo,
_module: PingPong,
_msg: PingPongInstantiateMsg,
) -> PingPongResult {
Ok(Response::new())
}
7 changes: 7 additions & 0 deletions contracts/{{ibc_app_name}}/src/handlers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub mod execute;
pub mod instantiate;
pub mod query;

pub use crate::handlers::{
execute::execute_handler, instantiate::instantiate_handler, query::query_handler,
};
34 changes: 34 additions & 0 deletions contracts/{{ibc_app_name}}/src/handlers/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use cosmwasm_std::{to_json_binary, Binary, Deps, Env, StdResult};

use crate::{
contract::{PingPong, PingPongResult},
msg::{PingPongQueryMsg, StatusResponse},
state::{PINGS, PONGS},
};

pub fn query_handler(
deps: Deps,
_env: Env,
_module: &PingPong,
msg: PingPongQueryMsg,
) -> PingPongResult<Binary> {
match msg {
PingPongQueryMsg::Status {} => to_json_binary(&query_status(deps)?),
}
.map_err(Into::into)
}

fn query_status(deps: Deps) -> StdResult<StatusResponse> {
// Sum pings
let pings = PINGS
.range(deps.storage, None, None, cosmwasm_std::Order::Ascending)
.map(|result| result.map(|(_k, v)| v).unwrap_or_default())
.sum();
// Sum pongs
let pongs = PONGS
.range(deps.storage, None, None, cosmwasm_std::Order::Ascending)
.map(|result| result.map(|(_k, v)| v).unwrap_or_default())
.sum();

Ok(StatusResponse { pings, pongs })
}
Loading

0 comments on commit 66ea405

Please sign in to comment.