fix(ws): pubsub parity#407
Merged
HealthyBuilder merged 3 commits intoMay 8, 2026
Merged
Conversation
Cross-checked every response and request shape in rpc/ws against agave/pubsub-client (anza-xyz/agave) and filled the gaps. Method-level parity was already complete, but option sets, response fields, and the BlockSubscribe/ParsedBlockSubscribe split had drifted in ways that produced the "unable to decode client response" error on jsonParsed block notifications (issue solana-foundation#291) and left several subscriptions without the options Agave exposes. BlockSubscribe unification (closes solana-foundation#291) ---------------------------------------- BlockSubscribe now accepts every UiTransactionEncoding the RPC supports — base58, base64, base64+zstd, jsonParsed — through a single method, matching Agave's shape. Go can't express BlockResult.Value is a Go-style union: BlockResultValue carries both Block (*rpc.GetBlockResult) and ParsedBlock (*rpc.GetParsedBlockResult). Exactly one is populated per frame, chosen by the Encoding captured at subscribe time and routed inside decodeBlockNotification(isParsed). base58 / base64 / base64+zstd -> Block jsonParsed -> ParsedBlock ParsedBlockSubscribe is marked Deprecated but continues to return *ParsedBlockResult so nothing breaks for existing callers. Request / config parity ----------------------- - AccountSubscribeConfig: new struct mirroring RpcAccountInfoConfig (commitment, encoding, dataSlice, minContextSlot). The existing AccountSubscribe / AccountSubscribeWithOpts are preserved as thin wrappers; AccountSubscribeWithConfig exposes the full surface. - ProgramSubscribeConfig: new struct mirroring RpcProgramAccountsConfig (commitment, encoding, dataSlice, filters, minContextSlot, withContext, sortResults). - SignatureSubscribeConfig: new struct mirroring RpcSignatureSubscribeConfig, adds enableReceivedNotification. - Each Config has an unexported (c *Config).params() helper that matches Agave's serde(skip_serializing_if="Option::is_none") behavior. Response parity --------------- - SignatureResult.Value now models the untagged ProcessedSignature | ReceivedSignature union via SignatureResultValue{IsReceived, Processed}. Custom UnmarshalJSON handles the object form ({"err":...}), the string form "receivedSignature", and null. The old Value.Err path is replaced by Value.Processed.Err. - VoteResult gains VotePubkey and Signature to match RpcVote. - SlotsUpdatesResult adds Err (Dead variant), documents which fields are populated per discriminator. - All Context fields across the subscription result types moved from anonymous struct{Slot uint64} to a shared RPCResponseContext (slot + apiVersion), matching RpcResponseContext. Consumer adaptation ------------------- sendAndConfirmTransaction.WaitForConfirmation adapted to the new SignatureResult shape and loops on IsReceived until a processed notification arrives — previously retried only once, so a second consecutive received-only frame would have passed a nil Processed through and wrongly reported (confirmed=true, err=nil). Examples -------- - rpc/ws/examples/blockSubscribe: demonstrates the Block/ParsedBlock union via a switch on which field is populated. - rpc/ws/examples/parsedBlockSubscribe: removed (redundant now). Tests (new subscriptions_test.go + parsedBlockSubscribe_test.go) ---------------------------------------------------------------- Fixture JSON mirrors the wire format produced by Agave's rpc_subscriptions.rs integration tests: - accountNotification: base64 and jsonParsed payloads - programNotification, logsNotification, voteNotification, slotNotification, rootNotification - signatureNotification: processed (null err), processed (with err), and the "receivedSignature" string variant - slotsUpdatesNotification: all seven SlotUpdate variants - blockNotification: separate ParsedRoute / BinaryRoute tests that exercise decodeBlockNotification for both branches; the binary fixture includes a real [blob, "base64"] 2-array transaction + meta so drift between the two shapes would fail the test - TestConfigParams_Wire verifies per-field emission and omit behavior on every *SubscribeConfig.
ee36f0c to
0859a53
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Warning
Breaking Change SHould be merged into 2.0 branch
Problem
Agave's
pubsub-clienthas evolved since this repo's ws package was first written, and the two drifted across several dimensions that made our client either silently wrong or missing features users expectSummary of Changes
closes #291
closes #286
closes #208
closes #196