Skip to content

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)      │             │
└────────────────┘      └─────────────┘                          └─────────────┘
  1. Create a stream in the Inodra dashboard
  2. Connect via WebSocket or SSE
  3. Receive real-time events as they occur on-chain

Connection Protocols

ProtocolDelivery GuaranteeBest For
WebSocket (recommended)Exactly-onceWhen you need delivery guarantees
SSEAt-least-onceHigher 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, or lastEventId on WebSocket / the Last-Event-ID header 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:

TypeWhat It MonitorsExample Use CaseLearn More
EventsPackage event typesReact to DEX swaps, NFT mintsIncludes field filtering
AddressesWallet activityTrack treasury or user walletsSender & receiver activity
CoinsToken balance changesPayment confirmationsFilter by coin type
ObjectsObject mutationsWatch NFTs or AMM poolsTrack ownership changes

Warp vs Webhooks

FeatureWarp (WebSocket/SSE)Webhooks
Connection TypeClient-initiated, persistsServer pushes to your endpoint
Endpoint SetupNo public endpoint neededRequires HTTPS endpoint
LatencyLower (persistent conn)Slightly higher (HTTP request)
Best ForReal-time dashboards, appsBackend services, integrations
ReconnectionLive by default; mode=resume/lastEventId to replayN/A (retry on delivery failure)
Browser SupportNative EventSource APIN/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=resume or lastEventId
  • 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:

  1. Navigate to Warp Streams
  2. Click Add Stream
  3. Select the stream type (Event, Address, Coin, or Object)
  4. Configure your filters
  5. Save and copy the Stream ID

2. Connect to the Stream

Using WebSocket (recommended, with query params):

javascript
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):

javascript
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:

javascript
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 fetch with the x-api-key header (above) or the eventsource npm 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 (includes connId, 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 code 1008)
  • error - Connection-level error, e.g. STREAM_ALREADY_CONNECTED when 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

Released under the MIT License.