Warp (Real-Time Streaming)
Available on All Plans: Warp is available on all plans including Free tier. See stream limits by plan.
Overview
Inodra Warp delivers real-time blockchain data via WebSocket or Server-Sent Events (SSE). Unlike webhooks which push to your endpoint, Warp allows your application to maintain a persistent connection and receive events as they occur.
Ready to get started?
Create your free account and configure your first Warp stream in the dashboard.
How It Works
┌────────────────┐ ┌─────────────┐ WebSocket or SSE ┌─────────────┐
│ Sui Blockchain │─────►│ Inodra │───────Connection────────►│ Your App │
│ │ │ Warp │ (Real-time data) │ │
└────────────────┘ └─────────────┘ └─────────────┘- Create a stream in the Inodra dashboard
- Connect via WebSocket or SSE
- Receive real-time events as they occur on-chain
Connection Protocols
| Protocol | Delivery Guarantee | Best For |
|---|---|---|
| WebSocket (recommended) | Exactly-once | When you need delivery guarantees |
| SSE | At-least-once | Higher throughput |
Recommendation: Use WebSocket for production workloads. Client ACKs give you exactly-once delivery, so you don't need to build deduplication logic. SSE is a good fit for quick prototypes and environments where WebSocket isn't available.
WebSocket: Client ACKs enable exactly-once delivery. Events are only marked as delivered after your client acknowledges them.
SSE: Events are delivered at-least-once. On ungraceful disconnect, up to 30 seconds of events may be redelivered on reconnect.
Connect modes: While you're disconnected, every stream buffers events for up to 30 minutes (max 2,000). The mode you connect with decides what happens to that buffer - and it applies to that connection only; nothing is remembered between connects:
- Live (default, no parameters): the buffer is discarded; you receive events from connect-time forward. Best for real-time consumers of high-volume events.
- Resume (
?mode=resume, orlastEventIdon WebSocket / theLast-Event-IDheader on SSE): the buffer is replayed first, then live events follow.
To never miss events across reconnects, always pass the last event ID you processed when reconnecting (native EventSource does this automatically). See Reconnection & Event Replay for the full scenario breakdown.
Stream Types
Choose the right stream type for your use case:
| Type | What It Monitors | Example Use Case | Learn More |
|---|---|---|---|
| Events | Package event types | React to DEX swaps, NFT mints | Includes field filtering |
| Addresses | Wallet activity | Track treasury or user wallets | Sender & receiver activity |
| Coins | Token balance changes | Payment confirmations | Filter by coin type |
| Objects | Object mutations | Watch NFTs or AMM pools | Track ownership changes |
Warp vs Webhooks
| Feature | Warp (WebSocket/SSE) | Webhooks |
|---|---|---|
| Connection Type | Client-initiated, persists | Server pushes to your endpoint |
| Endpoint Setup | No public endpoint needed | Requires HTTPS endpoint |
| Latency | Lower (persistent conn) | Slightly higher (HTTP request) |
| Best For | Real-time dashboards, apps | Backend services, integrations |
| Reconnection | Live by default; mode=resume/lastEventId to replay | N/A (retry on delivery failure) |
| Browser Support | Native EventSource API | N/A |
Key Features
- Real-time streaming via WebSocket or SSE
- Multiple filter types: Events, addresses, coins, and objects
- Event field filtering: Filter events by specific field values
- Live by default: real-time from connect; opt into backlog replay with
mode=resumeorlastEventId - Exactly-once delivery: Available via WebSocket with client ACKs
- Credit billing: Charged per event + connection time
- Dashboard UI: Manage streams, view connection status
Quick Start
1. Create a Stream
Add a stream via the dashboard:
- Navigate to Warp Streams
- Click Add Stream
- Select the stream type (Event, Address, Coin, or Object)
- Configure your filters
- Save and copy the Stream ID
2. Connect to the Stream
Using WebSocket (recommended, with query params):
const streamId = 'your-stream-id'
const apiKey = 'your-api-key'
const ws = new WebSocket(`wss://mainnet-api.inodra.com/v1/warp/${streamId}/ws?api_key=${apiKey}`)
ws.onmessage = (event) => {
const msg = JSON.parse(event.data)
console.log(msg.event, msg.data)
// Send ACK for exactly-once delivery
if (msg.id) {
ws.send(JSON.stringify({ type: 'ack', id: msg.id }))
}
}Using SSE (fetch with x-api-key header):
const streamId = 'your-stream-id'
const apiKey = 'your-api-key'
const abort = new AbortController()
process.on('SIGINT', () => abort.abort())
const res = await fetch(`https://mainnet-api.inodra.com/v1/warp/${streamId}/stream`, {
headers: { 'x-api-key': apiKey },
signal: abort.signal
})
let buffer = ''
for await (const chunk of res.body) {
buffer += new TextDecoder().decode(chunk)
const parts = buffer.split('\n\n')
buffer = parts.pop()
for (const part of parts) {
const dataLine = part.split('\n').find((l) => l.startsWith('data:'))
if (dataLine) console.log(JSON.parse(dataLine.slice(5)))
}
}Using native EventSource (API key as query parameter):
Native browser EventSource can't set custom headers, but it works with the api_key query parameter and gets automatic reconnection with Last-Event-ID for free:
const streamId = 'your-stream-id'
const apiKey = 'your-api-key'
const es = new EventSource(
`https://mainnet-api.inodra.com/v1/warp/${streamId}/stream?api_key=${apiKey}`
)
es.addEventListener('connected', (e) => {
console.log('Connected:', JSON.parse(e.data))
})
// Listen for your stream type: 'event', 'address', 'coin', or 'object'
es.addEventListener('event', (e) => {
console.log(JSON.parse(e.data))
})Note: Query-parameter authentication is supported for compatibility, but we don't recommend it where headers are possible - the key can end up in server logs and browser history. Prefer
fetchwith thex-api-keyheader (above) or theeventsourcenpm package in Node.js. You can rotate keys instantly from the dashboard if one leaks.
3. Handle Events
The stream sends different event types:
connected- Connection established (includesconnId,subscriptionId,subscriptionType,protocol)event/address/coin/object- Blockchain activity, named after your stream type (see Event, Address, Coin, and Object stream pages for payloads)quota_exceeded- Credit limit reached, the connection closes right after (WebSocket close code1008)error- Connection-level error, e.g.STREAM_ALREADY_CONNECTEDwhen the stream already has an active connection (one connection per stream)
See Setup & Connection for complete examples with error handling and reconnection logic.
Common Use Cases
Real-Time Dashboards
Build live dashboards that update instantly:
- Trading interfaces: Show price changes and swaps in real-time
- Portfolio trackers: Display balance updates as they happen
- Analytics dashboards: Stream metrics without polling
Browser Applications
Perfect for frontend applications:
- Notification systems: Alert users of wallet activity
- Game state updates: Sync on-chain game state instantly
- Marketplace feeds: Show new listings and sales live
Backend Services
Use with server-side applications:
- Event processing: React to on-chain events immediately
- Data pipelines: Stream blockchain data to your systems
- Alert systems: Trigger notifications based on activity
Next Steps
- Setup & Connection - Authentication, connection handling, best practices
- Event Streams - Stream Move events with field filtering
- Address Streams - Stream wallet activity
- Coin Streams - Stream balance changes
- Object Streams - Stream object mutations
- Webhooks - Alternative push-based delivery for backend services