Skip to content

Commit f2b3165

Browse files
docs(examples): un-stale read-path RPC examples
Several examples hardcoded signatures, blockhashes, or base64 blobs that rotted the moment they were merged — or queried testnet where the needed data is sparse. Reshape them to fetch fresh input on mainnet-beta so they keep working as the cluster advances: - getTransaction, getSignatureStatuses: pull a recent signature via GetSignaturesForAddressWithOpts on the SPL Token program, then operate on it. - getFeeForMessage: build a real Transfer message in-code and base64 it via tx.Message.ToBase64(), instead of a dummy string. - isBlockhashValid: fetch a live blockhash via GetLatestBlockhash. - getBlock: switch to mainnet-beta and pass MaxSupportedTransactionVersion, which is required now that v0 transactions exist in blocks. - getProgramAccounts: swap the unbounded Metaplex query for a Token-2022 mint query with dataSize filter + DataSlice so the response stays small enough for public RPCs. - getLeaderSchedule: switch to mainnet-beta and print a summary instead of spew-dumping every validator in the epoch.
1 parent 0c4e706 commit f2b3165

7 files changed

Lines changed: 167 additions & 71 deletions

File tree

rpc/examples/getBlock/getBlock.go

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,43 +16,48 @@ package main
1616

1717
import (
1818
"context"
19+
"fmt"
1920

2021
"github.com/davecgh/go-spew/spew"
2122
"github.com/gagliardetto/solana-go"
2223
"github.com/gagliardetto/solana-go/rpc"
2324
)
2425

2526
func main() {
26-
endpoint := rpc.TestNet_RPC
27-
client := rpc.New(endpoint)
27+
ctx := context.Background()
28+
client := rpc.New(rpc.MainNetBeta_RPC)
2829

29-
slot, err := client.GetSlot(context.TODO(), rpc.CommitmentFinalized)
30+
slot, err := client.GetSlot(ctx, rpc.CommitmentFinalized)
3031
if err != nil {
3132
panic(err)
3233
}
3334

35+
// Mainnet blocks contain v0 (versioned) transactions; GetBlock
36+
// requires MaxSupportedTransactionVersion or it errors out.
37+
maxVersion := uint64(0)
38+
3439
{
35-
out, err := client.GetBlock(context.TODO(), slot)
40+
out, err := client.GetBlockWithOpts(ctx, slot, &rpc.GetBlockOpts{
41+
MaxSupportedTransactionVersion: &maxVersion,
42+
})
3643
if err != nil {
3744
panic(err)
3845
}
39-
// spew.Dump(out) // NOTE: This generates a lot of output.
40-
spew.Dump(len(out.Transactions))
46+
// Full block is large; just show the tx count.
47+
fmt.Println("transactions in block:", len(out.Transactions))
4148
}
4249

4350
{
4451
includeRewards := false
4552
out, err := client.GetBlockWithOpts(
46-
context.TODO(),
53+
ctx,
4754
slot,
48-
// You can specify more options here:
4955
&rpc.GetBlockOpts{
50-
Encoding: solana.EncodingBase64,
51-
Commitment: rpc.CommitmentFinalized,
52-
// Get only signatures:
53-
TransactionDetails: rpc.TransactionDetailsSignatures,
54-
// Exclude rewards:
55-
Rewards: &includeRewards,
56+
Encoding: solana.EncodingBase64,
57+
Commitment: rpc.CommitmentFinalized,
58+
TransactionDetails: rpc.TransactionDetailsSignatures,
59+
Rewards: &includeRewards,
60+
MaxSupportedTransactionVersion: &maxVersion,
5661
},
5762
)
5863
if err != nil {

rpc/examples/getFeeForMessage/getFeeForMessage.go

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,51 @@ package main
1616

1717
import (
1818
"context"
19+
"fmt"
1920

2021
"github.com/davecgh/go-spew/spew"
22+
"github.com/gagliardetto/solana-go"
23+
"github.com/gagliardetto/solana-go/programs/system"
2124
"github.com/gagliardetto/solana-go/rpc"
2225
)
2326

27+
// GetFeeForMessage returns the fee for a base64-encoded Solana Message
28+
// (not a full Transaction). Here we construct a realistic Transfer
29+
// message to show how the base64 argument is produced.
2430
func main() {
25-
endpoint := rpc.TestNet_RPC
26-
client := rpc.New(endpoint)
31+
ctx := context.Background()
32+
client := rpc.New(rpc.MainNetBeta_RPC)
2733

28-
example, err := client.GetFeeForMessage(
29-
context.Background(),
30-
"AQABAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAA",
34+
from := solana.NewWallet().PublicKey()
35+
to := solana.NewWallet().PublicKey()
36+
37+
recent, err := client.GetLatestBlockhash(ctx, rpc.CommitmentFinalized)
38+
if err != nil {
39+
panic(fmt.Errorf("get blockhash: %w", err))
40+
}
41+
42+
tx, err := solana.NewTransaction(
43+
[]solana.Instruction{
44+
system.NewTransferInstruction(
45+
solana.LAMPORTS_PER_SOL/1000, // 0.001 SOL
46+
from,
47+
to,
48+
).Build(),
49+
},
50+
recent.Value.Blockhash,
51+
solana.TransactionPayer(from),
52+
)
53+
if err != nil {
54+
panic(fmt.Errorf("build tx: %w", err))
55+
}
56+
57+
out, err := client.GetFeeForMessage(
58+
ctx,
59+
tx.Message.ToBase64(),
3160
rpc.CommitmentProcessed,
3261
)
3362
if err != nil {
3463
panic(err)
3564
}
36-
spew.Dump(example)
65+
spew.Dump(out)
3766
}

rpc/examples/getLeaderSchedule/getLeaderSchedule.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,29 @@ package main
1616

1717
import (
1818
"context"
19+
"fmt"
1920

20-
"github.com/davecgh/go-spew/spew"
2121
"github.com/gagliardetto/solana-go/rpc"
2222
)
2323

2424
func main() {
25-
endpoint := rpc.TestNet_RPC
26-
client := rpc.New(endpoint)
25+
ctx := context.Background()
26+
client := rpc.New(rpc.MainNetBeta_RPC)
2727

28-
out, err := client.GetLeaderSchedule(
29-
context.TODO(),
30-
)
28+
out, err := client.GetLeaderSchedule(ctx)
3129
if err != nil {
3230
panic(err)
3331
}
34-
spew.Dump(out) // NOTE: this creates a lot of output
32+
33+
// The response maps every validator in the current epoch to its
34+
// scheduled slots; on mainnet this is huge. Only print a summary.
35+
fmt.Println("validators in current epoch:", len(out))
36+
count := 0
37+
for validator, slots := range out {
38+
if count >= 5 {
39+
break
40+
}
41+
fmt.Printf(" %s -> %d slots\n", validator, len(slots))
42+
count++
43+
}
3544
}

rpc/examples/getProgramAccounts/getProgramAccounts.go

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,43 @@ package main
1616

1717
import (
1818
"context"
19+
"fmt"
1920

20-
"github.com/davecgh/go-spew/spew"
2121
"github.com/gagliardetto/solana-go"
2222
"github.com/gagliardetto/solana-go/rpc"
2323
)
2424

25+
// getProgramAccounts returns every account owned by a program. Public
26+
// mainnet RPCs reject it without a restrictive filter because the
27+
// response would be too large. This example filters Token-2022 accounts
28+
// down to just mint accounts (82-byte data) and prints the first few.
2529
func main() {
26-
endpoint := rpc.TestNet_RPC
27-
client := rpc.New(endpoint)
30+
ctx := context.Background()
31+
client := rpc.New(rpc.MainNetBeta_RPC)
2832

29-
out, err := client.GetProgramAccounts(
30-
context.TODO(),
31-
solana.MustPublicKeyFromBase58("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"),
33+
out, err := client.GetProgramAccountsWithOpts(
34+
ctx,
35+
solana.Token2022ProgramID,
36+
&rpc.GetProgramAccountsOpts{
37+
Commitment: rpc.CommitmentFinalized,
38+
Filters: []rpc.RPCFilter{
39+
{DataSize: 82}, // SPL Token mint account size
40+
},
41+
// Only fetch the first byte of data so the response stays small.
42+
DataSlice: &rpc.DataSlice{Offset: ptrU64(0), Length: ptrU64(1)},
43+
},
3244
)
3345
if err != nil {
3446
panic(err)
3547
}
36-
spew.Dump(len(out))
37-
spew.Dump(out) // NOTE: this can generate a lot of output
48+
49+
fmt.Println("Token-2022 mints found:", len(out))
50+
for i, acc := range out {
51+
if i >= 5 {
52+
break
53+
}
54+
fmt.Printf(" %d: %s\n", i, acc.Pubkey)
55+
}
3856
}
57+
58+
func ptrU64(v uint64) *uint64 { return &v }

rpc/examples/getSignatureStatuses/getSignatureStatuses.go

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,42 @@ package main
1616

1717
import (
1818
"context"
19+
"fmt"
1920

2021
"github.com/davecgh/go-spew/spew"
2122
"github.com/gagliardetto/solana-go"
2223
"github.com/gagliardetto/solana-go/rpc"
2324
)
2425

2526
func main() {
26-
endpoint := rpc.TestNet_RPC
27-
client := rpc.New(endpoint)
27+
ctx := context.Background()
28+
client := rpc.New(rpc.MainNetBeta_RPC)
29+
30+
// Fetch fresh signatures so the example keeps working as the
31+
// cluster advances.
32+
limit := 2
33+
sigs, err := client.GetSignaturesForAddressWithOpts(
34+
ctx,
35+
solana.TokenProgramID,
36+
&rpc.GetSignaturesForAddressOpts{Limit: &limit},
37+
)
38+
if err != nil {
39+
panic(fmt.Errorf("getSignaturesForAddress: %w", err))
40+
}
41+
if len(sigs) == 0 {
42+
panic("no recent signatures found")
43+
}
44+
45+
toLookup := make([]solana.Signature, 0, len(sigs))
46+
for _, s := range sigs {
47+
toLookup = append(toLookup, s.Signature)
48+
}
49+
fmt.Println("querying statuses for", len(toLookup), "signatures")
2850

2951
out, err := client.GetSignatureStatuses(
30-
context.TODO(),
31-
true,
32-
// All the transactions you want the get the status for:
33-
solana.MustSignatureFromBase58("2CwH8SqVZWFa1EvsH7vJXGFors1NdCuWJ7Z85F8YqjCLQ2RuSHQyeGKkfo1Tj9HitSTeLoMWnxpjxF2WsCH8nGWh"),
34-
solana.MustSignatureFromBase58("5YJHZPeHZuZjhunBc1CCB1NDRNf2tTJNpdb3azGsR7PfyEncCDhr95wG8EWrvjNXBc4wCKixkheSbCxoC2NCG3X7"),
52+
ctx,
53+
true, // searchTransactionHistory
54+
toLookup...,
3555
)
3656
if err != nil {
3757
panic(err)

rpc/examples/getTransaction/getTransaction.go

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package main
1616

1717
import (
1818
"context"
19+
"fmt"
1920

2021
"github.com/davecgh/go-spew/spew"
2122
bin "github.com/gagliardetto/binary"
@@ -24,28 +25,34 @@ import (
2425
)
2526

2627
func main() {
27-
endpoint := rpc.TestNet_RPC
28-
client := rpc.New(endpoint)
28+
ctx := context.Background()
29+
client := rpc.New(rpc.MainNetBeta_RPC)
2930

30-
txSig := solana.MustSignatureFromBase58("4bjVLV1g9SAfv7BSAdNnuSPRbSscADHFe4HegL6YVcuEBMY83edLEvtfjE4jfr6rwdLwKBQbaFiGgoLGtVicDzHq")
31-
{
32-
out, err := client.GetTransaction(
33-
context.TODO(),
34-
txSig,
35-
nil,
36-
)
37-
if err != nil {
38-
panic(err)
39-
}
40-
spew.Dump(out)
41-
spew.Dump(out.Transaction.GetTransaction())
31+
// Fetch a fresh signature so the example keeps working as the
32+
// cluster advances. The SPL Token program always has recent activity
33+
// on mainnet-beta.
34+
limit := 1
35+
sigs, err := client.GetSignaturesForAddressWithOpts(
36+
ctx,
37+
solana.TokenProgramID,
38+
&rpc.GetSignaturesForAddressOpts{Limit: &limit},
39+
)
40+
if err != nil {
41+
panic(fmt.Errorf("getSignaturesForAddress: %w", err))
42+
}
43+
if len(sigs) == 0 {
44+
panic("no recent signatures found")
4245
}
46+
txSig := sigs[0].Signature
47+
fmt.Println("fetching tx:", txSig)
48+
49+
maxVersion := uint64(0)
4350
{
4451
out, err := client.GetTransaction(
45-
context.TODO(),
52+
ctx,
4653
txSig,
4754
&rpc.GetTransactionOpts{
48-
Encoding: solana.EncodingJSON,
55+
MaxSupportedTransactionVersion: &maxVersion,
4956
},
5057
)
5158
if err != nil {
@@ -56,24 +63,26 @@ func main() {
5663
}
5764
{
5865
out, err := client.GetTransaction(
59-
context.TODO(),
66+
ctx,
6067
txSig,
6168
&rpc.GetTransactionOpts{
62-
Encoding: solana.EncodingBase58,
69+
Encoding: solana.EncodingJSON,
70+
MaxSupportedTransactionVersion: &maxVersion,
6371
},
6472
)
6573
if err != nil {
6674
panic(err)
6775
}
6876
spew.Dump(out)
69-
spew.Dump(out.Transaction.GetBinary())
77+
spew.Dump(out.Transaction.GetTransaction())
7078
}
7179
{
7280
out, err := client.GetTransaction(
73-
context.TODO(),
81+
ctx,
7482
txSig,
7583
&rpc.GetTransactionOpts{
76-
Encoding: solana.EncodingBase64,
84+
Encoding: solana.EncodingBase64,
85+
MaxSupportedTransactionVersion: &maxVersion,
7786
},
7887
)
7988
if err != nil {

rpc/examples/isBlockhashValid/isValidBlockhash.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,29 @@ import (
1919
"fmt"
2020

2121
"github.com/davecgh/go-spew/spew"
22-
"github.com/gagliardetto/solana-go"
2322
"github.com/gagliardetto/solana-go/rpc"
2423
)
2524

2625
func main() {
27-
endpoint := rpc.MainNetBeta_RPC
28-
client := rpc.New(endpoint)
26+
ctx := context.Background()
27+
client := rpc.New(rpc.MainNetBeta_RPC)
28+
29+
// Blockhashes are only valid for ~150 blocks (~1 minute), so fetch
30+
// a live one instead of hardcoding.
31+
recent, err := client.GetLatestBlockhash(ctx, rpc.CommitmentFinalized)
32+
if err != nil {
33+
panic(fmt.Errorf("get blockhash: %w", err))
34+
}
2935

30-
blockHash := solana.MustHashFromBase58("J7rBdM6AecPDEZp8aPq5iPSNKVkU5Q76F3oAV4eW5wsW")
3136
out, err := client.IsBlockhashValid(
32-
context.TODO(),
33-
blockHash,
37+
ctx,
38+
recent.Value.Blockhash,
3439
rpc.CommitmentFinalized,
3540
)
3641
if err != nil {
3742
panic(err)
3843
}
3944
spew.Dump(out)
40-
spew.Dump(out.Value) // true or false
4145

42-
fmt.Println("is blockhash valid:", out.Value)
46+
fmt.Println("is blockhash valid:", out.Value) // true or false
4347
}

0 commit comments

Comments
 (0)