Publish events from a Rust contract
An event can contain topics, alongside the data it is publishing. The topics data can be any value or type you want.
With the release of Whisk, Protocol 23, the syntax for publishing smart contract events has changed. In order to provide the most up-to-date information, this guide has been updated to include the new patterns. Find more detailed information in the Rust SDK documentation.
The strategy here is to first create some struct
s that will define how our events are shaped. Then, within the contract's function, we can create and publish those structs.
// This event will be published with the following structure:
// `["COUNTER", "increment"], data = count: u32`
#[contractevent(topics = ["COUNTER", "increment"], data_format = "single-value")]
pub struct Increment {
count: u32,
}
// Events without explicit topics will use the struct name for the sole topic.
// By default, the event data will follow the struct shape.
// This event will be published with the following structure:
// `["borrow"], data = {addr: Address, amount: i128}`
#[contractevent]
pub struct Borrow {
addr: Address,
amount: i128,
}
// Event topics can also be noted in the struct, so they're dynamic.
// This event will be published with the following structure:
// `["deposit", addr: Address, token: Address], data = [amount: i128, time: u64]`
#[contractevent(data_format = "vec")]
pub struct Deposit {
#[topic]
addr: Address,
#[topic]
token: Address,
amount: i128,
time: u64,
}
// This function does nothing beside publish events.
pub fn events_function(env: Env, invoker: Address, token: Address) {
Increment {
count: 8675309,
}.publish(&env);
Borrow {
addr: invoker.clone(),
amount: 123_0000000,
}.publish(&env);
Deposit {
addr: invoker,
token: token,
amount: 321_0000000,
time: env.ledger().timestamp(),
}.publish(&env);
}
A more realistic example can be found in the way the token interface works. For example, the interface requires an event to be published every time the transfer
function is invoked, with the following information:
#[contractevent(data_format = "single-value")]
pub struct Transfer {
#[topic]
from: Address,
#[topic]
to: Address,
amount: i128,
}
pub fn transfer(env: Env, from: Address, to: Address, amount: i128) {
// transfer logic omitted here
Transfer { from, to, amount }.publish(&env);
}
Guides in this category:
📄️ Consume previously ingested events
Consume ingested events without querying the RPC again
📄️ Ingest events published from a contract
Use Stellar RPC's getEvents method for querying events, with a 7 day retention window
📄️ Publish events from a Rust contract
Publish events from a Rust contract