#[contract]Expand description
Procedural macro generating messages from contract impl block.
Generates instantiate, migrate, reply, sudo, exec and query
enum messages to be later used in contract implementation.
§Example usage
pub struct SvContract {
data: Item<ContractData>,
}
#[sylvia::contract]
#[sv::error(ContractError)]
#[sv::features(replies)]
impl SvContract {
pub const fn new() -> Self {
Self {
data: Item::new("data"),
}
}
#[sv::msg(instantiate)]
fn instantiate(&self, ctx: InstantiateCtx, admin: Option<String>) -> Result<Response, ContractError> {
}
#[sv::msg(exec)]
fn execute(&self, ctx: ExecCtx) -> Result<Response, ContractError> {
}
#[sv::msg(query)]
fn query(&self, ctx: QueryCtx) -> Result<Response, ContractError> {
}
#[sv::msg(migrate)]
fn migrate(&self, ctx: MigrateCtx) -> Result<Response, ContractError> {
}
#[sv::msg(reply)]
fn reply(&self, ctx: ReplyCtx, result: SubMsgResult, #[sv::payload(raw)] payload: Binary) -> Result<Response, ContractError> {
}
#[sv::msg(sudo)]
fn sudo(&self, ctx: SudoCtx) -> Result<Response, ContractError> {
}
}This would generate output like:
pub mod sv {
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(
sylvia::serde::Serialize,
sylvia::serde::Deserialize,
Clone,
Debug,
PartialEq,
sylvia::schemars::JsonSchema,
)]
#[serde(rename_all = "snake_case")]
pub struct InstantiateMsg {
pub admin: Option<String>,
}
impl InstantiateMsg {
pub fn new(admin: Option<String>) -> Self {
Self { admin }
}
pub fn dispatch(
self,
contract: &SvContract,
ctx: (
sylvia::cw_std::DepsMut<sylvia::cw_std::Empty>,
sylvia::cw_std::Env,
sylvia::cw_std::MessageInfo,
),
) -> Result<Response, ContractError> {
let Self { admin } = self;
contract
.instantiate(Into::into(ctx), admin)
.map_err(Into::into)
}
}
}And appropriate messages for exec, query, migrate, reply and sudo variants.
§Attributes
Contract macro supports multiple attributes to customize the behavior of generated messages.
§sv::msg(...)
Message structures are generated based on specific implemented methods attributed with
#[sv::msg(msg_type)]. Msg attribute takes as its first argument type of message it is
supposed to handle:
instantiate- instantiation message handler. There should be always exactly oneexec- execute message variantquery- query message variantmigrate- migrate message variantreply- reply message variantsudo- sudo message variant
In the case of a query, it is possible to pass a second argument which is its ResponseType.
This is required in case of aliased results wrapping their ResponseType to properly
implement QueryResponses.
pub struct SvContract {
data: Item<ContractData>,
}
#[sylvia::contract]
#[sv::error(ContractError)]
impl SvContract {
pub const fn new() -> Self {
Self {
data: Item::new("data"),
}
}
#[sv::msg(instantiate)]
fn instantiate(&self, ctx: InstantiateCtx, admin: Option<String>) -> Result<Response, ContractError> {
Ok(Response::new())
}
#[sv::msg(query, resp=QueryResponse)]
fn query(&self, ctx: QueryCtx) -> Result<QueryResponse, ContractError> {
// Some query implementation
}
}§sv::custom(msg=..., query=...)
Allows restricting interface to use specific
custom message and query types. If used with ExecC and QueryC associated
types sv::custom(...) attribute has priority in defining custom types.
§sv::error(error_type)
Allows specifing custom error type for the contract. Default is cosmwasm_std::StdError.
§sv::override_entry_point(entry_point_type=<path_to_entry_point(msg_path)>
Allows overriding default entry point for specific message type.
Used in case there is a need to provide some custom functionality inside the entry point.
Specified entry point will be used in generated multitest helpers
pub struct SvContract;
#[cw_serde]
pub enum CustomExecMsg {}
#[entry_point]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: CustomExecMsg,
) -> StdResult<Response> {
}
#[sylvia::contract]
#[sv::override_entry_point(exec=execute(CustomExecMsg))]
impl SvContract {
}§sv::messages(path_to_interface)
Used to declare interfaces implemented on the contract. Required for the contract to be able to handle an interface message.
pub mod sv_interface {
#[sylvia::interface]
pub trait SvInterface {
type Error: From<StdError>;
}
}
impl sv_interface::SvInterface for SvContract {
type Error = StdError;
}
pub struct SvContract;
#[sylvia::contract]
#[sv::messages(sv_interface)]
impl SvContract {
}In case an interface has different name than a module in which its defined you have to pass the name of an interface as below:
pub mod interface {
#[sylvia::interface]
pub trait SvInterface {
type Error: From<StdError>;
}
}
impl interface::SvInterface for SvContract {
type Error = StdError;
}
pub struct SvContract;
#[sylvia::contract]
#[sv::messages(interface as SvInterface)]
impl SvContract {
}§sv::msg_attr(msg_type, {...})
This attribute can be used for the whole impl Contract {} block and
for every message type: exec, query, sudo, instantiate,
migrate and reply. The {...} part will be forwarded as an
attribute #[{...}] to the given message type (enum or struct).
§sv::attr({...})
Forwards variant’s attribute to the specific enum’s field in the
generated message type. It can be used along with sv::msg(...)
and only for message types variants that resolves in an enum field,
i.e. exec, query and sudo.
§sv::features(...)
Enables additional features for the contract. Allows user to use features that are considered breaking before the major release.
Currently supported features are:
-
replies- enables better dispatching ofreplyas well as its auto deserialization. With this feature enabled, user can use additional parameters in thesv::msgattribute like so:#[sv::msg(reply, handlers=[scenario1, scenario2], reply_on=Success)].Based on this parameters reply ids will be generated and associated with proper scenario specified by the
reply_onparameter.User can also specify custom
dataandpayloadtypes that will be auto deserialized from thecosmwasm_std::Binarytype.
§sv::payload(raw)
Requires contract to be marked with the sv::features(replies).
Used next to the reply method argument. It disables auto deserialization of the payload argument.
§sv::data(...)
Requires contract to be marked with the sv::features(replies).
Used next to the reply method argument. Based on the passed parameters it enables different behavior:
-
#[sv::data(raw)]- Returns error if the data isNone, extracts and forwardsBinaryif it’sSome. -
#[sv::data(raw, opt)]- ForwardsdataasOption<Binary>. -
#[sv::data(opt)]- Expects type ofdatain the method signature to bedata: Option<T> where T: Deserialize. Tries to deserializedatato type defined in the method signature and forwards it wrapped in theOption. Requiresdatato be JSON serialized.
If data is:
Some(valid) | Some(invalid) | None |
|---|---|---|
forwards Some(valid) | early returns an error specifying what went wrong with serde error attached | None - forwards None |
#[sv::data]- Expects data in the method signature to bedata: T where T: Deserialize. Tries to deserialize data to type defined in the method signature and forwards it or returns early an error. Requiresdatato be JSON serialized.
If data is:
Some(valid) | Some(invalid) | None |
|---|---|---|
forwards valid | early returns error specifying what went wrong with serde error attached | early returns error specifying the data is missing |
#[sv::data(instantiate)]- special case for reply toWasmMsg::instantiateandWasmMsg::instantiate2. Tries to deserialize data usingparse_instantiate_response_data.
If data is:
Some(valid) | Some(invalid) | None |
|---|---|---|
extracts and forwards valid | early returns error specifying what went wrong with serde error attached | early returns error specifying the data is missing |
#[sv::data(instantiate, opt)]- special case for reply toWasmMsg::instantiateandWasmMsg::instantiate2. tries to deserialize data usingparse_instantiate_response_data.
if data is:
Some(valid) | Some(invalid) | None |
|---|---|---|
forwards Some(valid) | early returns error specifying what went wrong with serde error attached | Forwards None |
- Missing
#[sv::data(...)]- In casesv::datais not found Sylvia won’t forward thedataargument so thedatashould be omited in the method signature.