SENDY

Token stream

This stream attaches to the same namespace as the firehose documented in Trade stream, but Sendy evaluates the SPL mint before emitting: you only receive trade payloads whose tokenAddress equals your tokenMint. Ideal for alerting on one pool, powering a coin detail mirror, or throttling egress when broader coverage is irrelevant.

Why not filter locally?

  • Bandwidth stays low when wallets are noisy on many unrelated tokens.
  • Consumers remain tiny—no branching tree of socket connections per ticker.
  • Eligibility semantics stay authoritative on the API (quota still applies per connection).

Mint validation

Provide a canonical Solana pubkey string. Malformed mints yield error with invalid_address before streaming starts—catch it alongside other handshake failures documented in Authentication.

Official TypeScript SDK

connectWalletTradesForToken(wallet, mint) injects tokenMint into auth automatically.

import { SendyClient, type WalletTradeStreamReady } from '@mvritz/sendy-sdk';

const MINT = 'So11111111111111111111111111111111111111112';
const client = new SendyClient({ apiKey: process.env.SENDY_API_KEY! });
const socket = client.connectWalletTradesForToken('YOUR_WALLET', MINT);

socket.on('ready', (p: WalletTradeStreamReady) => {
  console.assert(p.filter === 'token');
  console.assert(p.tokenMint === MINT);
});

Handshake with mint filter

  • Namespace remains /sdk/wallet; only the handshake payload differs.
  • Hosts & paths match Trade stream.

Auth JSON

{
  "apiKey": "sendy_…",
  "walletAddress": "<eligible solana pubkey>",
  "tokenMint": "<mint pubkey to match>"
}

Signals

  • ready filter: "token"; tokenMint echoes the subscribed mint.
  • trade — mint always matches tokenMint
  • error — handshake issues including mint validation

Implementations

Mirrors the multilingual layout of the sibling page: drop in your mint constant, reconnect if the pair changes. Rust crates are the same as the full-wallet variant (rust_socketio, tokio, serde_json).

connect — one mint only
import { io } from 'socket.io-client';

const TOKEN_MINT = 'So11111111111111111111111111111111111111112';

const socket = io('https://api.sendy.lol/sdk/wallet', {
  path: '/socket.io',
  transports: ['websocket'],
  auth: {
    apiKey: process.env.SENDY_API_KEY!,
    walletAddress: 'YOUR_WALLET',
    tokenMint: TOKEN_MINT,
  },
});

socket.on('ready', (p) => {
  console.assert(p.filter === 'token');
  console.assert(p.tokenMint === TOKEN_MINT);
});

socket.on('trade', (trade) => {
  console.assert(trade.tokenAddress === TOKEN_MINT);
});

Manual CONNECT line

Paste the CONNECT line after Engine.IO establishes the websocket. Compared to the unrestricted stream documented on the other page, the JSON blob adds tokenMint—everything else about wscat limitations (raw framing, no automatic backoff) stays identical.