From fb242e7d8201f790ecb8df45ed3c1851887d0605 Mon Sep 17 00:00:00 2001 From: Linus Kendall <5172293+linuskendall@users.noreply.github.com> Date: Mon, 14 Sep 2026 06:20:44 +0000 Subject: [PATCH 1/2] feat(websocket): add voteUnsubscribe specification --- methods/websocket/voteUnsubscribe.md | 7 +++++ methods/websocket/voteUnsubscribe.yaml | 27 ++++++++++++++++++ proposals/0060-vote-unsubscribe.md | 38 ++++++++++++++++++++++++++ spec-info.yaml | 2 +- 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 methods/websocket/voteUnsubscribe.md create mode 100644 methods/websocket/voteUnsubscribe.yaml create mode 100644 proposals/0060-vote-unsubscribe.md diff --git a/methods/websocket/voteUnsubscribe.md b/methods/websocket/voteUnsubscribe.md new file mode 100644 index 0000000..b80c47b --- /dev/null +++ b/methods/websocket/voteUnsubscribe.md @@ -0,0 +1,7 @@ +# voteUnsubscribe + +Cancels a subscription created by `voteSubscribe` on the same WebSocket connection and returns `true`. An id that this connection does not hold returns `InvalidParams` (-32602) with the message `Invalid subscription id.` + +## Implementation notes + +[**Agave**](../../implementations/agave.md) implements this method in the [pinned PubSub trait](https://github.com/anza-xyz/agave/blob/6dd9d38771e46103b9680357a855804165612602/rpc/src/rpc_pubsub.rs#L227). Cloudbreak and Superbank do not serve WebSocket subscriptions. diff --git a/methods/websocket/voteUnsubscribe.yaml b/methods/websocket/voteUnsubscribe.yaml new file mode 100644 index 0000000..40be4a5 --- /dev/null +++ b/methods/websocket/voteUnsubscribe.yaml @@ -0,0 +1,27 @@ +name: voteUnsubscribe +status: standard +summary: Cancel a voteSubscribe subscription. +params: + - name: subscriptionId + required: true + summary: Identifier returned by voteSubscribe on this connection. + schema: { $ref: '#/components/schemas/U64' } +result: + name: success + summary: True when the subscription is cancelled. + schema: { type: boolean } +errors: + - $ref: '#/components/errors/InvalidParams' +examples: + - name: basic + summary: Cancel a subscription. + params: + - name: subscriptionId + value: 1 + result: + name: success + value: true +implementations: + agave: { status: full } + cloudbreak: { status: none } + superbank: { status: none } diff --git a/proposals/0060-vote-unsubscribe.md b/proposals/0060-vote-unsubscribe.md new file mode 100644 index 0000000..a55b3fd --- /dev/null +++ b/proposals/0060-vote-unsubscribe.md @@ -0,0 +1,38 @@ +--- +number: 0060 +title: Add voteUnsubscribe +authors: [rpcpool] +status: draft +created: 2026-09-14 +reference-implementations: [https://github.com/anza-xyz/agave/blob/6dd9d38771e46103b9680357a855804165612602/rpc/src/rpc_pubsub.rs#L227] +--- + +# Add voteUnsubscribe + +## Summary + +Add the voteUnsubscribe WebSocket RPC method. + +## Motivation + +Agave exposes this public PubSub lifecycle method. + +## Specification + +Add the paired WebSocket method page. It defines the connection-scoped cancellation request, true result, and invalid-subscription error. + +## Return-type impact + +The method returns true after cancellation. + +## Compatibility + +This is additive. Agave implements it. Cloudbreak and Superbank do not currently implement WebSocket PubSub. + +## Reference implementation + +[Agave pinned handler](https://github.com/anza-xyz/agave/blob/6dd9d38771e46103b9680357a855804165612602/rpc/src/rpc_pubsub.rs#L227) + +## Security considerations + +Servers release the subscription resources when this call succeeds. diff --git a/spec-info.yaml b/spec-info.yaml index 892ea85..bca4391 100644 --- a/spec-info.yaml +++ b/spec-info.yaml @@ -1,5 +1,5 @@ title: Solana JSON-RPC API -version: 0.1.0 +version: 0.2.0 license: name: MIT url: https://opensource.org/license/mit/ From 055a48a6301ca2289b2d58a9b282f170984f4334 Mon Sep 17 00:00:00 2001 From: Linus Kendall <5172293+linuskendall@users.noreply.github.com> Date: Mon, 14 Sep 2026 06:42:16 +0000 Subject: [PATCH 2/2] fix(websocket): document disabled subscription error --- methods/websocket/voteUnsubscribe.md | 4 ++-- methods/websocket/voteUnsubscribe.yaml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/methods/websocket/voteUnsubscribe.md b/methods/websocket/voteUnsubscribe.md index b80c47b..59b705e 100644 --- a/methods/websocket/voteUnsubscribe.md +++ b/methods/websocket/voteUnsubscribe.md @@ -1,7 +1,7 @@ # voteUnsubscribe -Cancels a subscription created by `voteSubscribe` on the same WebSocket connection and returns `true`. An id that this connection does not hold returns `InvalidParams` (-32602) with the message `Invalid subscription id.` +Cancels a subscription created by `voteSubscribe` on the same WebSocket connection and returns `true`. An id that this connection does not hold returns `InvalidParams` (-32602) with the message `Invalid subscription id.` Agave returns `MethodNotFound` unless the validator enables `--rpc-pubsub-enable-vote-subscription`. ## Implementation notes -[**Agave**](../../implementations/agave.md) implements this method in the [pinned PubSub trait](https://github.com/anza-xyz/agave/blob/6dd9d38771e46103b9680357a855804165612602/rpc/src/rpc_pubsub.rs#L227). Cloudbreak and Superbank do not serve WebSocket subscriptions. +[**Agave**](../../implementations/agave.md) implements this method in the [pinned PubSub trait](https://github.com/anza-xyz/agave/blob/6dd9d38771e46103b9680357a855804165612602/rpc/src/rpc_pubsub.rs#L227). diff --git a/methods/websocket/voteUnsubscribe.yaml b/methods/websocket/voteUnsubscribe.yaml index 40be4a5..dd46646 100644 --- a/methods/websocket/voteUnsubscribe.yaml +++ b/methods/websocket/voteUnsubscribe.yaml @@ -11,6 +11,7 @@ result: summary: True when the subscription is cancelled. schema: { type: boolean } errors: + - $ref: '#/components/errors/MethodNotFound' - $ref: '#/components/errors/InvalidParams' examples: - name: basic