Skip to content

Commit 427de1a

Browse files
authored
fix(ws): use uint64 for params.Subscription in incoming notifications (#427)
Solana validators emit subscription IDs as JSON unsigned 64-bit integers; typing the decode target as `int` made decodeResponseFromMessage fail for IDs above MaxInt32 (on 32-bit) or MaxInt64 (on 64-bit). Switch to uint64 to match the wire format. Closes #286.
1 parent bf130a2 commit 427de1a

2 files changed

Lines changed: 31 additions & 2 deletions

File tree

rpc/ws/types.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,15 @@ type response struct {
6868
}
6969

7070
type params struct {
71-
Result *stdjson.RawMessage `json:"result"`
72-
Subscription int `json:"subscription"`
71+
Result *stdjson.RawMessage `json:"result"`
72+
// Subscription is the validator-assigned subscription id. The validator
73+
// emits these as JSON unsigned 64-bit integers, so the field must use
74+
// uint64 to round-trip safely. Using int here failed JSON decoding on
75+
// 32-bit builds and on any value above math.MaxInt64 (issue #286). The
76+
// value is not consumed downstream — the routing key is parsed
77+
// separately via getUint64WithOk in handleMessage — but the field is
78+
// kept so encoding/json does not error on the incoming notification.
79+
Subscription uint64 `json:"subscription"`
7380
}
7481

7582
type Options struct {

rpc/ws/types_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package ws
22

33
import (
4+
stdjson "encoding/json"
45
"math"
56
"testing"
67

@@ -32,3 +33,24 @@ func TestGetUint64_AcceptsNumberAndString(t *testing.T) {
3233
require.NoError(t, err)
3334
require.Equal(t, uint64(3338220398172203928), id)
3435
}
36+
37+
// TestResponseDecodesLargeSubscriptionID covers issue #286: validator
38+
// notifications carry the subscription id as a JSON uint64. Before the fix
39+
// params.Subscription was typed `int`, which fails encoding/json decode on
40+
// 32-bit builds and on any value above math.MaxInt64. The field must use
41+
// uint64 to round-trip safely.
42+
func TestResponseDecodesLargeSubscriptionID(t *testing.T) {
43+
// Use the largest JSON-safe-but-still-uint64 value the server might emit.
44+
// math.MaxUint64 itself stresses the regression most directly.
45+
payload := []byte(`{
46+
"jsonrpc": "2.0",
47+
"params": {
48+
"result": null,
49+
"subscription": 18446744073709551615
50+
}
51+
}`)
52+
var r response
53+
require.NoError(t, stdjson.Unmarshal(payload, &r))
54+
require.NotNil(t, r.Params)
55+
require.Equal(t, uint64(math.MaxUint64), r.Params.Subscription)
56+
}

0 commit comments

Comments
 (0)