Für Entwickler / JSON-RPC
Abonnements
Vier Abonnementarten, auf einem Server, der nicht der HTTP-Listener ist. Hier lebt der Mini-Block-Strom, die eine Oberfläche, die Sie auf keiner anderen Chain finden.
Ein eigener Server
Abonnements gibt es auf dem HTTP-Port nicht
eth_subscribe gegen den HTTP-Endpunkt antwortet -32601. Der Node registriert nirgends ein jsonrpsee-Abonnement; der Socket ist ein eigener, handgeschriebener Server auf einem eigenen Listener, und er ist der einzige Ort, an dem Abonnements bedient werden.
Eine Replika hat überhaupt keinen WebSocket-Server - der Listener wird nur auf dem Leader-Pfad gestartet. Abonnements sind eine Oberfläche, die es nur beim Leader gibt.
| Endpunkt | Value |
|---|---|
| Endpunkt | wss://rpc.picklechain.xyz/ws/das öffentliche Testnetz; die Beispiele schreiben es als $WS_URL |
| Ein Node, den Sie selbst betreiben | ws://127.0.0.1:8546der voreingestellte WebSocket-Port eines auf Ihrem eigenen Rechner gestarteten Node |
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.
Der Handshake
eth_subscribe und pickle_subscribe werden austauschbar angenommen und verhalten sich identisch:
// ->
{"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.
Die vier Arten
One notification per sealed EVM block.
Gut zu wissen. 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.
Gut zu wissen. 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.
Gut zu wissen. 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.
Gut zu wissen. "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.
Ein durchgerechnetes Beispiel
Der Mini-Block-Strom, mit der Rückfallebene, die der hauseigene Feed verwendet. Die Rückfallebene zählt: Ein abgerissener Socket ist normal, und der Abfragepfad ist der Weg, ohne Lücken aufzuholen.
// 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.Wenn der Socket schließt, fragen Sie pickle_miniBlockNumber und dann pickle_getMiniBlockByNumber ab Ihrer zuletzt gesehenen Höhe ab. Begrenzen Sie das Aufholen - der Referenz-Client holt höchstens 100 pro Durchgang -, sonst wird aus einer langen Trennung ein Schwall von Anfragen gegen das geteilte Budget für schwere Lesezugriffe.
Grenzen und die Abwurfregel
| Grenze | 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 |
Langsame Abonnenten verlieren Daten still
Jeder Strom ist ein Broadcast-Kanal mit einer Tiefe von 1024. Ein Abonnent, der zurückfällt, wird vom Strom abgeworfen, statt den Speicher des Node wachsen zu lassen - Sie bekommen keinen Fehlerrahmen, Sie bekommen eine Lücke. Beim Planungsziel des Mini-Blocks sind das ein paar Sekunden Luft, jede Arbeit pro Ereignis, die schwerer wiegt als ein Schub in eine Queue, gehört also vom Socket weg.
Keine dieser Grenzen ist über die Umgebung einstellbar, und die Verbindungsobergrenze wird beim Annehmen durchgesetzt: Die 257. Verbindung wird ohne Fehlerrahmen geschlossen, was nach einem Netzwerkausfall aussieht statt nach einer Ablehnung.
Gewöhnliche Aufrufe über den Socket
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.
Fehlercodes unterscheiden sich je nach Transport
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.