Streaming
For wallets with hundreds or thousands of token accounts, a single REST call may be slow. The streamWalletAssets method opens a WebSocket connection and yields items in chunks as they are discovered, so your UI can render progressively.
Requirements
- The client must be constructed with a
sessionToken(API keys are not accepted on the WebSocket path). - The session must include the
wallet:streamscope.
Usage
import { BurnerClient, SessionScope } from '@burnandclaim/sdk'
// Backend: create a session with the stream scope
const session = await server.createSession({
walletAddress,
scopes: [SessionScope.WalletStream, SessionScope.WalletRead],
ttlSeconds: 600,
})
// Frontend: stream assets
const client = new BurnerClient({ sessionToken: session.token })
const allItems: WalletItem[] = []
for await (const chunk of client.streamWalletAssets(walletAddress)) {
allItems.push(...chunk.items)
updateUI(allItems, chunk.counts)
if (chunk.complete) {
console.log(`Scan complete. ${allItems.length} items found.`)
}
}Chunk shape
Each chunk is a WalletAssetsChunk:
interface WalletAssetsChunk {
walletAddress: string
items: WalletItem[] // items in this chunk only
chunkIndex: number // monotonic, starting at 0
complete: boolean // true on the final chunk
counts: Record<WalletItemType, number> // running totals
}Concatenate items across chunks to build the full asset list. The counts field gives running totals that become final when complete is true.
Chunk size
By default, the server sends up to 50 items per chunk. You can tune this:
for await (const chunk of client.streamWalletAssets(walletAddress, {
chunkSize: 25, // smaller chunks for snappier UI updates
})) {
// ...
}Smaller chunk sizes mean more WebSocket messages but faster time-to-first-render. Larger values reduce overhead for very large wallets.
When to use streaming vs REST
| Scenario | Recommendation |
|---|---|
| Wallet with < 100 accounts | Use getWalletAssets() — single round trip is fast enough. |
| Wallet with 100+ accounts | Use streamWalletAssets() — items appear as they are found. |
| Server-side batch processing | Use getWalletAssets() — simpler, no WebSocket needed. |
| Real-time UI with progress indicator | Use streamWalletAssets() — show a progress bar using chunkIndex. |
Connection lifecycle
The async generator manages the WebSocket connection automatically:
- The connection opens when iteration begins.
- The connection closes when the generator completes (final chunk), when you
breakout of the loop, or if an error occurs. - You do not need to call
disconnect()or clean up manually.
// Early exit is safe -- the socket is cleaned up automatically
for await (const chunk of client.streamWalletAssets(walletAddress)) {
allItems.push(...chunk.items)
if (allItems.length >= 50) {
break // connection is closed automatically
}
}Error handling
Stream errors are thrown as standard Error instances inside the async generator:
try {
for await (const chunk of client.streamWalletAssets(walletAddress)) {
renderChunk(chunk)
}
} catch (err) {
if (err instanceof Error) {
if (err.message.includes('session token')) {
// missing or invalid session token
} else if (err.message.includes('connect')) {
// WebSocket connection failed
} else {
// server-side stream error
}
}
}Protocol details
Under the hood, the SDK connects to the /burner Socket.IO namespace at wss://api.aerosol.com/burner with WebSocket transport. Authentication is passed via the auth.sessionToken field on the Socket.IO handshake.
Events:
| Event | Direction | Payload |
|---|---|---|
streamWalletAssets | Client to server | { walletAddress, chunkSize? } |
walletAssetsChunk | Server to client | WalletAssetsChunk |
walletAssetsError | Server to client | string (error message) |