Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions creator-keys/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
//!
//! This approach ensures that indexers can reliably parse event data across
//! different contract versions.
//!
//! ### Quote-Related Event Field Semantics
//!
//! - `supply`: Number of keys in circulation after the trade (for buy/sell events)
//! - `payment`: Total amount paid by the buyer (for buy events, ≥ key price)

use soroban_sdk::{contracttype, symbol_short, Address, String, Symbol};

Expand Down Expand Up @@ -50,6 +55,12 @@ pub const BUY_EVENT_DATA_FIELDS: [&str; 2] = ["supply", "payment"];
/// Number of fields in the buy event data payload.
pub const BUY_EVENT_FIELD_COUNT: usize = BUY_EVENT_DATA_FIELDS.len();

/// Stable field order for sell event tuple payloads.
pub const SELL_EVENT_DATA_FIELDS: [&str; 1] = ["supply"];

/// Number of fields in the sell event data payload.
pub const SELL_EVENT_FIELD_COUNT: usize = SELL_EVENT_DATA_FIELDS.len();

/// Stable registration event payload for downstream indexers.
///
/// Event shape:
Expand Down
5 changes: 5 additions & 0 deletions creator-keys/tests/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,8 @@ fn test_sell_key_event_payload_tracks_zero_supply_after_last_sale() {
assert_eq!(topics.actor, seller);
assert_eq!(payload.supply, 0);
}

#[test]
fn test_sell_key_event_payload_field_order_is_documented() {
assert_eq!(events::SELL_EVENT_DATA_FIELDS, ["supply"]);
}
12 changes: 4 additions & 8 deletions docs/contract-event-conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,9 @@ The following table summarizes the events currently implemented in the `creator-

| Event Name | Topics (Index 0, 1, 2) | Data Fields | Data Type |
| :--- | :--- | :--- | :--- |
| `register` | `(Symbol("register"), creator)` | `creator`, `handle`, `supply`, `holder_count` | `struct CreatorRegisteredEvent` |
| `register` | `(Symbol("register"), creator)` | `creator`, `handle`, `supply`, `holder_count`, `creator_bps`, `protocol_bps` | `struct CreatorRegisteredEvent` |
| `buy` | `(Symbol("buy"), creator, buyer)` | `supply`, `payment` | `tuple (u32, i128)` |
| `sell` | `(Symbol("sell"), creator, seller)` | `supply` | `tuple (u32)` |

## Deviations and Exceptions

### Unimplemented Events
- **`sell_key`**: Currently, the `sell_key` operation does not emit an event. This is a known deviation from the pattern where every state-mutating operation should emit an event. Indexers tracking supply or holder changes must currently rely on state snapshots or future contract updates that introduce this event.

### Data Type Inconsistency
While the general preference is for `struct` payloads (like `register`), some high-frequency events like `buy` use `tuples` for gas efficiency. Indexers should check the `contracttype` encoding to distinguish between map-based structs and array-based tuples.
## Data Type Inconsistency
While the general preference is for `struct` payloads (like `register`), some high-frequency events like `buy` and `sell` use `tuples` for gas efficiency. Indexers should check the `contracttype` encoding to distinguish between map-based structs and array-based tuples.
Loading