Pour les développeurs / JSON-RPC
Abonnements
Quatre types d'abonnement, sur un serveur qui n'est pas l'écouteur HTTP. C'est là que vit le flux de mini-blocs, la seule surface ici que vous ne trouverez pas sur une autre chaîne.
Un serveur séparé
Les abonnements n'existent pas sur le port HTTP
eth_subscribe contre le point d'accès HTTP répond -32601. Le nœud n'enregistre aucune souscription jsonrpsee nulle part ; le socket est un serveur écrit à la main, sur son propre écouteur, et c'est le seul endroit où les abonnements sont servis.
Une réplique n'a aucun serveur WebSocket - l'écouteur n'est lancé que sur le chemin du leader. Les abonnements sont une surface réservée au leader.
| Point d'accès | Value |
|---|---|
| Point d'accès | wss://rpc.picklechain.xyz/ws/le réseau de test public ; les exemples l'écrivent $WS_URL |
| Un nœud que vous faites tourner | ws://127.0.0.1:8546le port WebSocket par défaut d'un nœud démarré sur votre machine |
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.
La poignée de main
eth_subscribe et pickle_subscribe sont acceptées indifféremment et se comportent à l'identique :
// ->
{"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.
Les quatre types
One notification per sealed EVM block.
Bon à savoir. 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.
Bon à savoir. 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.
Bon à savoir. 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.
Bon à savoir. "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.
Un exemple complet
Le flux de mini-blocs, avec le repli qu'utilise le flux de première partie. Le repli compte : un socket coupé est normal, et la voie du sondage est la façon de rattraper sans trous.
// WS_URL : wss://rpc.picklechain.xyz/ws/ sur le réseau de test public, ou un nœud à vous.
// Le chemin /ws est obligatoire - une montée en WebSocket sur l'origine nue répond 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.Si le socket se ferme, sondez pickle_miniBlockNumber puis pickle_getMiniBlockByNumber depuis la dernière hauteur vue. Bornez le rattrapage - le client de référence en récupère au plus 100 par passe - ou une longue déconnexion se transforme en rafale de requêtes contre le budget de lectures lourdes partagé.
Limites et politique d'éjection
| Limite | 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 |
Les abonnés lents perdent des données en silence
Chaque flux est un canal de diffusion de 1024 de profondeur. Un abonné qui prend du retard est éjecté du flux plutôt que laissé faire grossir la mémoire du nœud - vous ne recevez pas de trame d'erreur, vous recevez un trou. À la cible d'ordonnancement du mini-bloc, ce tampon représente quelques secondes de marge, donc tout travail par événement plus lourd qu'un empilement dans une file n'a pas sa place sur le socket.
Aucune de ces limites n'est réglable par l'environnement, et le plafond de connexions est appliqué à l'acceptation : la 257e connexion est fermée sans trame d'erreur, ce qui ressemble à une panne réseau plutôt qu'à un refus.
Les appels ordinaires sur le 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.
Les codes d'erreur diffèrent selon le 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.