การติดตามผ่าน WebSocket

เชื่อมต่อกับ WebSocket endpoint ของ BlockVectra สำหรับ eth_subscribe newHeads และ logs เรียนรู้วิธีการเชื่อมต่อ, กฎของตัวกรอง, การหน่วงเวลาเชื่อมต่อใหม่ และการกู้คืนข้อมูล

BlockVectra ให้บริการการเชื่อมต่อ WebSocket ที่ปลอดภัย (wss://) สำหรับสตรีมการติดตามเหตุการณ์ Ethereum แบบเรียลไทม์ควบคู่ไปกับคำขอ JSON-RPC มาตรฐาน

Choose WebSocket, Webhook or polling

ใช้ WebSocket สำหรับ newHeads สดและ logs ที่กรองแล้วเมื่อแอปพลิเคชันของคุณสามารถรักษาการเชื่อมต่อไว้ได้ ใช้ Blockchain Webhook API เพื่อรับกิจกรรมของกระเป๋าเงินที่ติดตาม ณ HTTPS endpoint พร้อม การตรวจสอบลายเซ็น raw-body, การลองใหม่ และการ replay ข้อมูลที่ตรงกันซึ่งเก็บรักษาไว้ ใช้ การโพลล์ HTTP สำหรับการตรวจสอบการชำระเงิน ERC-20 ตามกำหนดเวลาและการดึงข้อมูล log ย้อนหลัง คู่มือสเตเบิลคอยน์ยังแสดง ตัวรับ Webhook สำหรับ USDT / USDC ด้วย สำหรับการเปรียบเทียบเชิงสถาปัตยกรรมข้ามการรองรับของเชน ข้อกำหนดของตัวรับ และข้อดีข้อเสียในการกู้คืนสำหรับนักพัฒนาและ AI Agent โปรดดู คู่มือการเลือกระหว่าง Webhook, WebSocket หรือการโพลล์ RPC

การรองรับ WebSocket มาจาก ws และ subscriptions ใน GET /v1/chains; การรองรับ Push มาจากรายการ GET /v1/push/chains ที่ผ่านการยืนยันตัวตนแล้ว เชนที่ไม่มี WebSocket ยังคงสามารถใช้ Webhook สำหรับแอดเดรสได้หากมีรายชื่ออยู่ที่นั่น

การหลุดการเชื่อมต่อของ WebSocket กำหนดให้ต้องสมัครรับข้อมูลใหม่และดึงข้อมูลย้อนหลัง; โดยจะไม่ส่งเหตุการณ์ควบคุมของ Push อย่าง subscription.gap หรือ chain.reorg ออกมา สำหรับ Webhook ช่องว่างจะต้องสแกนตามช่วง; การแจ้งเตือน reorg กำหนดให้ต้องทำเครื่องหมายหรือละทิ้งเหตุการณ์ที่ถูกแทนที่ก่อนเก็บเหตุการณ์ canonical ที่ส่งซ้ำโดยอัตโนมัติ Push replay จะส่งซ้ำเฉพาะข้อมูลที่ตรงกันซึ่งเก็บรักษาไว้ ไม่รวมข้อมูลก่อนที่จะเพิ่มแอดเดรสหรือเชน หรือในขณะที่การติดตามอยู่ในสถานะ offline โปรดตรวจสอบ กฎการเรียกเก็บเงิน และ เอกสารอ้างอิงข้อผิดพลาด เมื่อนำการกู้คืนไปใช้งาน

Available chains

คุณสามารถตรวจสอบว่าการติดตามผ่าน WebSocket เปิดใช้งานบนเครือข่ายหรือไม่ โดยการอ่าน ws (boolean) และ subscriptions (อาร์เรย์ของประเภทที่รองรับ) ใน GET /v1/chains

ตารางด้านล่างแสดงเครือข่ายที่เปิดใช้งานการรองรับ WebSocket:

เชนเอนด์พอยต์ WebSocket (คีย์ในพาธ)
Robinhood Chainwss://api.blockvectra.com/v1/robinhood_mainnet/{api_key}
Robinhood Chain Testnetwss://api.blockvectra.com/v1/robinhood_testnet/{api_key}

Connection and authentication

ไคลเอนต์สร้างการเชื่อมต่อ WebSocket ด้วย TLS ที่ปลอดภัย (wss://) โดยสามารถระบุ API key ได้สองวิธี:

  • Path key: wss://api.blockvectra.com/v1/{chain}/{api_key}
  • Header key: wss://api.blockvectra.com/v1/{chain} พร้อมส่วนหัว x-api-key: {api_key} หรือ Authorization: Bearer {api_key} ในระหว่างการแฮนด์เชก HTTP Upgrade

เมื่อใช้คีย์ในพาธ ระบบจะใช้คีย์ในพาธและละเว้นส่วนหัวการยืนยันตัวตนทั้งสองรายการ หากไม่มีคีย์ในพาธ ค่า x-api-key ที่ไม่ว่างจะมีลำดับความสำคัญสูงกว่า Authorization: Bearer WebSocket API ของเบราว์เซอร์ไม่สามารถกำหนดส่วนหัวเหล่านี้ได้; ให้ใช้ URL แบบคีย์ในพาธ

Handshake admission checks

การแฮนด์เชกอาจล้มเหลวด้วยสาเหตุต่อไปนี้:

  • Authentication: การไม่ระบุ API key จะส่งกลับ HTTP 401 (missing_api_key); API key ที่ไม่รู้จัก ปิดใช้งาน หรือถูกเพิกถอน จะส่งกลับ HTTP 401 (invalid_api_key); หากระบบยืนยันตัวตนไม่พร้อมใช้งานชั่วคราว การตอบกลับจะเป็น HTTP 503 (auth_unavailable)
  • Account balance: บัญชีที่มียอดคงเหลือแบบชำระล่วงหน้าเป็นศูนย์หรือติดลบจะส่งกลับ HTTP 402 (balance_exhausted); หากไม่สามารถยืนยันสถานะการเรียกเก็บเงินได้ การตอบกลับจะเป็น HTTP 503 (billing_unavailable)
  • Connection limits: การเชื่อมต่อเกินขีดจำกัดต่อคีย์ (20 การเชื่อมต่อ) หรือขีดจำกัดต่อบัญชี (50 การเชื่อมต่อ) จะส่งกลับ HTTP 429 (ws_connection_limit)
  • Chain availability: การขอเชนที่ไม่รู้จักหรือไม่ให้บริการจะส่งกลับ HTTP 404 (unknown_chain)
  • Server capacity: เมื่อเซิร์ฟเวอร์ไม่ว่างหรือโอเวอร์โหลด การแฮนด์เชกจะส่งกลับ HTTP 503 (overloaded) พร้อมส่วนหัว Retry-After

เมื่อเชื่อมต่อแล้ว ไคลเอนต์สามารถส่งคำขอ JSON-RPC 2.0 มาตรฐาน (เช่น eth_blockNumber หรือ eth_call) และเมธอดควบคุมการติดตามในรูปแบบ text frame เข้ารหัส UTF-8 ได้

Billing rules

  • การสร้างการเชื่อมต่อ, การเปิดการเชื่อมต่อทิ้งไว้โดยไม่มีกิจกรรม และ ping/pong heartbeat ไม่คิดค่าบริการ
  • การเรียก eth_subscribe และ eth_unsubscribe ที่สำเร็จจะคิดค่าบริการ รวมถึงการยกเลิกการติดตามที่ส่งกลับ false; การเรียกที่ล้มเหลวจะไม่คิดค่าบริการ การเรียก JSON-RPC ทั่วไปเป็นไปตาม กฎการเรียกเก็บเงินของ JSON-RPC
  • การแจ้งเตือน newHeads จะนับหนึ่งครั้งต่อแฮชบล็อกต่อการเชื่อมต่อ โดยไม่คำนึงว่าการเชื่อมต่อนั้นจะมีการติดตาม newHeads กี่รายการ
  • การแจ้งเตือน logs จะนับหนึ่งครั้งต่อการติดตามต่อแฮชบล็อกและเฟสที่มี log ที่ตรงกัน; บล็อกที่ไม่มีข้อมูลตรงกันจะไม่คิดค่าบริการ log ที่ตรงกันหลายรายการในบล็อกและเฟสเดียวกันจะไม่เพิ่มทวีคูณค่าบริการ การติดตามที่แยกจากกันจะนับแยกกัน แม้ว่าตัวกรองจะซ้อนทับกันก็ตาม log การ Reorganize (removed: true) จะถือเป็นหน่วยแยกต่างหาก; บล็อกที่เข้ามาแทนที่ ณ ความสูงเดียวกันจะมีแฮชที่ต่างกันและถือเป็นคนละหน่วย
  • การแจ้งเตือนจะคิดค่าบริการหลังจากถูก flush ไปยัง socket send buffer สำเร็จแล้วเท่านั้น; การแจ้งเตือนที่อยู่ในคิวหรือตกหล่นซึ่งไม่ได้ถูก flush จะไม่คิดค่าบริการ การแจ้งเตือนที่อยู่ในคิวก่อนการตอบกลับ eth_unsubscribe จะนับหากถูก flush ข้อความ WebSocket ไม่มีส่วนหัวการเรียกเก็บเงินของ HTTP; ตรวจสอบการใช้งานบัญชีสำหรับ CU ที่วัดปริมาณแล้ว

Subscription methods

API ใช้อินเทอร์เฟซ pub/sub มาตรฐานของ Ethereum: eth_subscribe และ eth_unsubscribe

newHeads

ส่งออบเจกต์ส่วนหัวบล็อกใหม่เมื่อใดก็ตามที่มีบล็อกใหม่ถูกเพิ่มต่อท้าย head ของเชน

  • Subscribe request:
    {"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["newHeads"]}
  • Subscribe response: ส่งกลับตัวระบุการติดตามเลขฐานสิบหกที่ไม่เปิดเผยโครงสร้างภายใน:
    {"jsonrpc":"2.0","id":1,"result":"0x1"}
  • Push notification frame:
    {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x1","result":{"number":"0x1b4","hash":"0x..."}}}

logs

ส่งเหตุการณ์ log ที่ตรงกับเกณฑ์ตัวกรองที่ระบุ

  • Filter requirement: ตัวกรองการติดตาม logs ทุกรายการต้องระบุ address (แอดเดรสของสัญญาหรืออาร์เรย์ของแอดเดรส) หรือ topic0 (ตำแหน่ง topic แรก ที่ไม่ใช่ null) ตัวกรองที่ไม่ระบุทั้งสองอย่าง (เช่น {} หรือ {"topics":[null,"0x..."]}) จะถูกปฏิเสธด้วยรหัสข้อผิดพลาด -32602 (logs_filter_required)

  • Filter limits: สูงสุด 100 แอดเดรส; สูงสุด 4 ตำแหน่ง topic โดยมีแฮชตัวเลือกได้สูงสุด 16 รายการต่อตำแหน่ง

  • Filter capacity: หากตัวกรอง log ที่ใช้งานอยู่เต็มความจุ การติดตามจะส่งกลับรหัสข้อผิดพลาด -32022 (ws_filter_capacity)

  • Chain reorganizations: หากบล็อกถูกลบออกเนื่องจาก reorg ของเชน การแจ้งเตือน log สำหรับ log ที่ถูกลบออกจะมี "removed": true

  • Subscribe request:

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

eth_unsubscribe

ยกเลิกการติดตามที่ใช้งานอยู่โดยใช้ตัวระบุการติดตาม

  • Unsubscribe request:
    {"jsonrpc":"2.0","id":3,"method":"eth_unsubscribe","params":["0x1"]}
  • Unsubscribe response:
    {"jsonrpc":"2.0","id":3,"result":true}

Runnable examples

เชื่อมต่อโดยใช้ viem v2 ผ่าน createPublicClient และ transport webSocket แทนที่ {chain} ด้วยตัวระบุเชนเป้าหมาย และแทนที่ {api_key} ด้วย API key ของคุณ:

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);
  },
});

Close codes and client actions

เมื่อเซิร์ฟเวอร์ยุติเซสชัน WebSocket จะส่งเฟรม Close พร้อมรหัสปิดเฉพาะและเหตุผลสั้นๆ ตารางด้านล่างแสดงรหัสปิดที่ส่งออกมาจากเซิร์ฟเวอร์และการดำเนินการที่แนะนำ:

Close codeReason stringDescriptionRetryableClient action
1001idleการเชื่อมต่อที่ไม่มีกิจกรรมโดยไม่มีการติดตามหรือข้อความเป็นเวลา 3600 วินาที (1 ชั่วโมง)Yesเชื่อมต่อใหม่ตามต้องการ
1003binary frames are not acceptedได้รับเฟรม WebSocket ไบนารี; รองรับเฉพาะเฟรมข้อความ UTF-8 เท่านั้นNoอย่าเชื่อมต่อใหม่อัตโนมัติ อัปเดตไคลเอนต์ให้ส่งเฟรมข้อความ
1009message too largeเพย์โหลดขาเข้าเกิน 1 MiBNoอย่าเชื่อมต่อใหม่อัตโนมัติ แบ่งคำขอขนาดใหญ่ออกหรือลดขนาดเพย์โหลด
1012service restartเซิร์ฟเวอร์กำลังรีสตาร์ต หรือเซสชันมีอายุการใช้งานถึงขีดจำกัดสูงสุด (24 ชั่วโมง)Yesเชื่อมต่อใหม่โดยใช้การหน่วงเวลาแบบสุ่ม สร้างการติดตามใหม่อีกครั้ง และดึงข้อมูลที่พลาดไปย้อนหลัง
1013chain unavailableเชนไม่พร้อมใช้งานYesเชื่อมต่อใหม่โดยใช้ full-jitter exponential backoff สร้างการติดตามใหม่อีกครั้ง และดึงข้อมูลที่พลาดไปย้อนหลัง
1013overloadedเซิร์ฟเวอร์โอเวอร์โหลดชั่วคราวYesเชื่อมต่อใหม่โดยใช้ full-jitter exponential backoff สร้างการติดตามใหม่อีกครั้ง และดึงข้อมูลที่พลาดไปย้อนหลัง
4402insufficient balanceยอดคงเหลือในบัญชีหมดNoอย่าเชื่อมต่อใหม่อัตโนมัติ เติมเงินในยอดคงเหลือของคุณ แล้วเชื่อมต่อใหม่
4404invalid api keyAPI key ไม่รู้จัก ปิดใช้งาน หรือถูกเพิกถอนNoอย่าเชื่อมต่อใหม่อัตโนมัติ ตรวจสอบหรือสลับ API key ในคอนโซลก่อนเชื่อมต่อใหม่
4408slow consumerเซิร์ฟเวอร์ปิดเซสชันที่คิวการ push เกิน 512 KiB และทิ้งการแจ้งเตือนที่รอดำเนินการ; ไคลเอนต์อาจไม่ได้รับ close frame (เบราว์เซอร์รายงาน 1006)Yesปฏิบัติต่อการหลุดการเชื่อมต่อที่ไม่คาดคิด (ไม่ได้รับ close frame เบราว์เซอร์รายงาน 1006) เช่นเดียวกับ 4408: เชื่อมต่อใหม่ด้วย backoff สร้างการติดตามใหม่อีกครั้ง และดึงข้อมูลที่ตกหล่นย้อนหลังด้วย eth_getLogs; สมัครรับข้อมูลน้อยลง หรืออ่านให้เร็วขึ้น
4429push rate exceededอัตราการแจ้งเตือนเกิน 1,000 push/วินาทีYesลดการติดตามหรือจำกัดตัวกรองให้แคบลง; เชื่อมต่อใหม่ด้วย backoff สมัครรับข้อมูลใหม่ และดึงข้อมูลย้อนหลัง
4503billing unavailableระบบการเรียกเก็บเงินไม่พร้อมใช้งานชั่วคราวYesสถานะชั่วคราว; เชื่อมต่อใหม่โดยใช้ full-jitter exponential backoff

Reconnection and exponential backoff

เพื่อป้องกันปัญหาพายุการเชื่อมต่อใหม่พร้อมกันเมื่อการเชื่อมต่อหลุด ไคลเอนต์ต้องนำ exponential backoff พร้อม full jitter ไปใช้งาน:

  • สูตร Backoff: ก่อนความพยายามในการเชื่อมต่อใหม่ครั้งที่ n (n = 0, 1, 2, ...), ให้รอเป็นระยะเวลาที่สุ่มเลือกแบบสม่ำเสมอ:
    delay = random(0, min(20s, 0.5s * 2^n))
  • รีเซ็ตตัวนับ: รีเซ็ตตัวนับการลองใหม่ n เป็น 0 หลังจากรักษาการเชื่อมต่อที่เสถียรและไม่หยุดชะงักได้อย่างน้อย 60 วินาที เท่านั้น
  • Close code 1012: หน่วงเวลาเริ่มต้นแบบสุ่มก่อนความพยายามเชื่อมต่อใหม่ครั้งแรกเพื่อหลีกเลี่ยงสไปก์การเชื่อมต่อใหม่พร้อมกัน
  • รหัสที่ไม่สามารถลองใหม่ได้: อย่าเชื่อมต่อใหม่อัตโนมัติสำหรับ 4402, 4404, 1003 หรือ 1009

Backfilling missed data after reconnection

การติดตามผ่าน WebSocket จะไม่คงอยู่ข้ามการเชื่อมต่อ; การแจ้งเตือนที่ส่งออกมาระหว่างที่หลุดการเชื่อมต่อจะไม่ถูกเก็บรักษาไว้บนเซิร์ฟเวอร์ หลังจากการเชื่อมต่อใหม่ ไคลเอนต์ควรดำเนินกลยุทธ์การไล่ตามข้อมูล:

  1. ดึงข้อมูล log ย้อนหลังด้วย eth_getLogs:
    • บันทึกหมายเลขบล็อกสูงสุดที่ประมวลผลสำเร็จไว้อย่างถาวร (last_processed_block)
    • เรียก eth_subscribe("logs", ...) ทันทีเมื่อเชื่อมต่อใหม่เพื่อจับเหตุการณ์สด
    • คิวรีบล็อกที่พลาดไปผ่าน eth_getLogs ด้วย fromBlock: last_processed_block + 1 และ toBlock: "latest" (หรือบล็อกแรกที่ได้รับจากสตรีมสด)
    • หากช่องว่างการหลุดการเชื่อมต่อเกิน max_logs_block_range ของเครือข่าย (จาก GET /v1/chains) ให้แบ่งการคิวรีออกเป็น chunk โดยไม่เกินขีดจำกัดนั้น
    • ขจัดข้อมูล log ที่ซ้ำกันข้ามขอบเขตการคิวรีโดยใช้ทูเพิลเฉพาะ (blockHash, transactionHash, logIndex)
  2. ดึงข้อมูลส่วนหัวบล็อกย้อนหลังด้วย eth_getBlockByNumber:
    • บันทึกหมายเลขบล็อกและแฮชล่าสุดที่ได้รับก่อนหลุดการเชื่อมต่อ
    • สมัครรับข้อมูล newHeads ใหม่อีกครั้ง
    • คิวรี eth_getBlockByNumber("latest", false) และดึงข้อมูลบล็อกระดับกลางที่ขาดหายไปตามลำดับ ตรวจสอบความต่อเนื่องของเชน parentHash เพื่อตรวจจับ reorg

Limits

LimitValueResult when exceeded
การติดตามต่อการเชื่อมต่อ WebSocket100-32022 subscription_limit
การติดตาม newHeads ต่อการเชื่อมต่อ WebSocket4-32022 subscription_limit
ข้อกำหนดตัวกรองการติดตาม logsต้องระบุ address หรือ topic0 (ตำแหน่งแรกใน topics)-32602 logs_filter_required

ขั้นตอนถัดไป

อัปเดตล่าสุด:

ในหน้านี้