開発者へ / JSON-RPC
サブスクリプション
四つのサブスクリプションの種類が、HTTP のリスナーではないサーバーの上にあります。ミニブロックのストリームが住んでいるのはここで、ほかのチェーンでは見つからない唯一の面がそれです。
別のサーバー
サブスクリプションは HTTP のポートには存在しません
HTTP のエンドポイントに対する eth_subscribe は -32601 を 返します。ノードは jsonrpsee のサブスクリプションをどこにも登録していません。ソケットは 自分のリスナーを持つ手書きの別サーバーであり、サブスクリプションが提供される唯一の場所です。
レプリカには WebSocket サーバーがまったくありません。リスナーはリーダーの経路でのみ 起動されます。サブスクリプションはリーダー専用の面です。
| エンドポイント | Value |
|---|---|
| エンドポイント | wss://rpc.picklechain.xyz/ws/公開テスト用ネットワーク。例ではこれを $WS_URL と書きます |
| 自分で動かすノード | ws://127.0.0.1:8546自分のマシンで起動したノードの既定の WebSocket ポート |
On a deployment behind a reverse proxy, both /ws and /ws/ are served as two separate locations with no redirect between them: a WebSocket client mostly does not follow a 301 on its handshake, so whichever spelling was redirected would simply fail to connect.
ハンドシェイク
eth_subscribe と pickle_subscribe はどちらも同じように 受け付けられ、同じようにふるまいます。
// ->
{"jsonrpc":"2.0","id":1,"method":"pickle_subscribe","params":["miniBlocks"]}
// <-
{"jsonrpc":"2.0","id":1,"result":"0x1"}
// <- then, per event
{"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x1","result":{…}}}- Subscription ids come from a per-connection counter starting at 1, so two connections both see 0x1. Do not treat an id as globally unique.
- Notifications always arrive under the method name eth_subscription, even for a subscription opened as pickle_subscribe. Unwrap the payload at params.result.
- eth_unsubscribe and pickle_unsubscribe both return a boolean: true if the id was found on this connection, false otherwise.
四つの種類
One notification per sealed EVM block.
知っておくとよいこと。 The payload is a nine-field summary - number, hash, parentHash, timestamp, mixHash, baseFeePerGas, transactionCount, miniBlockFrom, miniBlockTo - and not the full header that eth_getBlockByNumber returns. transactionCount is a decimal number. A client that needs gasLimit, gasUsed or logsBloom must re-fetch the block.
miniBlocks
alias: newMiniBlocksThe preconfirmation stream: one notification per sealed mini-block, at the mini-block scheduling target. Both spellings are the same stream.
知っておくとよいこと。 Mini-block fields break the eth_* hex convention on purpose: number, evmBlockNumber, timestampUs and each receipt's gasUsed are decimal JSON numbers, and the timestamp is in microseconds.
Logs as they are indexed, with the standard address and topics filtering. An absent or empty filter means every log.
知っておくとよいこと。 A malformed topics filter answers -32602 before an id is allocated, so a failed subscribe leaves you with no subscription rather than a silent one.
Transaction hashes, as a bare string payload.
知っておくとよいこと。 "Pending" does not mean what it means elsewhere. There is no public mempool; a hash is published only AFTER the transaction has executed and been indexed. Treat this as an executed-transaction feed, not a mempool feed.
通しの例
ミニブロックのストリームと、ファーストパーティのフィードが使っている代替経路です。この 代替経路が効きます。ソケットが切れるのは普通のことで、取りこぼしなく追いつく方法が ポーリングの経路です。
// WS_URL: wss://rpc.picklechain.xyz/ws/ on the public testnet, or a node of your own.
// The /ws path is required - an upgrade at the bare origin answers 405.
const socket = new WebSocket(WS_URL);
socket.addEventListener("open", () => {
socket.send(JSON.stringify({
jsonrpc: "2.0", id: 1, method: "pickle_subscribe", params: ["miniBlocks"],
}));
});
socket.addEventListener("message", (event) => {
const message = JSON.parse(event.data);
// The subscribe reply carries an id; notifications carry params.result.
if (!message.params) return;
const mini = message.params.result;
// Decimal numbers, not hex quantities - and microseconds, not seconds.
console.log(mini.number, mini.transactions.length, mini.timestampUs);
});
// A slow handler is DROPPED from the stream rather than buffered, so do the
// work elsewhere and keep this callback cheap.ソケットが閉じたら、pickle_miniBlockNumber を問い合わせ、最後に見た高さから pickle_getMiniBlockByNumber を取ってください。追いつきには上限を設けること。 参照クライアントは 1 回のパスにつき最大 100 件を取得します。さもないと長い切断が、共有の 重い読み取り予算に対する大量のリクエストに変わります。
制限と切り離しの方針
| 制限 | Value |
|---|---|
| Message size | 256 KiBframe and message both; oversized answers -32005 "message too large" |
| Connections | 256excess connections are dropped at accept, with no error frame - your client sees a closed socket, not a rejection |
| Subscriptions per connection | 32-32005 "subscription limit reached" |
| Requests per second | 100 per connection-32005 "request rate limit exceeded" |
| Stream depth | 1024 per streama subscriber that falls behind is DROPPED from the stream rather than buffered, so a slow handler loses notifications silently. Do the work off the socket |
遅い購読者は静かにデータを失います
各ストリームは深さ 1024 のブロードキャストチャネルです。遅れた購読者は、ノードの メモリを膨らませるのではなくストリームから切り離されます。エラーのフレームは届かず、 届くのは欠落です。ミニブロックのスケジューリング目標において、このバッファは数秒ぶんの 余裕にあたるので、イベントごとの処理がキューへ積む以上に重いなら、それはソケットの外に 置くべきです。
これらの制限はどれも環境変数で調整できず、接続数の上限は accept の時点で適用されます。 257 番目の接続はエラーのフレームなしに閉じられるので、拒否ではなくネットワーク障害のように 見えます。
ソケット上の通常の呼び出し
Any frame that is not a subscribe or unsubscribe is forwarded to the same handler the HTTP port uses, so every method in the reference is callable over the socket.
エラーコードはトランスポートによって異なります
Error codes are re-wrapped on the way out. Every non-send failure comes back as -32603 regardless of its original code, so an eth_call revert is -32000 over HTTP and -32603 over the socket. A client that branches on the code needs to know which transport it is on.