Langganan WebSocket

Hubungkan ke endpoint WebSocket BlockVectra untuk eth_subscribe newHeads dan logs. Pelajari metode koneksi, aturan filter, backoff penyambungan kembali, dan pemulihan.

BlockVectra menyediakan koneksi WebSocket aman (wss://) untuk streaming langganan peristiwa Ethereum secara real-time bersama permintaan JSON-RPC standar.

Memilih WebSocket, Webhook, atau polling

Gunakan WebSocket untuk newHeads langsung dan logs terfilter ketika aplikasi Anda dapat mempertahankan koneksi. Gunakan Blockchain Webhook API untuk menerima aktivitas dompet yang dipantau di endpoint HTTPS, dengan verifikasi tanda tangan body mentah, percobaan ulang, dan replay kecocokan yang disimpan. Gunakan polling HTTP untuk pemantauan pembayaran ERC-20 terjadwal dan backfill log historis. Panduan stablecoin juga menunjukkan penerima Webhook USDT / USDC. Untuk perbandingan arsitektur berdasarkan dukungan chain, persyaratan penerima, dan kompromi pemulihan bagi pengembang dan AI Agent, lihat panduan memilih Webhook, WebSocket, atau polling RPC.

Dukungan WebSocket berasal dari ws dan subscriptions dalam GET /v1/chains; dukungan Push berasal dari daftar GET /v1/push/chains yang memerlukan autentikasi. Chain tanpa WebSocket tetap dapat menggunakan Webhook alamat jika tercantum di sana.

Koneksi WebSocket yang terputus memerlukan langganan ulang dan backfill; koneksi tersebut tidak menerbitkan peristiwa kontrol Push subscription.gap atau chain.reorg. Untuk Webhook, celah memerlukan pemindaian rentang; pemberitahuan reorg memerlukan peristiwa yang diganti ditandai atau dibuang sebelum menyimpan peristiwa kanonis yang dikirim ulang otomatis. Replay Push mengirim ulang kecocokan yang disimpan, bukan data sebelum alamat atau chain ditambahkan atau saat langganan offline. Tinjau aturan penagihan dan referensi error saat mengimplementasikan pemulihan.

Chain yang tersedia

Anda dapat memeriksa apakah langganan WebSocket aktif di suatu jaringan dengan membaca ws (boolean) dan subscriptions (array tipe yang didukung) dalam GET /v1/chains.

Tabel di bawah mencerminkan jaringan dengan dukungan WebSocket yang diaktifkan:

RantaiEndpoint WebSocket (kunci di path)
Robinhood Chainwss://api.blockvectra.com/v1/robinhood_mainnet/{api_key}
Robinhood Chain Testnetwss://api.blockvectra.com/v1/robinhood_testnet/{api_key}

Koneksi dan autentikasi

Klien membuat koneksi WebSocket TLS aman (wss://). API key dapat disediakan dengan dua cara:

  • API key pada jalur: wss://api.blockvectra.com/v1/{chain}/{api_key}
  • API key pada header: wss://api.blockvectra.com/v1/{chain} dengan header x-api-key: {api_key} atau Authorization: Bearer {api_key} saat handshake HTTP Upgrade.

Jika API key ada pada jalur, API key tersebut digunakan dan kedua header autentikasi diabaikan. Tanpa API key pada jalur, x-api-key yang tidak kosong diprioritaskan dibandingkan Authorization: Bearer. API WebSocket browser tidak dapat mengatur header ini; gunakan URL dengan API key pada jalur.

Pemeriksaan penerimaan handshake

Handshake dapat gagal dengan:

  • Autentikasi: API key yang tidak disertakan mengembalikan HTTP 401 (missing_api_key); API key yang tidak dikenal, dinonaktifkan, atau dicabut mengembalikan HTTP 401 (invalid_api_key); jika autentikasi tidak tersedia sementara, responsnya HTTP 503 (auth_unavailable).
  • Saldo akun: Akun dengan saldo prabayar nol atau negatif mengembalikan HTTP 402 (balance_exhausted); jika state penagihan tidak dapat dipastikan, responsnya HTTP 503 (billing_unavailable).
  • Batas koneksi: Melampaui batas per API key (20 koneksi) atau batas per akun (50 koneksi) mengembalikan HTTP 429 (ws_connection_limit).
  • Ketersediaan chain: Meminta chain yang tidak dikenal atau tidak dilayani mengembalikan HTTP 404 (unknown_chain).
  • Kapasitas server: Ketika server sibuk atau kelebihan beban, handshake mengembalikan HTTP 503 (overloaded) dengan header Retry-After.

Setelah terhubung, klien dapat mengirim permintaan JSON-RPC 2.0 standar (seperti eth_blockNumber atau eth_call) dan metode kontrol langganan dalam format frame teks UTF-8.

Aturan penagihan

  • Membuat koneksi, mempertahankan koneksi yang tidak aktif, dan heartbeat ping/pong tidak ditagih.
  • Panggilan eth_subscribe dan eth_unsubscribe yang berhasil ditagih, termasuk pembatalan langganan yang mengembalikan false; panggilan gagal tidak ditagih. Panggilan JSON-RPC biasa mengikuti aturan penagihan JSON-RPC.
  • Notifikasi newHeads dihitung sekali per hash blok per koneksi, terlepas dari jumlah langganan newHeads pada koneksi tersebut.
  • Notifikasi logs dihitung sekali per langganan per hash blok dan fase yang memiliki log cocok; blok tanpa kecocokan tidak ditagih. Beberapa log yang cocok dalam blok dan fase yang sama tidak melipatgandakan biaya. Langganan terpisah dihitung secara terpisah, meskipun filternya tumpang tindih. Log reorganisasi (removed: true) membentuk unit terpisah; blok pengganti pada tinggi yang sama memiliki hash berbeda dan merupakan unit berbeda.
  • Notifikasi hanya ditagih setelah berhasil ditulis ke buffer pengiriman socket; notifikasi dalam antrean atau yang dibuang tanpa ditulis tidak ditagih. Notifikasi yang masuk antrean sebelum jawaban eth_unsubscribe dihitung jika ditulis. Pesan WebSocket tidak membawa header penagihan HTTP; lihat penggunaan akun untuk CU yang diukur.

Metode langganan

API mengimplementasikan antarmuka pub/sub Ethereum standar: eth_subscribe dan eth_unsubscribe.

newHeads

Menerbitkan objek header blok baru setiap kali blok baru ditambahkan ke head chain.

  • Permintaan langganan:
    {"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["newHeads"]}
  • Respons langganan: Mengembalikan pengenal langganan heksadesimal yang bersifat opaque:
    {"jsonrpc":"2.0","id":1,"result":"0x1"}
  • Frame notifikasi push:
    {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x1","result":{"number":"0x1b4","hash":"0x..."}}}

logs

Menerbitkan peristiwa log yang cocok dengan kriteria filter yang ditentukan.

  • Persyaratan filter: Setiap filter langganan logs harus menentukan address (alamat kontrak atau array alamat) atau topic0 (posisi topic pertama, bukan null). Filter yang tidak menentukan keduanya (seperti {} atau {"topics":[null,"0x..."]}) ditolak dengan kode error -32602 (logs_filter_required).

  • Batas filter: Maksimal 100 alamat; maksimal 4 posisi topic dengan maksimal 16 hash kandidat per posisi.

  • Kapasitas filter: Jika filter log aktif mencapai kapasitas, langganan mengembalikan kode error -32022 (ws_filter_capacity).

  • Reorganisasi chain: Jika blok dihapus akibat reorg chain, notifikasi log untuk log yang dihapus membawa "removed": true.

  • Permintaan langganan:

    {"jsonrpc":"2.0","id":2,"method":"eth_subscribe","params":["logs",{"address":"0x1234567890123456789012345678901234567890"}]}

eth_unsubscribe

Mengakhiri langganan aktif menggunakan pengenal langganannya.

  • Permintaan pembatalan langganan:
    {"jsonrpc":"2.0","id":3,"method":"eth_unsubscribe","params":["0x1"]}
  • Respons pembatalan langganan:
    {"jsonrpc":"2.0","id":3,"result":true}

Contoh yang dapat dijalankan

Hubungkan menggunakan viem v2 melalui createPublicClient dan transport webSocket. Ganti {chain} dengan pengenal chain tujuan dan {api_key} dengan API key Anda:

import { createPublicClient, webSocket } from 'viem';

const apiKey = process.env.BLOCKVECTRA_API_KEY || '{api_key}';
const url = `wss://api.blockvectra.com/v1/robinhood_mainnet/${apiKey}`;

const client = createPublicClient({
  transport: webSocket(url),
});

// 1. Subscribe to new block headers (newHeads)
const unwatchBlocks = client.watchBlocks({
  onBlock: (block) => {
    console.log('New block header received:', block.number, block.hash);
  },
  onError: (error) => {
    console.error('watchBlocks error:', error);
  },
});

// 2. Subscribe to contract event logs (filter requires address or topic0)
const unwatchEvents = client.watchEvent({
  address: '0x1234567890123456789012345678901234567890',
  onLogs: (logs) => {
    console.log('Matching logs received:', logs);
  },
  onError: (error) => {
    console.error('watchEvent error:', error);
  },
});

Kode penutupan dan tindakan klien

Ketika server mengakhiri sesi WebSocket, server mengirim frame Close dengan kode penutupan tertentu dan alasan singkat. Tabel di bawah mencantumkan kode penutupan yang diterbitkan server dan tindakan yang disarankan:

Kode penutupanString alasanKeteranganDapat dicoba ulangTindakan klien
1001idleKoneksi tidak aktif tanpa langganan atau pesan selama 3600 detik (1 jam)YaSambungkan kembali sesuai kebutuhan.
1003binary frames are not acceptedFrame WebSocket biner diterima; hanya frame teks UTF-8 yang diterimaTidakJangan menyambungkan kembali secara otomatis. Perbarui klien untuk mengirim frame teks.
1009message too largePayload masuk melebihi 1 MiBTidakJangan menyambungkan kembali secara otomatis. Pecah permintaan besar atau kurangi ukuran payload.
1012service restartServer dimulai ulang, atau sesi mencapai masa hidup maksimum (24 jam)YaSambungkan kembali dengan backoff berjitter acak, buat ulang langganan, dan lakukan backfill data yang terlewat.
1013chain unavailableChain tidak tersediaYaSambungkan kembali dengan backoff eksponensial full jitter, buat ulang langganan, dan lakukan backfill data yang terlewat.
1013overloadedServer kelebihan beban sementaraYaSambungkan kembali dengan backoff eksponensial full jitter, buat ulang langganan, dan lakukan backfill data yang terlewat.
4402insufficient balanceSaldo akun habisTidakJangan menyambungkan kembali secara otomatis. Top up saldo Anda, lalu sambungkan kembali.
4404invalid api keyAPI key tidak dikenal, dinonaktifkan, atau dicabutTidakJangan menyambungkan kembali secara otomatis. Verifikasi atau rotasi API key di konsol sebelum menyambungkan kembali.
4408slow consumerServer menutup sesi yang antrean push-nya melampaui 512 KiB dan membuang notifikasi tertunda; klien mungkin tidak menerima frame penutupan (browser melaporkan 1006)YaPerlakukan koneksi terputus tak terduga (tidak menerima frame penutupan, browser melaporkan 1006) seperti 4408: sambungkan kembali dengan backoff, buat ulang langganan, dan lakukan backfill data yang dibuang dengan eth_getLogs; kurangi langganan, atau baca lebih cepat.
4429push rate exceededLaju notifikasi melebihi 1,000 push/detikYaKurangi langganan atau persempit filter; sambungkan kembali dengan backoff, berlangganan ulang, dan lakukan backfill.
4503billing unavailablePenagihan tidak tersedia sementaraYaKondisi sementara; sambungkan kembali dengan backoff eksponensial full jitter.

Penyambungan kembali dan backoff eksponensial

Untuk mencegah lonjakan penyambungan kembali serentak ketika koneksi terputus, klien harus mengimplementasikan backoff eksponensial dengan full jitter:

  • Rumus backoff: Sebelum percobaan penyambungan kembali ke-n (n = 0, 1, 2, ...), tunggu durasi yang dipilih secara acak dari distribusi seragam:
    delay = random(0, min(20s, 0.5s * 2^n))
  • Reset penghitung: Reset penghitung percobaan ulang n menjadi 0 hanya setelah mempertahankan koneksi stabil tanpa terputus selama setidaknya 60 seconds.
  • Kode penutupan 1012: Tambahkan penundaan awal acak sebelum percobaan penyambungan kembali pertama untuk menghindari lonjakan penyambungan kembali serentak.
  • Kode yang tidak dapat dicoba ulang: Jangan menyambungkan kembali secara otomatis pada 4402, 4404, 1003, atau 1009.

Backfill data yang terlewat setelah penyambungan kembali

Langganan WebSocket tidak bertahan lintas koneksi; notifikasi yang diterbitkan saat koneksi terputus tidak disimpan di server. Setelah tersambung kembali, klien sebaiknya menjalankan strategi mengejar ketertinggalan:

  1. Backfill log dengan eth_getLogs:
    • Simpan secara persisten nomor blok tertinggi yang berhasil diproses (last_processed_block).
    • Segera panggil eth_subscribe("logs", ...) saat tersambung kembali untuk menangkap peristiwa langsung.
    • Kueri blok yang terlewat melalui eth_getLogs dengan fromBlock: last_processed_block + 1 dan toBlock: "latest" (atau blok pertama yang diterima dari aliran langsung).
    • Jika celah koneksi terputus melebihi max_logs_block_range jaringan (dari GET /v1/chains), bagi kueri menjadi potongan yang tidak melebihi batas tersebut.
    • Lakukan deduplikasi entri log di batas kueri menggunakan tuple unik (blockHash, transactionHash, logIndex).
  2. Backfill header blok dengan eth_getBlockByNumber:
    • Catat nomor dan hash blok terbaru yang diterima sebelum koneksi terputus.
    • Berlangganan ulang ke newHeads.
    • Kueri eth_getBlockByNumber("latest", false) dan ambil blok perantara yang terlewat secara berurutan. Verifikasi kesinambungan chain melalui parentHash untuk mendeteksi reorg.

Batas

BatasNilaiHasil saat terlampaui
Langganan per koneksi WebSocket100-32022 subscription_limit
Langganan newHeads per koneksi WebSocket4-32022 subscription_limit
Persyaratan filter langganan logsHarus menentukan address atau topic0 (posisi pertama dalam topics)-32602 logs_filter_required

Langkah berikutnya

Terakhir diperbarui:

Di halaman ini