Nodes announce
Each node signs and announces its event types and event contracts to its peers, with a membership token from the operator. Peers learn a type only if the token says the node belongs to its owner.
Build / Events
Events let contracts react to each other. An organization declares an event type and emits it from its scripts. Anyone can deploy an event contract, on any node, that runs with each event it consumes, and pays for its own runs.
POST /v1/eventsemitconsumes01
A contract runs when someone calls it. An event contract runs when something happens instead: an order is placed, a payment clears, a record changes. Three pieces make that work:
| What it is | Who can use it | |
|---|---|---|
| Event type | a named, versioned set of fields | declared by an organization, on one of its nodes |
emit | publishes an event of that type from a run | only the type's owner, from its own nodes |
| Event contract | a contract that consumes one type | anyone, on any node, unless the type is restricted |
Publishers never pay for consumers, so anyone can subscribe to an event without costing the organization that emits it.
02
An event type is a script of its own. It names the fields its events carry and has no body. Names, paths and versions work as they do for contracts, and versions are immutable.
event com.example.OrderPlaced@1(orderId: string, total: decimal)
restricted event com.example.AuditEntry(entry: object)A restricted event type is consumed only by event contracts its owner deployed, for events you want to keep inside your organization.
Declare it on a node of your organization with its API key, or a run token from one of its own API clients. The node's organization owns the type, because it's the organization whose nodes may emit it.
curl -X POST https://node.example/v1/events \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_KEY" \
-d '{"source": "event com.example.OrderPlaced(orderId: string, total: decimal)"}'GET /v1/events lists the event types a node knows, its own and those it learned from peers. DELETE /v1/events/com.example.OrderPlaced@1 deletes one.
03
A request or a contract emits an event with emit, naming every field:
contract com.example.Checkout(orderId: string, total: decimal): string {
emit com.example.OrderPlaced(orderId: orderId, total: total)
return orderId
}Checkout, and it emits as you.# The most events one run may emit. Defaults to 16.
MAX_EVENTS_PER_RUN=16
# The most one event's data may take, as JSON, in bytes. Defaults to 32 KiB.
MAX_EVENT_DATA_BYTES=3276804
An event contract names the type it consumes. The event's fields are its parameters, so it declares none of its own, and it has no return type.
contract com.example.OnOrderPlaced consumes com.example.OrderPlaced@1 {
var state(orderId) seen: int32 = 0
seen = seen + 1
const logger: com.example.Logger
logger.info(message: "Order ${orderId}: ${total}, from ${caller.org}")
}event, with its id, type, version, publishedAt and depth, and caller, the event's owner and the node that published it.Deploy it like any contract, with POST /v1/contracts.
05
An event can be emitted on one node and consumed on many others. Every hop is signed, and receivers check the publisher against the operator, so no node has to take another's word for who owns an event.
Each node signs and announces its event types and event contracts to its peers, with a membership token from the operator. Peers learn a type only if the token says the node belongs to its owner.
When a run succeeds, its node signs each event and queues it for its own event contracts, and once for each peer subscribed to it. Restricted events go only to the owner's contracts.
A worker delivers each event, retrying with backoff for up to a day. The receiver checks the signature, the membership token, the event's age and depth, and that it knows the type.
The receiver queues the event once for each local event contract and runs it, retrying a failure up to 3 times in all.
Delivery is at least once, and each event contract runs once per event id. Events may arrive in any order. Admins follow deliveries at GET /v1/admin/events/outbox and runs at GET /v1/admin/events/inbox.
06
07
An event contract may emit events of its own, so one event can set off another. Each event carries its chain, and a few rules keep a chain from looping:
For example, contract A emits Event1, and event contract B consumes it. If B emits Event2, event contract C may consume that, but C can't emit Event1 or Event2, or call A or B.
08
Read the full reference, including how nodes sign and check events, in the stellarium-ts events guide and the documentation. Events need RequestScript 1.6.0, which adds event declarations, consumes and emit; learn the language at requestscript.org.
Built something with events? Show it off on Discord.