Add contractevent macro and event support to contract spec#1473
Add contractevent macro and event support to contract spec#1473leighmcculloch merged 15 commits intomainfrom
Conversation
754c2a6 to
b184e22
Compare
b184e22 to
2bc47ce
Compare
|
TODO:
|
This comment was marked as outdated.
This comment was marked as outdated.
|
Yet another alternative way to define topics, which is largely a simplification, although in the default case there is more to do: Replace this: #[contractevent]
#[derive(Clone, Default, Debug, Eq, PartialEq)]
pub struct MyEvent {
#[topic]
pub my_topic: u32,
pub my_event_data: u32,
pub more_event_data: u64,
}With: #[contractevent(topics = ["my_event"])]
#[derive(Clone, Default, Debug, Eq, PartialEq)]
pub struct MyEvent {
#[topic]
pub my_topic: u32,
pub my_event_data: u32,
pub more_event_data: u64,
}In this way there is no "default" behaviour where a topic is inserted with the type name. Topics are always explicitly defined. |
I gave this approach a go, but it's not particularly enjoyable to have to type the topics out in the cases where the struct name matches the event name, and it becomes really easy to publish events with no topics which can make it a little harder to filter different types of events. So I'm leaning away from that back to the original solution. |
|
I got feedback offline about the concept of So I've renamed |
…ncluding the max length
|
I found a bug in how the map variant of events are passed to the host. |
Fixed in 3f977d4. |
|
I've opened a follow up to this PR that uses the |
### What Add `contractevent` types for tokens and stellar asset contract. Remove event publishing helpers. ### Why With the addition of the `contractevent` macro in #1473 it makes sense to use the macro to update the specs generated for the token and the stellar asset contract such that their generated specs include the events. The `transfer` event added is represented with two event types: - `Transfer`, which is the `single-value` data with an `amount`. - `TransferMuxed`, which is the `map` data with a non-optional `to_muxed_id`. Two types are used because of the differing data format type, and the contract event schema does not support multiple data format types to be represented in a single type, to avoid complexity. The reason that a non-optional `to_muxed_id` is used is because without https://github.com/orgs/stellar/discussions/1750 the option none would be stored as a void. In the future if that change occurs it may make sense to update `TransferMuxed` to `Transfer2`, or similar, where-by it represents some larger set of parameters that may grow over time. The existing event publishing helpers are removed, rather than deprecated, because the helpers build versions of the events that will no longer be used by the stellar asset contract after CAP-67, versions that include an admin topic. If the helpers remain, folks may continue to call them and emit the topic. If the functions were updated, it would be a breaking change anyway. It is more obvious to make the break by removing them and encouraging use of the new events. Because the new event types carry parameters as fields, it is very explicit that the admin topic is gone. Close #1097 Close #1488 ### Merging This change is intended to be merged to `main` after #1473.
What
Add
contracteventmacro for defining events, and event support to contract spec.In it's most basic form, as follows, where an automatic prefix topic based on the name will be published, with any topic fields appended to the topic list, and any other fields emitted as map entries in a map:
But also supporting more advanced customisable forms, where prefix topics can be overriden and a max of two provided, and where the data section can be defined as either being a
vecor asingle-valueinstead.Why
The
contracteventmacro will achieve a couple things for events.It will allow developers to define the event as a type, in a similar way that they can define an event in Solidity contracts. Defining it as a type makes it easier to reuse the event, and to define the types safely and be clear about what types within the event are being published.
It will provide a foundation that the Rust SDK can use to include in the contract interface (spec) an entry for the event. That entry can then be used by downstream systems to bring more meaning to the raw event data that is visible in transaction / ledger close meta. For an example of what that looks like, see https://github.com/orgs/stellar/discussions/1724#discussioncomment-13118291.
The advanced customisations are a necessity to be able to make the events and the event schema describe existing contract events. The network already has a variety of events and some contracts use two fields as fixed prefix topics, such as the Soroswap contracts. Some use vecs for the data section, and even a single value such as an
amount: i128, such as the Stellar Asset Contract.Close #1097
Docs for the
contracteventattribute macroGenerates conversions from the struct into a published event.
Fields of the struct become topics and data parameters in the published event.
Includes the event in the contract spec so that clients can generate bindings for the type and downstream systems can understand the meaning of the event.
Examples
Basic Contract Event
Defining a basic contract event.
The event will have a single fixed prefix topic matching the name of the struct in lower snake case. The fixed prefix topic will appear before any topics listed as fields. In the example below, the topics for the event will be:
"my_event"my_topicfieldThe event’s data will be a
Map, containing a key-value pair for each field with the key being the name as aSymbol. In the example below, the data for the event will be:Prefix Topics
Defining a contract event with a custom set of fixed prefix topics.
The prefix topic list can be set to another value. In the example below, the topics for the event will be:
"my_contract""an_event"my_topicfieldData Format
Defining a contract event with a different data format. The data format of the event is by default a map, but can alternatively be defined as a
vecorsingle-value.Vec
In the example below, the data for the event will be a
Veccontaining:Single Value
In the example below, the data for the event will be a u32.
When the data format is a single value there must be no more than one data field.
A Full Example
Defining a contract event, publishing it in a contract, and testing it.