This document is the authoritative reference for every event emitted by the SplitNaira Soroban contract. Backend services and indexers must consume events through this schema. Do not infer event shape from test snapshots alone.
Event schemas follow a conservative stability contract:
- Topic strings and payload field order are part of the public API. Indexers that decode raw XDR rely on positional tuple ordering.
- Additive changes (new optional events) are non-breaking.
- Any change to a topic string, payload field type, or positional order is a
breaking change and requires a new event name (e.g.
project_created_v2) with the old event kept for one deprecation window. - Breaking changes are announced in
CHANGELOG.mdand the contract release checklist.
Emitted once when a new royalty-split project is successfully created.
| Field | Value |
|---|---|
| Topics | ["project_created", project_id: Symbol] |
| Data | owner: Address |
Example (decoded)
topics: ["project_created", "afrobeats_vol3"]
data: GABC...XYZ
Notes
- Emitted by
create_project. project_idin topics matches the caller-supplied ID.- Indexers can use this event to build a project registry without polling.
Emitted when a project's splits are permanently locked and can no longer be modified.
| Field | Value |
|---|---|
| Topics | ["project_locked", project_id: Symbol] |
| Data | project_id: Symbol |
Example (decoded)
topics: ["project_locked", "afrobeats_vol3"]
data: "afrobeats_vol3"
Notes
- Emitted by
lock_project. - After this event,
update_collaboratorswill returnSplitError::ProjectLocked (9).
Emitted on every successful deposit into a project escrow.
| Field | Value |
|---|---|
| Topics | ["deposit_received", project_id: Symbol] |
| Data | (from: Address, amount: i128, project_balance: i128) |
Example (decoded)
topics: ["deposit_received", "afrobeats_vol3"]
data: (GABC...XYZ, 5000000, 12000000)
Notes
amountandproject_balanceare in stroops (1 XLM = 10,000,000 stroops).project_balanceis the total held in escrow after this deposit.- Emitted by
deposit.
Emitted once per collaborator during a distribution round, immediately
before distribution_complete.
| Field | Value |
|---|---|
| Topics | ["payment_sent", project_id: Symbol] |
| Data | (recipient: Address, amount: i128) |
Example (decoded)
topics: ["payment_sent", "afrobeats_vol3"]
data: (GDEF...UVW, 3000000)
Notes
amountis the collaborator's share for this round, in stroops.- One event per collaborator — indexers summing
payment_sentamounts within a round should match thetotalfield in the correspondingdistribution_completeevent.
Emitted once per distribution round, after all payment_sent events for
that round have been emitted.
| Field | Value |
|---|---|
| Topics | ["distribution_complete", project_id: Symbol] |
| Data | (round: u32, total: i128) |
Example (decoded)
topics: ["distribution_complete", "afrobeats_vol3"]
data: (1, 5000000)
Notes
roundstarts at 1 and increments with each successful distribute call.totalis the sum of allpayment_sentamounts in this round, in stroops.- Indexers can use
(project_id, round)as a stable idempotency key.
Emitted when a project's title or type is changed.
| Field | Value |
|---|---|
| Topics | ["metadata_updated", project_id: Symbol] |
| Data | project_id: Symbol |
Example (decoded)
topics: ["metadata_updated", "afrobeats_vol3"]
data: "afrobeats_vol3"
Notes
- Emitted by
update_metadata. - Indexers that cache project title/type should re-fetch on this event.
Emitted when a project owner transfers ownership to a new address.
| Field | Value |
|---|---|
| Topics | ["ownership_transferred", project_id: Symbol] |
| Data | (previous_owner: Address, new_owner: Address) |
Example (decoded)
topics: ["ownership_transferred", "afrobeats_vol3"]
data: (GABC...XYZ, GHIJ...MNO)
Notes
- Emitted by
transfer_ownership. - Authorization gates (e.g.
update_collaborators) check the new owner immediately after this event.
Emitted when the contract admin withdraws tokens that were not allocated to any project (i.e. deposited directly to the contract address).
| Field | Value |
|---|---|
| Topics | ["unallocated_withdrawn", token: Address] |
| Data | (admin: Address, to: Address, amount: i128, remaining_unallocated: i128) |
Example (decoded)
topics: ["unallocated_withdrawn", CUSDC...CONTRACT]
data: (GADMIN...XYZ, GDEST...ABC, 1000000, 500000)
Notes
remaining_unallocatedis the contract-level unallocated balance after the withdrawal.- Amounts in stroops.
| Event | Trigger | Key fields for indexing |
|---|---|---|
project_created |
create_project |
project_id, owner |
project_locked |
lock_project |
project_id |
deposit_received |
deposit |
project_id, from, amount, project_balance |
payment_sent |
distribute (per collaborator) |
project_id, recipient, amount |
distribution_complete |
distribute (once per round) |
project_id, round, total |
metadata_updated |
update_metadata |
project_id |
ownership_transferred |
transfer_ownership |
project_id, previous_owner, new_owner |
unallocated_withdrawn |
withdraw_unallocated |
token, admin, to, amount |