This document serves as a centralized reference for all on-chain events emitted by the NotifyChain smart contracts.
NotifyChain leverages these on-chain events to feed the off-chain listener, index events in SQLite, trigger real-time notifications (e.g. to Discord), and display logs on the frontend operator dashboard.
NotifyChain contracts use a structured event design that allows off-chain services to quickly categorize and filter events without needing to parse the full event payload first.
Every event emitted by the AutoShareContract carries a NotificationCategory as one of its indexed topics. This allows listeners to filter for whole categories of events.
The enum is defined in events.rs:
| Variant | Value (U32) | Description |
|---|---|---|
Group |
0 |
AutoShare group lifecycle changes (creation, updates, active state toggles). |
Admin |
1 |
Administrative actions (pause/unpause, transferring admin, auth failures). |
Financial |
2 |
Movement of funds (withdrawing usage fees). |
Notification |
3 |
Scheduled notification operations (creation, expiration, cancellation, revocation). |
Every event emitted by AutoShareContract also carries a NotificationPriority topic to help downstream routers filter or trigger alerts based on severity.
The enum is defined in events.rs:
| Variant | Value (U32) | Description |
|---|---|---|
Low |
0 |
Informational: routine operations. No operator action required. |
Medium |
1 |
Standard: day-to-day operational events worth tracking. |
High |
2 |
Elevated: events operators should review promptly. |
Critical |
3 |
Urgent: security-relevant or funds-moving events demanding immediate attention (e.g., admin transfer). |
To prevent breaking changes in downstream indexers, category and priority topics are appended as the last two topics of every event. Older indexers that only read the event name and primary identifiers will naturally ignore these trailing topics.
These events are defined in base/events.rs within the AutoShare contract.
In Soroban, CamelCase struct names compile to snake_case symbols by default (e.g., AutoshareCreated is emitted on-chain with the first topic Symbol("autoshare_created")).
Emitted when a new AutoShare group is created.
- Trigger Method: create
- Topics:
Symbol("autoshare_created")creator: Address(Indexed creator of the group)category: NotificationCategory(AlwaysGroup/0)priority: NotificationPriority(TypicallyLow/0)
- Data (Payload):
id: BytesN<32>(The 32-byte group identifier)
Emitted when the members list of an AutoShare group is updated.
- Trigger Method: update_members
- Topics:
Symbol("autoshare_updated")updater: Address(Address that updated the members)category: NotificationCategory(AlwaysGroup/0)priority: NotificationPriority(TypicallyMedium/1)
- Data (Payload):
id: BytesN<32>(The group identifier)
Emitted when an AutoShare group is deactivated by its creator.
- Trigger Method: deactivate_group
- Topics:
Symbol("group_deactivated")creator: Address(Creator performing deactivation)category: NotificationCategory(AlwaysGroup/0)priority: NotificationPriority(TypicallyMedium/1)
- Data (Payload):
id: BytesN<32>(The group identifier)
Emitted when a deactivated group is reactivated.
- Trigger Method: activate_group
- Topics:
Symbol("group_activated")creator: Address(Creator performing reactivation)category: NotificationCategory(AlwaysGroup/0)priority: NotificationPriority(TypicallyMedium/1)
- Data (Payload):
id: BytesN<32>(The group identifier)
Emitted when the contract is paused by the administrator.
- Trigger Method: pause
- Topics:
Symbol("contract_paused")category: NotificationCategory(AlwaysAdmin/1)priority: NotificationPriority(AlwaysHigh/2)
- Data (Payload): None
Emitted when the contract is unpaused by the administrator.
- Trigger Method: unpause
- Topics:
Symbol("contract_unpaused")category: NotificationCategory(AlwaysAdmin/1)priority: NotificationPriority(AlwaysHigh/2)
- Data (Payload): None
Emitted when admin privileges are transferred to a new account.
- Trigger Method: transfer_admin
- Topics:
Symbol("admin_transferred")old_admin: Address(Old admin address)category: NotificationCategory(AlwaysAdmin/1)priority: NotificationPriority(AlwaysCritical/3)
- Data (Payload):
new_admin: Address(The new admin address)
Emitted when the admin withdraws collected usage fees from the contract.
- Trigger Method: withdraw
- Topics:
Symbol("withdrawal")token: Address(Token withdrawn)recipient: Address(Recipient address)category: NotificationCategory(AlwaysFinancial/2)priority: NotificationPriority(AlwaysHigh/2)
- Data (Payload):
amount: i128(Amount withdrawn)
Emitted when an unauthorized operation attempt is detected on-chain.
- Topics:
Symbol("authorization_failure")caller: Address(The caller who failed authentication)category: NotificationCategory(AlwaysAdmin/1)priority: NotificationPriority(AlwaysCritical/3)
- Data (Payload):
action: String(The action attempted)
Emitted when a scheduled notification is cancelled on-chain.
- Trigger Method: cancel_notification
- Topics:
Symbol("scheduled_notification_cancelled")caller: Address(The user who triggered cancellation)category: NotificationCategory(AlwaysNotification/3)priority: NotificationPriority(AlwaysMedium/1)
- Data (Payload):
notification_id: BytesN<32>(ID of the cancelled notification)
Emitted when a notification is scheduled on-chain with a bounded lifetime.
- Trigger Method: schedule_notification
- Topics:
Symbol("notification_scheduled")creator: Address(The creator of the notification)category: NotificationCategory(AlwaysNotification/3)priority: NotificationPriority(AlwaysLow/0)
- Data (Payload):
notification_id: BytesN<32>(The 32-byte notification identifier)
Emitted when a scheduled notification's lifetime elapses, marking it expired.
- Trigger Method: expire_notification
- Topics:
Symbol("notification_expired")notification_id: BytesN<32>(ID of the expired notification)category: NotificationCategory(AlwaysNotification/3)priority: NotificationPriority(AlwaysLow/0)
- Data (Payload):
expires_at: u64(Unix timestamp when it expired)
Emitted when a scheduled notification is revoked by its creator or admin.
- Trigger Method: revoke_notification
- Topics:
Symbol("notification_revoked")notification_id: BytesN<32>(ID of the revoked notification)revoked_by: Address(User who performed revocation)category: NotificationCategory(AlwaysNotification/3)priority: NotificationPriority(AlwaysMedium/1)
- Data (Payload):
revoked_at: u64(Unix timestamp when it was revoked)
These events are defined in events.rs within the TaskBounty contract. They do not use the category/priority helper wrapper but emit multi-topic symbols directly.
Emitted when a new task is created and reward tokens are escrowed in the contract.
- Trigger Method: create_task
- Topics:
Symbol("task")Symbol("created")
- Data (Payload):
id: u64(ID of the task)poster: Address(Creator of the task)title: String(Title of the task)reward: i128(Reward amount escrowed)deadline: u64(Unix timestamp for completion deadline)
Emitted when a contributor submits work for a task.
- Trigger Method: submit_work
- Topics:
Symbol("work")Symbol("submit")
- Data (Payload):
task_id: u64submission_id: u64(Unique submission index)contributor: Addresswork_url: String(Link to work deliverables - IPFS/Github/etc.)
Emitted when the poster approves a work submission, releasing escrowed rewards.
- Trigger Method: approve_submission
- Topics:
Symbol("sub")Symbol("approved")
- Data (Payload):
task_id: u64submission_id: u64contributor: Address(Receiving party of the reward)reward: i128(Amount transferred)
Emitted when the poster rejects a submission.
- Trigger Method: reject_submission
- Topics:
Symbol("sub")Symbol("rejected")
- Data (Payload):
task_id: u64submission_id: u64contributor: Address
Emitted when a task is cancelled and funds are refunded to the poster.
- Trigger Method: cancel_task
- Topics:
Symbol("task")Symbol("cancel")
- Data (Payload):
task_id: u64poster: Address(Refunded account)
Emitted when a poster or contributor raises a dispute over a work submission.
- Trigger Method: raise_dispute
- Topics:
Symbol("dispute")Symbol("raised")
- Data (Payload):
task_id: u64submission_id: u64raiser: Address(Party raising the dispute)reason: String(Text description of the dispute reason)
Off-chain clients (like the listener) read raw event logs from the Stellar RPC and map them back to application objects. Below is a TypeScript example demonstrating how to read and categorize events using the Stellar SDK.
import { xdr, Address, scValToNative } from '@stellar/stellar-sdk';
interface DecodedEvent {
contractId: string;
eventName: string;
category?: string;
priority?: string;
data: any;
}
// Map value indices back to human-readable strings
const CATEGORIES = ['Group', 'Admin', 'Financial', 'Notification'];
const PRIORITIES = ['Low', 'Medium', 'High', 'Critical'];
function parseSorobanEvent(rawEvent: any): DecodedEvent {
const topics = rawEvent.topic.map((t: string) => xdr.ScVal.fromXDR(t, 'base64'));
const dataScVal = xdr.ScVal.fromXDR(rawEvent.value, 'base64');
// Topic 0 is always the event name (symbol)
const eventName = scValToNative(topics[0]).toString();
const decoded: DecodedEvent = {
contractId: rawEvent.contractId,
eventName,
data: scValToNative(dataScVal)
};
// If the contract is AutoShare, parse category and priority appended at the end
if (topics.length >= 4) {
const rawCategory = scValToNative(topics[topics.length - 2]);
const rawPriority = scValToNative(topics[topics.length - 1]);
decoded.category = CATEGORIES[rawCategory] || `Unknown (${rawCategory})`;
decoded.priority = PRIORITIES[rawPriority] || `Unknown (${rawPriority})`;
}
return decoded;
}