Attribute Macro sylvia::interface

source ·
#[interface]
Expand description

Procedural macro generating messages from a contract trait. Generates sudo, exec and query enum messages to be later used in contract implementation.

§Example usage

#[sylvia::interface]
pub trait SvInterface {
   type Error: From<StdError>;

   #[sv::msg(exec)]
   fn update_admin(&self, ctx: ExecCtx, admin: Option<String>) -> Result<Response, Self::Error>;

   #[sv::msg(query)]
   fn admin(&self, ctx: QueryCtx) -> Result<AdminQueryResponse, Self::Error>;

   #[sv::msg(sudo)]
   fn remove_admin(&self, ctx: SudoCtx, #[serde(default)] admin: String) -> Result<Response, Self::Error>;
}

This would generate output like:

pub mod sv {
    #[derive(
        sylvia::serde::Serialize,
        sylvia::serde::Deserialize,
        Clone,
        Debug,
        PartialEq,
        sylvia::schemars::JsonSchema,
    )]
    #[serde(rename_all = "snake_case")]
    pub enum ExecMsg {
        UpdateAdmin { admin: Option<String> },
    }

    impl ExecMsg {
        pub fn dispatch<C: SvInterface>(contract: &C, ctx: (DepsMut, Env, MessageInfo))
            -> Result<Response, C::Error>
        {
            // Some dispatching implementation
        }
    }
}

Similarly for Query and Sudo enum messages.

§Associated types

Generics are not supported by the interface macro and won’t be. Instead, you can define associated types on an interface to allow users implementing it to customize the behavior to their liking.

Some names are however parsed and used in special contexts. Those are:

  • Error - error type returned by interface methods. This one is required to be declared.
  • ExecC - custom message type used in messages. Has to implement cosmwasm_std::CustomMsg.
  • QueryC - custom query type used in messages. Has to implement cosmwasm_std::CustomQuery.
#[sylvia::interface]
pub trait SvInterface {
   type Error: From<StdError>;
   type ExecC: CustomMsg;
   type QueryC: CustomQuery;

   #[sv::msg(exec)]
   fn update_admin(&self, ctx: ExecCtx<Self::QueryC>, admin: Option<String>) -> Result<Response<Self::ExecC>, Self::Error>;
}

Although it’s not required to define ExecC and QueryC types, it’s recommended to do so to allow the users of the interface to customize the behavior to their liking.

If however you want to restrict the interface to use specific custom message and query types, you can do so using #[sv::custom(msg=..., query=...)] attribute explained below.

§Attributes

Interface macro supports multiple attributes to customize the behavior of generated messages.

§sv::msg(...)

Messages structures are generated basing on interface trait method attributed with #[sv::msg(msg_type)]. Msg attribute takes as its first argument type of message it is supposed to handle:

  • exec - execute message variant
  • query - query message variant
  • sudo - 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 type AdminResult<ErrorT> = Result<AdminQueryResponse, ErrorT>;

#[sylvia::interface]
pub trait SvInterface {
   type Error: From<StdError>;

   #[sv::msg(exec)]
   fn update_admin(&self, ctx: ExecCtx, admin: Option<String>) -> Result<Response, Self::Error>;

   #[sv::msg(query, resp=AdminQueryResponse)]
   fn admin(&self, ctx: QueryCtx) -> AdminResult<Self::Error>;

   #[sv::msg(sudo)]
   fn remove_admin(&self, ctx: SudoCtx, admin: String) -> Result<Response, Self::Error>;
}

§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.

#[cw_serde]
pub enum SvCustomMsg {}

#[cw_serde]
pub enum SvCustomQuery {}

impl CustomMsg for SvCustomMsg {}
impl CustomQuery for SvCustomQuery {}

#[sylvia::interface]
#[sv::custom(msg=SvCustomMsg, query=SvCustomQuery)]
pub trait SvInterface {
   type Error: From<StdError>;
   type ExecC: CustomMsg;
   type QueryC: CustomQuery;

   #[sv::msg(exec)]
   fn update_admin(&self, ctx: ExecCtx<SvCustomQuery>, admin: Option<String>) -> Result<Response<SvCustomMsg>, Self::Error>;
}