Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rpc/ws/blockSubscribe.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func (cl *Client) BlockSubscribe(
obj["transactionDetails"] = opts.TransactionDetails
}
if opts.Rewards != nil {
obj["rewards"] = opts.Rewards
obj["showRewards"] = opts.Rewards
}
if opts.MaxSupportedTransactionVersion != nil {
obj["maxSupportedTransactionVersion"] = *opts.MaxSupportedTransactionVersion
Expand Down
107 changes: 107 additions & 0 deletions rpc/ws/blockSubscribe_rewards_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package ws

import (
"strconv"
"testing"
"time"

"github.com/gagliardetto/solana-go/rpc"
"github.com/stretchr/testify/require"
)

// readSubscribeParams reads one subscribe request from the mock server and
// returns the params map of the second element (the options object), responding
// to the client so the subscribe call can return.
func readSubscribeParams(t *testing.T, m *mockWSServer, wsSubID uint64) map[string]any {
t.Helper()
select {
case msg := <-m.incoming:
var req struct {
ID uint64 `json:"id"`
Method string `json:"method"`
Params []any `json:"params"`
}
require.NoError(t, json.Unmarshal(msg, &req))
resp := `{"jsonrpc":"2.0","result":` + strconv.FormatUint(wsSubID, 10) + `,"id":` + strconv.FormatUint(req.ID, 10) + `}`
m.send(t, resp)
// params[0] is the filter ("all"), params[1] is the opts object
require.GreaterOrEqual(t, len(req.Params), 2, "expected opts object in params[1]: %s", string(msg))
opts, ok := req.Params[1].(map[string]any)
require.True(t, ok, "expected map opts in params[1], got %T", req.Params[1])
return opts
case <-time.After(2 * time.Second):
t.Fatal("timed out waiting for subscribe request")
return nil
}
}

// TestBlockSubscribeUsesShowRewardsField pins that BlockSubscribe sends the
// Solana-spec field "showRewards" (not "rewards") in its params object.
//
// See https://solana.com/docs/rpc/websocket/blocksubscribe for the spec, and
// issue #208 for the bug report.
func TestBlockSubscribeUsesShowRewardsField(t *testing.T) {
m := newMockWSServer(t)
defer m.stop()
c := connectClient(t, m)
defer c.Close()

rewards := false
opts := &BlockSubscribeOpts{
Commitment: rpc.CommitmentConfirmed,
Rewards: &rewards,
}

type subResult struct {
err error
}
ch := make(chan subResult, 1)
go func() {
_, err := c.BlockSubscribe(NewBlockSubscribeFilterAll(), opts)
ch <- subResult{err}
}()

params := readSubscribeParams(t, m, 1)
require.NoError(t, (<-ch).err)

_, hasOldKey := params["rewards"]
require.False(t, hasOldKey, "params must not include legacy 'rewards' key: %v", params)

v, ok := params["showRewards"]
require.True(t, ok, "params must include 'showRewards' key: %v", params)
require.Equal(t, false, v)
}

// TestParsedBlockSubscribeUsesShowRewardsField pins the same fix for the
// parsed-block subscription path.
func TestParsedBlockSubscribeUsesShowRewardsField(t *testing.T) {
m := newMockWSServer(t)
defer m.stop()
c := connectClient(t, m)
defer c.Close()

rewards := true
opts := &BlockSubscribeOpts{
Commitment: rpc.CommitmentConfirmed,
Rewards: &rewards,
}

type subResult struct {
err error
}
ch := make(chan subResult, 1)
go func() {
_, err := c.ParsedBlockSubscribe(NewBlockSubscribeFilterAll(), opts)
ch <- subResult{err}
}()

params := readSubscribeParams(t, m, 2)
require.NoError(t, (<-ch).err)

_, hasOldKey := params["rewards"]
require.False(t, hasOldKey, "params must not include legacy 'rewards' key: %v", params)

v, ok := params["showRewards"]
require.True(t, ok, "params must include 'showRewards' key: %v", params)
require.Equal(t, true, v)
}
2 changes: 1 addition & 1 deletion rpc/ws/parsedBlockSubscribe.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (cl *Client) ParsedBlockSubscribe(
obj["transactionDetails"] = opts.TransactionDetails
}
if opts.Rewards != nil {
obj["rewards"] = opts.Rewards
obj["showRewards"] = opts.Rewards
}
if opts.MaxSupportedTransactionVersion != nil {
obj["maxSupportedTransactionVersion"] = *opts.MaxSupportedTransactionVersion
Expand Down