Integration SDK
We've created helper functions for CosmWasm contracts that wish to integrate CronCat automation. There are a few crates available for developers that will handle logic involving task creation, handling the reply's response, validating an invocation as coming from your task, providing clean errors, and testing methods for dApps using cw-multi-test
.
Please see these examples that demonstrate usage:
Integration Utilities
The crate croncat-integration-utils
contains helper functions allowing your smart contract to leverage automation, and will help you programmatically create and handle tasks.
Key methods
create_croncat_task_submessage
Makes it simple to create a CronCat task in your smart contract. Fill out your CronCatTaskRequest
struct, send it to this method, and you'll receive a submessage to add to your contract's Response.
Example:
fn foo(…) -> Result<Response, ContractError> {
// load croncat_factory_address from state
let croncat_task = CronCatTaskRequest {
interval: CronCatInterval::Block(1),
boundary: None,
stop_on_fail: true,
actions: vec![CronCatAction {
msg: Wasm(Execute {
contract_addr: env.contract.address.to_string(),
msg: to_binary(&ExecuteMsg::Tick {})?,
funds: vec![],
}),
gas_limit: Some(300_000),
}],
queries: None,
transforms: None,
cw20: None,
};
let sub_message = create_croncat_task_submessage(
&deps.querier,
info,
croncat_factory_address,
croncat_task,
None,
)?;
Ok(Response::new()
.add_submessage(sub_message)
)
}
reply_handle_croncat_task_creation
After the task creation (see method above) we can handle the submessage's reply to see get details on the newly-created task, or propagate an error if there were problems.
Example:
pub fn reply(deps: DepsMut, msg: Reply) -> Result<Response, ContractError> {
let (task_info, msg_binary) = reply_handle_croncat_task_creation(msg)?;
// task_info contains relevant details to the newly-created task
Ok(Response::new().set_data(msg_binary))
}
handle_incoming_task
Sometimes, an invocation to your smart contract's method should only be called by a task your contract created. If this applies to your use case, this method helps validate this, then returns the TaskExecutionInfo, which is the same struct we get in the reply handler.
Example:
fn bar(…) -> Result<Response, ContractError> {
// load croncat_factory_address from state
let task_info = handle_incoming_task(
&deps.querier,
env.clone(),
info,
croncat_factory_addr,
None,
)?;
// This invocation is from our CronCat task.
}
Clean Errors
The croncat-errors-macro
crate is a procedural attribute macro meant to be used with the integration utils from above. This type of macro needs to be in its own crate, hence the distinction.
To use it, place the #[croncat_error]
macro on your error enum, before the derives.
Usage
#[croncat_error] // Add this macro
#[derive(Error, Debug, PartialEq)]
pub enum ContractError {
#[error("{0}")]
Std(#[from] StdError),
#[error("Custom error: {msg}")]
MyCustomError { msg: String },
}
What it does
This will do two things:
- Add this enum variant:
#[error("CronCat error: {err:?}")]
CronCatError {
err: CronCatContractError
}
- Add an implementation to assist with clean errors:
impl From<CronCatContractError> for ContractError {
fn from(error: CronCatContractError) -> Self {
ContractError::CronCatError {
err: error,
}
}
}
Test Helpers
If your project is using cw-multi-test
, you may add croncat-integration-testing
crate as a dev dependency.
Highlight method
The set_up_croncat_contracts
method will handle bootstrapping the secure CronCat factory architecture, and return addresses of the various contracts along with the App from cw-multi-test
.
Note: you may optionally pass in your App
as a parameter. In the example below, you'll see we're passing in None
which will create it.
#[test]
fn my_test() {
let CronCatTestEnv {
mut app,
factory,
manager,
tasks: _,
agents,
} = set_up_croncat_contracts(None);
// Rest of test…
}