Realtime: SSE & WebSocket
Dua jalur data real-time: Server-Sent Events dari API BaniPool untuk event akun, dan WebSocket (WSS) RPC jaringan untuk harga & blok langsung dari blockchain.
Server-Sent Events (SSE)
GET /v1/events/stream mengalirkan event milik sesi/key Anda (transaksi final/gagal, posisi keluar rentang, eksekusi strategi) plus data.degraded publik. Setiap event membawa id sebagai cursor; sambung ulang dengan Last-Event-ID (otomatis di EventSource) atau ?after=. Koneksi ditutup server ±100 detik untuk browser dan 15 menit untuk API key — cukup sambung ulang.
// Browser (sesi same-origin; jangan menaruh API key di URL)
const es = new EventSource('/api/v1/events/stream');
es.addEventListener('transaction.finalized', (e) => console.log(e.lastEventId, JSON.parse(e.data)));
es.addEventListener('position.out_of_range', (e) => console.log(JSON.parse(e.data)));
es.addEventListener('reset', () => { /* cursor kedaluwarsa: ambil snapshot baru */ });// Node.js / server dengan API key (header, bukan query string)
const res = await fetch('https://banipool.com/api/v1/events/stream', {
headers: { 'x-api-key': process.env.BANIPOOL_API_KEY!, accept: 'text/event-stream' },
});
const reader = res.body!.pipeThrough(new TextDecoderStream()).getReader();
let buf = '';
for (;;) {
const { value, done } = await reader.read();
if (done) break; // sambung ulang dengan header Last-Event-ID
buf += value;
let i;
while ((i = buf.indexOf('\n\n')) >= 0) {
const frame = buf.slice(0, i); buf = buf.slice(i + 2);
const field = (k: string) => frame.split('\n').find((l) => l.startsWith(k + ': '))?.slice(k.length + 2);
if (field('event')) console.log(field('id'), field('event'), field('data'));
}
}| Event | Kapan |
|---|---|
transaction.finalized | Transaksi yang Anda buat lewat BaniPool final di blockchain. |
transaction.failed | Transaksi revert/gagal. |
position.out_of_range | Posisi dalam aturan keluar rentang harga. |
strategy.executed | Aturan paper/notify terpicu. |
data.degraded | Sumber data publik sebuah jaringan menurun (publik). |
reset / revoked | Cursor lewat retensi / key dicabut atau sesi berakhir. |
WebSocket RPC (WSS)
API BaniPool tidak membuka WebSocket sendiri; data real-time on-chain (blok baru, event swap pool) dibaca langsung dari WSS RPC jaringan. Situs memakainya untuk quote Zap live, dan Anda dapat memasang WSS sendiri di /settings. Untuk aplikasi Anda gunakan WSS penyedia RPC (Alchemy, QuickNode, Infura, dRPC, atau RPC resmi jaringan).
import { createPublicClient, webSocket, parseAbiItem } from 'viem';
import { base } from 'viem/chains';
const client = createPublicClient({
chain: base,
transport: webSocket(process.env.BASE_WSS_URL), // wss://base-mainnet.g.alchemy.com/v2/<KEY>
});
// Blok baru
client.watchBlockNumber({ onBlockNumber: (n) => console.log('block', n) });
// Event Swap pool Uniswap v3 (alamat pool dari GET /v1/pools)
client.watchEvent({
address: '0xd0b53D9277642d899DF5C87A3966A349A798F224', // WETH/USDC 0,05% Base
event: parseAbiItem('event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick)'),
onLogs: (logs) => logs.forEach((l) => console.log('tick', l.args.tick)),
});// Tanpa library: JSON-RPC eth_subscribe langsung
const ws = new WebSocket(process.env.BASE_WSS_URL);
ws.onopen = () => ws.send(JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_subscribe', params: ['newHeads'] }));
ws.onmessage = (m) => {
const msg = JSON.parse(m.data);
if (msg.method === 'eth_subscription') console.log('block', parseInt(msg.params.result.number, 16));
};URL WSS penyedia biasanya memuat kunci akun (mis. Alchemy). Simpan sebagai rahasia di server Anda; di browser, gunakan pengaturan WSS situs yang menyimpannya terenkripsi secara lokal.