Package Events
Subscribe to real-time events emitted by specific Sui Move packages. Perfect for building reactive applications that respond instantly to on-chain activity without polling.
Overview
Package events are custom events emitted by Sui Move smart contracts. When a contract executes — whether it's minting an NFT, processing a swap, or updating game state — it can emit events that describe what happened.
Surflux's Package Events stream lets you subscribe to these events in real-time via Server-Sent Events (SSE). Instead of polling the blockchain or running your own indexer, you get instant notifications delivered directly to your application.
Use Cases
DeFi Protocols
- Listen for swap completions, liquidity additions, or liquidation events
- Build real-time price feeds from DEX activity
- Trigger alerts when specific trading conditions are met
NFT Platforms
- Track minting events as they happen
- Monitor marketplace sales and listings
- Build live activity feeds for collections
Gaming & Metaverse
- React to in-game events (battles, achievements, item transfers)
- Update UI instantly when game state changes
- Build live leaderboards and event logs
Automation & Bots
- Trigger workflows based on smart contract events
- Automate responses to protocol state changes
- Build MEV or arbitrage bots
How to Subscribe
Endpoint
GET /events?api-key={your_api_key}&last-id={resumption_id}
Base URL (Mainnet): https://flux.surflux.dev
Base URL (Testnet): https://testnet-flux.surflux.dev
Parameters
| Parameter | Required | Description |
|---|---|---|
api-key | Yes | Your Surflux API key for authentication |
last-id | No | Resume stream from a specific event ID (see below) |
Stream Resumption with last-id
The last-id parameter lets you control where the stream starts:
| Value | Behavior |
|---|---|
0 (default) | Start from the beginning (server buffer limits apply) |
$ | Only receive new events from now onwards |
{event-id} | Resume from after this specific event ID |
Important: Your client should persist the event ID from each received event. If the connection drops, use the last received ID to resume without missing events.
Connection Limits
Only one client per API key can be connected at a time. If you need multiple simultaneous connections, contact support for additional API keys.
Event Structure
Package Event Format
{
"type": "package_event",
"timestamp_ms": 1688769149870,
"checkpoint_id": 7090583,
"tx_hash": "BCnkYBU5RAwU2qS9fBuyFxFzACzX2MGKxUyKGnd8pRiV",
"data": {
"event_index": 1,
"sender": "0x443f35e4d8e7f0f9e590e92569cf08b49bc24b63a92dc80b5d5510e753aad2e8",
"event_type": "0x2::display::VersionUpdated<0x58156e414780a5a237db71afb0d852674eff8cd98f9572104cb79afeb4ad1e9d::suinet::SUITOMAINNET>",
"contents": {
"field": "field on your event",
"anotherField": "another field on your event"
}
}
}
Field Descriptions
| Field | Type | Description |
|---|---|---|
type | string | Always "package_event" for package events |
timestamp_ms | number | Unix timestamp in milliseconds when the event occurred |
checkpoint_id | number | Sui checkpoint number |
tx_hash | string | Transaction digest that emitted this event |
data.event_index | number | Index of this event within the transaction |
data.sender | string | Address that initiated the transaction |
data.event_type | string | Full type path of the emitted event |
data.contents | object | Event payload (structure defined by the Move contract) |
Code Examples
JavaScript / TypeScript
const apiKey = "your_api_key_here";
const eventSource = new EventSource(
`https://flux.surflux.dev/events?api-key=${apiKey}&last-id=$`
);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === "package_event") {
console.log("Package event received:", data.data.event_type);
console.log("Event contents:", data.data.contents);
// Persist event.lastEventId for resumption
localStorage.setItem("lastEventId", event.lastEventId);
}
};
eventSource.onerror = (error) => {
console.error("Connection error:", error);
eventSource.close();
// Reconnect with last received event ID
const lastId = localStorage.getItem("lastEventId");
// ... reconnect logic
};
Filtering Specific Events
To subscribe to specific package events, you'll need to filter on the client side:
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === "package_event") {
const eventType = data.data.event_type;
// Filter for specific package events
if (eventType.includes("0x123abc::nft::MintEvent")) {
console.log("NFT minted:", data.data.contents);
// Handle mint event
}
if (eventType.includes("0x456def::dex::SwapEvent")) {
console.log("Swap executed:", data.data.contents);
// Handle swap event
}
}
};
Best Practices
- Persist Event IDs — Always save the
lastEventIdfrom received events. Use it to resume the stream if your connection drops, ensuring you don't miss any events. - Handle Reconnections — Implement automatic reconnection logic with exponential backoff. SSE connections can drop due to network issues or server restarts.
- Filter on the Client — The SSE stream includes all package events and object changes. Filter by
event_typeon the client side to process only the events you care about. - Process Events Idempotently — You may receive duplicate events during reconnection. Design your event handlers to be idempotent.
- Monitor Connection Health — Set up heartbeat monitoring to detect stale connections and reconnect proactively.
Related Streams
- Address Events — Monitor all activity for a specific wallet
- Object Changes — Track changes to specific on-chain objects