Para desarrolladores / JSON-RPC

Suscripciones

Cuatro tipos de suscripción, en un servidor que no es el que escucha en HTTP. Aquí vive el flujo de minibloques, la única superficie de esta cadena que no encontrará en otra.

Un servidor aparte

Las suscripciones no existen en el puerto HTTP

eth_subscribe contra el punto de acceso HTTP responde -32601. El nodo no registra ninguna suscripción jsonrpsee en ninguna parte; el socket es un servidor escrito a mano, en su propio puerto de escucha, y es el único sitio donde se sirven las suscripciones.

Una réplica no tiene ningún servidor WebSocket - el puerto de escucha solo se lanza en la ruta del líder. Las suscripciones son una superficie reservada al líder.

Punto de accesoValue
Punto de accesowss://rpc.picklechain.xyz/ws/la red de pruebas pública; los ejemplos lo escriben como $WS_URL
Un nodo que usted mismo ejecutaws://127.0.0.1:8546el puerto WebSocket por defecto de un nodo arrancado en su propia máquina

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.

El handshake

eth_subscribe y pickle_subscribe se aceptan indistintamente y se comportan igual:

json
// ->
{"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.

Los cuatro tipos

One notification per sealed EVM block.

Conviene saberlo. 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: newMiniBlocks

The preconfirmation stream: one notification per sealed mini-block, at the mini-block scheduling target. Both spellings are the same stream.

Conviene saberlo. 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.

Conviene saberlo. 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.

Conviene saberlo. "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 ejemplo completo

El flujo de minibloques, con la vía de reserva que usa el feed de primera parte. La vía de reserva importa: un socket caído es normal, y el sondeo es la forma de recuperar el retraso sin huecos.

javascript
// 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.

Si el socket se cierra, sondee pickle_miniBlockNumber y luego pickle_getMiniBlockByNumber desde la última altura vista. Acote la recuperación - el cliente de referencia recupera como máximo 100 por pasada - o una desconexión larga se convierte en una ráfaga de peticiones contra el presupuesto compartido de lecturas pesadas.

Límites y política de expulsión

LímiteValue
Message size256 KiBframe and message both; oversized answers -32005 "message too large"
Connections256excess connections are dropped at accept, with no error frame - your client sees a closed socket, not a rejection
Subscriptions per connection32-32005 "subscription limit reached"
Requests per second100 per connection-32005 "request rate limit exceeded"
Stream depth1024 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

Los suscriptores lentos pierden datos en silencio

Cada flujo es un canal de difusión de 1024 de profundidad. Un suscriptor que se queda atrás es expulsado del flujo en lugar de dejarle hacer crecer la memoria del nodo - no recibe una trama de error, recibe un hueco. Con el objetivo de programación del minibloque, ese búfer representa unos segundos de margen, así que cualquier trabajo por evento más pesado que apilar en una cola no tiene sitio en el socket.

Ninguno de estos límites es ajustable por entorno, y el tope de conexiones se aplica en la aceptación: la conexión número 257 se cierra sin trama de error, lo que parece un fallo de red en lugar de un rechazo.

Las llamadas ordinarias por el 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.

Los códigos de error difieren según el transporte

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.