GithubHelp home page GithubHelp logo

gagliardetto / solana-go Goto Github PK

View Code? Open in Web Editor NEW
717.0 15.0 219.0 3.81 MB

Go SDK library and RPC client for the Solana Blockchain

License: Apache License 2.0

Go 100.00%
solana sdk golang blockchain rpc

solana-go's Introduction

Solana SDK library for Go

GoDoc GitHub tag (latest SemVer pre-release) Build Status TODOs Go Report Card

Go library to interface with Solana JSON RPC and WebSocket interfaces.

More contracts to come.

If you're using/developing Solana programs written in Anchor Framework, you can use anchor-go to generate Golang clients

If you're looking for a SERUM library, you can check out gagliardetto/serum-go (./programs/serum is deprecated.)

Future Development

solana-go is exclusively supported by my own time (which is money).

If my work has been useful in building your for-profit services/infra/bots/etc., consider donating at 8tTwBazKr2ST1b2kNrM7JMXwixRTvZicn7eRBihThymm (solana) to support future development.

Thanks!

Contents

Features

  • Full JSON RPC API
  • Full WebSocket JSON streaming API
  • Wallet, account, and keys management
  • Clients for native programs
    • system
    • config
    • stake
    • vote
    • BPF Loader
    • Secp256k1
  • Clients for Solana Program Library (SPL)
  • Client for Serum
  • Metaplex:
    • auction
    • metaplex
    • token-metadata
    • token-vault
    • nft-candy-machine
  • More programs

Current development status

There is currently no stable release. The SDK is actively developed and latest is v1.10.0 which is an alpha release.

The RPC and WS client implementation is based on this RPC spec.

Note

  • solana-go is in active development, so all APIs are subject to change.
  • This code is unaudited. Use at your own risk.

Requirements

  • Go 1.18 or later

Installation

$ cd my-project
$ go get github.com/gagliardetto/[email protected]

Pretty-Print transactions/instructions

pretty-printed

Instructions can be pretty-printed with the String() method on a Transaction:

tx, err := solana.NewTransaction(
  []solana.Instruction{
    system.NewTransferInstruction(
      amount,
      accountFrom.PublicKey(),
      accountTo,
    ).Build(),
  },
  recent.Value.Blockhash,
  solana.TransactionPayer(accountFrom.PublicKey()),
)

...

// Pretty print the transaction:
fmt.Println(tx.String())
// OR you can choose a destination and a title:
// tx.EncodeTree(text.NewTreeEncoder(os.Stdout, "Transfer SOL"))

SendAndConfirmTransaction

You can wait for a transaction confirmation using the github.com/gagliardetto/solana-go/rpc/sendAndConfirmTransaction package tools (for a complete example: see here)

// Send transaction, and wait for confirmation:
sig, err := confirm.SendAndConfirmTransaction(
  context.TODO(),
  rpcClient,
  wsClient,
  tx,
)
if err != nil {
  panic(err)
}
spew.Dump(sig)

The above command will send the transaction, and wait for its confirmation.

Address Lookup Tables

Resolve lookups for a transaction:

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/gagliardetto/solana-go"
	lookup "github.com/gagliardetto/solana-go/programs/address-lookup-table"
	"github.com/gagliardetto/solana-go/rpc"
	"golang.org/x/time/rate"
)

func main() {
	cluster := rpc.MainNetBeta

	rpcClient := rpc.NewWithCustomRPCClient(rpc.NewWithLimiter(
		cluster.RPC,
		rate.Every(time.Second), // time frame
		5,                       // limit of requests per time frame
	))

	version := uint64(0)
	tx, err := rpcClient.GetTransaction(
		context.Background(),
		solana.MustSignatureFromBase58("24jRjMP3medE9iMqVSPRbkwfe9GdPmLfeftKPuwRHZdYTZJ6UyzNMGGKo4BHrTu2zVj4CgFF3CEuzS79QXUo2CMC"),
		&rpc.GetTransactionOpts{
			MaxSupportedTransactionVersion: &version,
			Encoding:                       solana.EncodingBase64,
		},
	)
	if err != nil {
		panic(err)
	}
	parsed, err := tx.Transaction.GetTransaction()
	if err != nil {
		panic(err)
	}
	processTransactionWithAddressLookups(*parsed, rpcClient)
}

func processTransactionWithAddressLookups(txx solana.Transaction, rpcClient *rpc.Client) {
	if !txx.Message.IsVersioned() {
		fmt.Println("tx is not versioned; only versioned transactions can contain lookups")
		return
	}
	tblKeys := txx.Message.GetAddressTableLookups().GetTableIDs()
	if len(tblKeys) == 0 {
		fmt.Println("no lookup tables in versioned transaction")
		return
	}
	numLookups := txx.Message.GetAddressTableLookups().NumLookups()
	if numLookups == 0 {
		fmt.Println("no lookups in versioned transaction")
		return
	}
	fmt.Println("num lookups:", numLookups)
	fmt.Println("num tbl keys:", len(tblKeys))
	resolutions := make(map[solana.PublicKey]solana.PublicKeySlice)
	for _, key := range tblKeys {
		fmt.Println("Getting table", key)

		info, err := rpcClient.GetAccountInfo(
			context.Background(),
			key,
		)
		if err != nil {
			panic(err)
		}
		fmt.Println("got table "+key.String())

		tableContent, err := lookup.DecodeAddressLookupTableState(info.GetBinary())
		if err != nil {
			panic(err)
		}

		fmt.Println("table content:", spew.Sdump(tableContent))
		fmt.Println("isActive", tableContent.IsActive())

		resolutions[key] = tableContent.Addresses
	}

	err := txx.Message.SetAddressTables(resolutions)
	if err != nil {
		panic(err)
	}

	err = txx.Message.ResolveLookups()
	if err != nil {
		panic(err)
	}
	fmt.Println(txx.String())
}

Parse/decode an instruction from a transaction

package main

import (
  "context"
  "encoding/base64"
  "os"
  "reflect"

  "github.com/davecgh/go-spew/spew"
  bin "github.com/gagliardetto/binary"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/programs/system"
  "github.com/gagliardetto/solana-go/rpc"
  "github.com/gagliardetto/solana-go/text"
)

func main() {
  exampleFromGetTransaction()
}

func exampleFromBase64() {
  encoded := "AfjEs3XhTc3hrxEvlnMPkm/cocvAUbFNbCl00qKnrFue6J53AhEqIFmcJJlJW3EDP5RmcMz+cNTTcZHW/WJYwAcBAAEDO8hh4VddzfcO5jbCt95jryl6y8ff65UcgukHNLWH+UQGgxCGGpgyfQVQV02EQYqm4QwzUt2qf9f1gVLM7rI4hwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6ANIF55zOZWROWRkeh+lExxZBnKFqbvIxZDLE7EijjoBAgIAAQwCAAAAOTAAAAAAAAA="

  data, err := base64.StdEncoding.DecodeString(encoded)
  if err != nil {
    panic(err)
  }

  // parse transaction:
  tx, err := solana.TransactionFromDecoder(bin.NewBinDecoder(data))
  if err != nil {
    panic(err)
  }

  decodeSystemTransfer(tx)
}

func exampleFromGetTransaction() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  txSig := solana.MustSignatureFromBase58("3hZorctJtD3QLCRV3zF6JM6FDbFR5kAvsuKEG1RH9rWdz8YgnDzAvMWZFjdJgoL8KSNzZnx7aiExm1JEMC8KHfyy")
  {
    out, err := client.GetTransaction(
      context.TODO(),
      txSig,
      &rpc.GetTransactionOpts{
        Encoding: solana.EncodingBase64,
      },
    )
    if err != nil {
      panic(err)
    }

    tx, err := solana.TransactionFromDecoder(bin.NewBinDecoder(out.Transaction.GetBinary()))
    if err != nil {
      panic(err)
    }

    decodeSystemTransfer(tx)
  }
}

func decodeSystemTransfer(tx *solana.Transaction) {
  spew.Dump(tx)

  // Get (for example) the first instruction of this transaction
  // which we know is a `system` program instruction:
  i0 := tx.Message.Instructions[0]

  // Find the program address of this instruction:
  progKey, err := tx.ResolveProgramIDIndex(i0.ProgramIDIndex)
  if err != nil {
    panic(err)
  }

  // Find the accounts of this instruction:
  accounts, err := i0.ResolveInstructionAccounts(&tx.Message)
  if err != nil {
    panic(err)
  }

  // Feed the accounts and data to the system program parser
  // OR see below for alternative parsing when you DON'T know
  // what program the instruction is for / you don't have a parser.
  inst, err := system.DecodeInstruction(accounts, i0.Data)
  if err != nil {
    panic(err)
  }

  // inst.Impl contains the specific instruction type (in this case, `inst.Impl` is a `*system.Transfer`)
  spew.Dump(inst)
  if _, ok := inst.Impl.(*system.Transfer); !ok {
    panic("the instruction is not a *system.Transfer")
  }

  // OR
  {
    // There is a more general instruction decoder: `solana.DecodeInstruction`.
    // But before you can use `solana.DecodeInstruction`,
    // you must register a decoder for each program ID beforehand
    // by using `solana.RegisterInstructionDecoder` (all solana-go program clients do it automatically with the default program IDs).
    decodedInstruction, err := solana.DecodeInstruction(
      progKey,
      accounts,
      i0.Data,
    )
    if err != nil {
      panic(err)
    }
    // The returned `decodedInstruction` is the decoded instruction.
    spew.Dump(decodedInstruction)

    // decodedInstruction == inst
    if !reflect.DeepEqual(inst, decodedInstruction) {
      panic("they are NOT equal (this would never happen)")
    }

    // To register other (not yet registered decoders), you can add them with
    // `solana.RegisterInstructionDecoder` function.
  }

  {
    // pretty-print whole transaction:
    _, err := tx.EncodeTree(text.NewTreeEncoder(os.Stdout, text.Bold("TEST TRANSACTION")))
    if err != nil {
      panic(err)
    }
  }
}

Borsh encoding/decoding

You can use the github.com/gagliardetto/binary package for encoding/decoding borsh-encoded data:

Decoder:

  resp, err := client.GetAccountInfo(
    context.TODO(),
    pubKey,
  )
  if err != nil {
    panic(err)
  }

  borshDec := bin.NewBorshDecoder(resp.GetBinary())
  var meta token_metadata.Metadata
  err = borshDec.Decode(&meta)
  if err != nil {
    panic(err)
  }

Encoder:

buf := new(bytes.Buffer)
borshEncoder := bin.NewBorshEncoder(buf)
err := borshEncoder.Encode(meta)
if err != nil {
  panic(err)
}
// fmt.Print(buf.Bytes())

ZSTD account data encoding

You can request account data to be encoded with base64+zstd in the Encoding parameter:

resp, err := client.GetAccountInfoWithOpts(
  context.TODO(),
  pubKey,
  &rpc.GetAccountInfoOpts{
    Encoding:   solana.EncodingBase64Zstd,
    Commitment: rpc.CommitmentFinalized,
  },
)
if err != nil {
  panic(err)
}
spew.Dump(resp)

var mint token.Mint
err = bin.NewDecoder(resp.GetBinary()).Decode(&mint)
if err != nil {
  panic(err)
}
spew.Dump(mint)

Working with rate-limited RPC providers

package main

import (
  "context"

  "golang.org/x/time/rate"
  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  cluster := rpc.MainNetBeta
  client := rpc.NewWithCustomRPCClient(rpc.NewWithLimiter(
		cluster.RPC,
		rate.Every(time.Second), // time frame
		5,                       // limit of requests per time frame
	))

  out, err := client.GetVersion(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

Custom Headers for authenticating with RPC providers

package main

import (
  "context"

  "golang.org/x/time/rate"
  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  cluster := rpc.MainNetBeta
  client := rpc.NewWithHeaders(
    cluster.RPC,
    map[string]string{
      "x-api-key": "...",
    },
  )

  out, err := client.GetVersion(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

The data will AUTOMATICALLY get decoded and returned (the right decoder will be used) when you call the resp.GetBinary() method.

Timeouts and Custom HTTP Clients

You can use a timeout context:

ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
defer cancel()
acc, err := rpcClient.GetAccountInfoWithOpts(
  ctx,
  accountID,
  &rpc.GetAccountInfoOpts{
    Commitment: rpc.CommitmentProcessed,
  },
)

Or you can initialize the RPC client using a custom HTTP client using rpc.NewWithCustomRPCClient:

import (
  "net"
  "net/http"
  "time"

  "github.com/gagliardetto/solana-go/rpc"
  "github.com/gagliardetto/solana-go/rpc/jsonrpc"
)

func NewHTTPTransport(
  timeout time.Duration,
  maxIdleConnsPerHost int,
  keepAlive time.Duration,
) *http.Transport {
  return &http.Transport{
    IdleConnTimeout:     timeout,
    MaxIdleConnsPerHost: maxIdleConnsPerHost,
    Proxy:               http.ProxyFromEnvironment,
    Dial: (&net.Dialer{
      Timeout:   timeout,
      KeepAlive: keepAlive,
    }).Dial,
  }
}

// NewHTTP returns a new Client from the provided config.
func NewHTTP(
  timeout time.Duration,
  maxIdleConnsPerHost int,
  keepAlive time.Duration,
) *http.Client {
  tr := NewHTTPTransport(
    timeout,
    maxIdleConnsPerHost,
    keepAlive,
  )

  return &http.Client{
    Timeout:   timeout,
    Transport: tr,
  }
}

// NewRPC creates a new Solana JSON RPC client.
func NewRPC(rpcEndpoint string) *rpc.Client {
  var (
    defaultMaxIdleConnsPerHost = 10
    defaultTimeout             = 25 * time.Second
    defaultKeepAlive           = 180 * time.Second
  )
  opts := &jsonrpc.RPCClientOpts{
    HTTPClient: NewHTTP(
      defaultTimeout,
      defaultMaxIdleConnsPerHost,
      defaultKeepAlive,
    ),
  }
  rpcClient := jsonrpc.NewClientWithOpts(rpcEndpoint, opts)
  return rpc.NewWithCustomRPCClient(rpcClient)
}

Examples

Create account (wallet)

package main

import (
  "context"
  "fmt"

  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  // Create a new account:
  account := solana.NewWallet()
  fmt.Println("account private key:", account.PrivateKey)
  fmt.Println("account public key:", account.PublicKey())

  // Create a new RPC client:
  client := rpc.New(rpc.TestNet_RPC)

  // Airdrop 1 SOL to the new account:
  out, err := client.RequestAirdrop(
    context.TODO(),
    account.PublicKey(),
    solana.LAMPORTS_PER_SOL*1,
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  fmt.Println("airdrop transaction signature:", out)
}

Load/parse private and public keys

{
  // Load private key from a json file generated with
  // $ solana-keygen new --outfile=standard.solana-keygen.json
  privateKey, err := solana.PrivateKeyFromSolanaKeygenFile("/path/to/standard.solana-keygen.json")
  if err != nil {
    panic(err)
  }
  fmt.Println("private key:", privateKey.String())
  // To get the public key, you need to call the `PublicKey()` method:
  publicKey := privateKey.PublicKey()
  // To get the base58 string of a public key, you can call the `String()` method:
  fmt.Println("public key:", publicKey.String())
}

{
  // Load private key from base58:
  {
    privateKey, err := solana.PrivateKeyFromBase58("66cDvko73yAf8LYvFMM3r8vF5vJtkk7JKMgEKwkmBC86oHdq41C7i1a2vS3zE1yCcdLLk6VUatUb32ZzVjSBXtRs")
    if err != nil {
      panic(err)
    }
    fmt.Println("private key:", privateKey.String())
    fmt.Println("public key:", privateKey.PublicKey().String())
  }
  // OR:
  {
    privateKey := solana.MustPrivateKeyFromBase58("66cDvko73yAf8LYvFMM3r8vF5vJtkk7JKMgEKwkmBC86oHdq41C7i1a2vS3zE1yCcdLLk6VUatUb32ZzVjSBXtRs")
    _ = privateKey
  }
}

{
  // Generate a new key pair:
  {
    privateKey, err := solana.NewRandomPrivateKey()
    if err != nil {
      panic(err)
    }
    _ = privateKey
  }
  {
    { // Generate a new private key (a Wallet struct is just a wrapper around a private key)
      account := solana.NewWallet()
      _ = account
    }
  }
}

{
  // Parse a public key from a base58 string:
  {
    publicKey, err := solana.PublicKeyFromBase58("F8UvVsKnzWyp2nF8aDcqvQ2GVcRpqT91WDsAtvBKCMt9")
    if err != nil {
      panic(err)
    }
    _ = publicKey
  }
  // OR:
  {
    publicKey := solana.MustPublicKeyFromBase58("F8UvVsKnzWyp2nF8aDcqvQ2GVcRpqT91WDsAtvBKCMt9")
    _ = publicKey
  }
}

Transfer Sol from one wallet to another wallet

package main

import (
  "context"
  "fmt"
  "os"
  "time"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/programs/system"
  "github.com/gagliardetto/solana-go/rpc"
  confirm "github.com/gagliardetto/solana-go/rpc/sendAndConfirmTransaction"
  "github.com/gagliardetto/solana-go/rpc/jsonrpc"
  "github.com/gagliardetto/solana-go/rpc/ws"
  "github.com/gagliardetto/solana-go/text"
)

func main() {
  // Create a new RPC client:
  rpcClient := rpc.New(rpc.DevNet_RPC)

  // Create a new WS client (used for confirming transactions)
  wsClient, err := ws.Connect(context.Background(), rpc.DevNet_WS)
  if err != nil {
    panic(err)
  }

  // Load the account that you will send funds FROM:
  accountFrom, err := solana.PrivateKeyFromSolanaKeygenFile("/path/to/.config/solana/id.json")
  if err != nil {
    panic(err)
  }
  fmt.Println("accountFrom private key:", accountFrom)
  fmt.Println("accountFrom public key:", accountFrom.PublicKey())

  // The public key of the account that you will send sol TO:
  accountTo := solana.MustPublicKeyFromBase58("TODO")
  // The amount to send (in lamports);
  // 1 sol = 1000000000 lamports
  amount := uint64(3333)

  if true {
    // Airdrop 1 sol to the account so it will have something to transfer:
    out, err := rpcClient.RequestAirdrop(
      context.TODO(),
      accountFrom.PublicKey(),
      solana.LAMPORTS_PER_SOL*1,
      rpc.CommitmentFinalized,
    )
    if err != nil {
      panic(err)
    }
    fmt.Println("airdrop transaction signature:", out)
    time.Sleep(time.Second * 5)
  }
  //---------------

  recent, err := rpcClient.GetRecentBlockhash(context.TODO(), rpc.CommitmentFinalized)
  if err != nil {
    panic(err)
  }

  tx, err := solana.NewTransaction(
    []solana.Instruction{
      system.NewTransferInstruction(
        amount,
        accountFrom.PublicKey(),
        accountTo,
      ).Build(),
    },
    recent.Value.Blockhash,
    solana.TransactionPayer(accountFrom.PublicKey()),
  )
  if err != nil {
    panic(err)
  }

  _, err = tx.Sign(
    func(key solana.PublicKey) *solana.PrivateKey {
      if accountFrom.PublicKey().Equals(key) {
        return &accountFrom
      }
      return nil
    },
  )
  if err != nil {
    panic(fmt.Errorf("unable to sign transaction: %w", err))
  }
  spew.Dump(tx)
  // Pretty print the transaction:
  tx.EncodeTree(text.NewTreeEncoder(os.Stdout, "Transfer SOL"))

  // Send transaction, and wait for confirmation:
  sig, err := confirm.SendAndConfirmTransaction(
    context.TODO(),
    rpcClient,
    wsClient,
    tx,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(sig)

  // Or just send the transaction WITHOUT waiting for confirmation:
  // sig, err := rpcClient.SendTransactionWithOpts(
  //   context.TODO(),
  //   tx,
  //   false,
  //   rpc.CommitmentFinalized,
  // )
  // if err != nil {
  //   panic(err)
  // }
  // spew.Dump(sig)
}

RPC usage examples

RPC Methods

index > RPC > GetAccountInfo

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  bin "github.com/gagliardetto/binary"
  solana "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/programs/token"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.MainNetBeta_RPC
  client := rpc.New(endpoint)

  {
    pubKey := solana.MustPublicKeyFromBase58("SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt") // serum token
    // basic usage
    resp, err := client.GetAccountInfo(
      context.TODO(),
      pubKey,
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(resp)

    var mint token.Mint
    // Account{}.Data.GetBinary() returns the *decoded* binary data
    // regardless the original encoding (it can handle them all).
    err = bin.NewDecoder(resp.GetBinary()).Decode(&mint)
    if err != nil {
      panic(err)
    }
    spew.Dump(mint)
    // NOTE: The supply is mint.Supply, with the mint.Decimals:
    // mint.Supply = 9998022451607088
    // mint.Decimals = 6
    // ... which means that the supply is 9998022451.607088
  }
  {
    // Or you can use `GetAccountDataInto` which does all of the above in one call:
    pubKey := solana.MustPublicKeyFromBase58("SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt") // serum token
    var mint token.Mint
    // Get the account, and decode its data into the provided mint object:
    err := client.GetAccountDataInto(
      context.TODO(),
      pubKey,
      &mint,
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(mint)
  }
  {
    // // Or you can use `GetAccountDataBorshInto` which does all of the above in one call but for borsh-encoded data:
    // var metadata token_metadata.Metadata
    // // Get the account, and decode its data into the provided metadata object:
    // err := client.GetAccountDataBorshInto(
    //   context.TODO(),
    //   pubKey,
    //   &metadata,
    // )
    // if err != nil {
    //   panic(err)
    // }
    // spew.Dump(metadata)
  }
  {
    pubKey := solana.MustPublicKeyFromBase58("4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R") // raydium token
    // advanced usage
    resp, err := client.GetAccountInfoWithOpts(
      context.TODO(),
      pubKey,
      // You can specify more options here:
      &rpc.GetAccountInfoOpts{
        Encoding:   solana.EncodingBase64Zstd,
        Commitment: rpc.CommitmentFinalized,
        // You can get just a part of the account data by specify a DataSlice:
        // DataSlice: &rpc.DataSlice{
        //  Offset: pointer.ToUint64(0),
        //  Length: pointer.ToUint64(1024),
        // },
      },
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(resp)

    var mint token.Mint
    err = bin.NewDecoder(resp.GetBinary()).Decode(&mint)
    if err != nil {
      panic(err)
    }
    spew.Dump(mint)
  }
}

index > RPC > GetBalance

package main

import (
  "context"
  "fmt"
  "math/big"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.MainNetBeta_RPC
  client := rpc.New(endpoint)

  pubKey := solana.MustPublicKeyFromBase58("7xLk17EQQ5KLDLDe44wCmupJKJjTGd8hs3eSVVhCx932")
  out, err := client.GetBalance(
    context.TODO(),
    pubKey,
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
  spew.Dump(out.Value) // total lamports on the account; 1 sol = 1000000000 lamports

  var lamportsOnAccount = new(big.Float).SetUint64(uint64(out.Value))
  // Convert lamports to sol:
  var solBalance = new(big.Float).Quo(lamportsOnAccount, new(big.Float).SetUint64(solana.LAMPORTS_PER_SOL))

  // WARNING: this is not a precise conversion.
  fmt.Println("◎", solBalance.Text('f', 10))
}

index > RPC > GetBlock

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  example, err := client.GetRecentBlockhash(context.TODO(), rpc.CommitmentFinalized)
  if err != nil {
    panic(err)
  }

  {
    out, err := client.GetBlock(context.TODO(), uint64(example.Context.Slot))
    if err != nil {
      panic(err)
    }
    // spew.Dump(out) // NOTE: This generates a lot of output.
    spew.Dump(len(out.Transactions))
  }

  {
    includeRewards := false
    out, err := client.GetBlockWithOpts(
      context.TODO(),
      uint64(example.Context.Slot),
      // You can specify more options here:
      &rpc.GetBlockOpts{
        Encoding:   solana.EncodingBase64,
        Commitment: rpc.CommitmentFinalized,
        // Get only signatures:
        TransactionDetails: rpc.TransactionDetailsSignatures,
        // Exclude rewards:
        Rewards: &includeRewards,
      },
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(out)
  }
}

index > RPC > GetBlockCommitment

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  example, err := client.GetRecentBlockhash(context.TODO(), rpc.CommitmentFinalized)
  if err != nil {
    panic(err)
  }

  out, err := client.GetBlockCommitment(
    context.TODO(),
    uint64(example.Context.Slot),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetBlockHeight

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetBlockHeight(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetBlockProduction

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  {
    out, err := client.GetBlockProduction(context.TODO())
    if err != nil {
      panic(err)
    }
    spew.Dump(out)
  }
  {
    out, err := client.GetBlockProductionWithOpts(
      context.TODO(),
      &rpc.GetBlockProductionOpts{
        Commitment: rpc.CommitmentFinalized,
        // Range: &rpc.SlotRangeRequest{
        //  FirstSlot: XXXXXX,
        //  Identity:  solana.MustPublicKeyFromBase58("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
        // },
      },
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(out)
  }
}

index > RPC > GetBlockTime

package main

import (
  "context"
  "time"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  example, err := client.GetRecentBlockhash(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }

  out, err := client.GetBlockTime(
    context.TODO(),
    uint64(example.Context.Slot),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
  spew.Dump(out.Time().Format(time.RFC1123))
}

index > RPC > GetBlocks

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  example, err := client.GetRecentBlockhash(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }

  endSlot := uint64(example.Context.Slot)
  out, err := client.GetBlocks(
    context.TODO(),
    uint64(example.Context.Slot-3),
    &endSlot,
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetBlocksWithLimit

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  example, err := client.GetRecentBlockhash(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }

  limit := uint64(4)
  out, err := client.GetBlocksWithLimit(
    context.TODO(),
    uint64(example.Context.Slot-10),
    limit,
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetClusterNodes

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetClusterNodes(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetConfirmedBlock

package main

import (
  "context"

  "github.com/AlekSi/pointer"
  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  example, err := client.GetRecentBlockhash(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }

  { // deprecated and is going to be removed in solana-core v1.8
    out, err := client.GetConfirmedBlock(
      context.TODO(),
      uint64(example.Context.Slot),
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(out)
  }
  {
    slot := uint64(example.Context.Slot)
    out, err := client.GetConfirmedBlockWithOpts(
      context.TODO(),
      slot,
      // You can specify more options here:
      &rpc.GetConfirmedBlockOpts{
        Encoding:   solana.EncodingBase64,
        Commitment: rpc.CommitmentFinalized,
        // Get only signatures:
        TransactionDetails: rpc.TransactionDetailsSignatures,
        // Exclude rewards:
        Rewards: pointer.ToBool(false),
      },
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(out)
  }
}

index > RPC > GetConfirmedBlocks

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  example, err := client.GetRecentBlockhash(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }

  {
    endSlot := uint64(example.Context.Slot)
    // deprecated and is going to be removed in solana-core v1.8
    out, err := client.GetConfirmedBlocks(
      context.TODO(),
      uint64(example.Context.Slot-3),
      &endSlot,
      rpc.CommitmentFinalized,
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(out)
  }
}

index > RPC > GetConfirmedBlocksWithLimit

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  example, err := client.GetRecentBlockhash(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }

  limit := uint64(3)
  { // deprecated and is going to be removed in solana-core v1.8
    out, err := client.GetConfirmedBlocksWithLimit(
      context.TODO(),
      uint64(example.Context.Slot-10),
      limit,
      rpc.CommitmentFinalized,
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(out)
  }
}

index > RPC > GetConfirmedSignaturesForAddress2

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  pubKey := solana.MustPublicKeyFromBase58("SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt") // serum token
  {
    // deprecated and is going to be removed in solana-core v1.8
    out, err := client.GetConfirmedSignaturesForAddress2(
      context.TODO(),
      pubKey,
      // TODO:
      nil,
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(out)
  }
}

index > RPC > GetConfirmedTransaction

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  pubKey := solana.MustPublicKeyFromBase58("SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt") // serum token
  // Let's get a valid transaction to use in the example:
  example, err := client.GetConfirmedSignaturesForAddress2(
    context.TODO(),
    pubKey,
    nil,
  )
  if err != nil {
    panic(err)
  }

  out, err := client.GetConfirmedTransaction(
    context.TODO(),
    example[0].Signature,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetEpochInfo

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetEpochInfo(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetEpochSchedule

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetEpochSchedule(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetFeeCalculatorForBlockhash

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  example, err := client.GetRecentBlockhash(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }

  out, err := client.GetFeeCalculatorForBlockhash(
    context.TODO(),
    example.Value.Blockhash,
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetFeeRateGovernor

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetFeeRateGovernor(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetFees

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetFees(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetFeeForMessage

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  example, err := client.GetFeeForMessage(
    context.Background(),
    "AQABAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAA",
    rpc.CommitmentProcessed,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(example)
}

index > RPC > GetFirstAvailableBlock

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetFirstAvailableBlock(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetGenesisHash

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetGenesisHash(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetHealth

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetHealth(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
  spew.Dump(out == rpc.HealthOk)
}

index > RPC > GetHighestSnapshotSlot

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  example, err := client.GetHighestSnapshotSlot(
    context.Background(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(example)
}

index > RPC > GetLatestBlockhash

NEW: This method is only available in solana-core v1.9 or newer. Please use getRecentBlockhash for solana-core v1.8

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  example, err := client.GetLatestBlockhash(
    context.Background(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(example)
}

index > RPC > GetIdentity

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetIdentity(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetInflationGovernor

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetInflationGovernor(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetInflationRate

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetInflationRate(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetInflationReward

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  pubKey := solana.MustPublicKeyFromBase58("6dmNQ5jwLeLk5REvio1JcMshcbvkYMwy26sJ8pbkvStu")

  out, err := client.GetInflationReward(
    context.TODO(),
    []solana.PublicKey{
      pubKey,
    },
    &rpc.GetInflationRewardOpts{
      Commitment: rpc.CommitmentFinalized,
    },
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetLargestAccounts

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetLargestAccounts(
    context.TODO(),
    rpc.CommitmentFinalized,
    rpc.LargestAccountsFilterCirculating,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetLeaderSchedule

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetLeaderSchedule(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out) // NOTE: this creates a lot of output
}

index > RPC > GetMaxRetransmitSlot

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetMaxRetransmitSlot(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetMaxShredInsertSlot

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetMaxShredInsertSlot(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetMinimumBalanceForRentExemption

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  dataSize := uint64(1024 * 9)
  out, err := client.GetMinimumBalanceForRentExemption(
    context.TODO(),
    dataSize,
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetMultipleAccounts

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.MainNetBeta_RPC
  client := rpc.New(endpoint)

  {
    out, err := client.GetMultipleAccounts(
      context.TODO(),
      solana.MustPublicKeyFromBase58("SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt"),  // serum token
      solana.MustPublicKeyFromBase58("4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R"), // raydium token
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(out)
  }
  {
    out, err := client.GetMultipleAccountsWithOpts(
      context.TODO(),
      []solana.PublicKey{solana.MustPublicKeyFromBase58("SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt"), // serum token
        solana.MustPublicKeyFromBase58("4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R"), // raydium token
      },
      &rpc.GetMultipleAccountsOpts{
        Encoding:   solana.EncodingBase64Zstd,
        Commitment: rpc.CommitmentFinalized,
        // You can get just a part of the account data by specify a DataSlice:
        // DataSlice: &rpc.DataSlice{
        //  Offset: pointer.ToUint64(0),
        //  Length: pointer.ToUint64(1024),
        // },
      },
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(out)
  }
}

index > RPC > GetProgramAccounts

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetProgramAccounts(
    context.TODO(),
    solana.MustPublicKeyFromBase58("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(len(out))
  spew.Dump(out) // NOTE: this can generate a lot of output
}

index > RPC > GetRecentBlockhash

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  recent, err := client.GetRecentBlockhash(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(recent)
}

index > RPC > GetRecentPerformanceSamples

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  limit := uint(3)
  out, err := client.GetRecentPerformanceSamples(
    context.TODO(),
    &limit,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetRecentPrioritizationFees

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetRecentPrioritizationFees(
    context.TODO(),
    []solana.PublicKey{
      solana.MustPublicKeyFromBase58("q5BgreVhTyBH1QCeriVb7kQYEPneanFXPLjvyjdf8M3"),
    },
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetSignatureStatuses

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetSignatureStatuses(
    context.TODO(),
    true,
    // All the transactions you want the get the status for:
    solana.MustSignatureFromBase58("2CwH8SqVZWFa1EvsH7vJXGFors1NdCuWJ7Z85F8YqjCLQ2RuSHQyeGKkfo1Tj9HitSTeLoMWnxpjxF2WsCH8nGWh"),
    solana.MustSignatureFromBase58("5YJHZPeHZuZjhunBc1CCB1NDRNf2tTJNpdb3azGsR7PfyEncCDhr95wG8EWrvjNXBc4wCKixkheSbCxoC2NCG3X7"),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetSignaturesForAddress

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetSignaturesForAddress(
    context.TODO(),
    solana.MustPublicKeyFromBase58("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetSlot

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetSlot(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetSlotLeader

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetSlotLeader(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetSlotLeaders

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  recent, err := client.GetRecentBlockhash(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }

  out, err := client.GetSlotLeaders(
    context.TODO(),
    uint64(recent.Context.Slot),
    10,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetSnapshotSlot

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetSnapshotSlot(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetStakeActivation

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  pubKey := solana.MustPublicKeyFromBase58("EW2p7QCJNHMVj5nQCcW7Q2BDETtNBXn68FyucU4RCjvb")
  out, err := client.GetStakeActivation(
    context.TODO(),
    pubKey,
    rpc.CommitmentFinalized,
    nil,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetSupply

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetSupply(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetTokenAccountBalance

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  pubKey := solana.MustPublicKeyFromBase58("EzK5qLWhftu8Z2znVa5fozVtobbjhd8Gdu9hQHpC8bec")
  out, err := client.GetTokenAccountBalance(
    context.TODO(),
    pubKey,
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetTokenAccountsByDelegate

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  pubKey := solana.MustPublicKeyFromBase58("AfkALUPjQp8R1rUwE6KhT38NuTYWCncwwHwcJu7UtAfV")
  out, err := client.GetTokenAccountsByDelegate(
    context.TODO(),
    pubKey,
    &rpc.GetTokenAccountsConfig{
      Mint: solana.MustPublicKeyFromBase58("So11111111111111111111111111111111111111112"),
    },
    nil,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetTokenAccountsByOwner

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  bin "github.com/gagliardetto/binary"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/programs/token"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  pubKey := solana.MustPublicKeyFromBase58("7HZaCWazgTuuFuajxaaxGYbGnyVKwxvsJKue1W4Nvyro")
  out, err := client.GetTokenAccountsByOwner(
    context.TODO(),
    pubKey,
    &rpc.GetTokenAccountsConfig{
      Mint: solana.WrappedSol.ToPointer(),
    },
    &rpc.GetTokenAccountsOpts{
      Encoding: solana.EncodingBase64Zstd,
    },
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)

  {
    tokenAccounts := make([]token.Account, 0)
    for _, rawAccount := range out.Value {
      var tokAcc token.Account

      data := rawAccount.Account.Data.GetBinary()
      dec := bin.NewBinDecoder(data)
      err := dec.Decode(&tokAcc)
      if err != nil {
        panic(err)
      }
      tokenAccounts = append(tokenAccounts, tokAcc)
    }
    spew.Dump(tokenAccounts)
  }
}

index > RPC > GetTokenLargestAccounts

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.MainNetBeta_RPC
  client := rpc.New(endpoint)

  pubKey := solana.MustPublicKeyFromBase58("SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt") // serum token
  out, err := client.GetTokenLargestAccounts(
    context.TODO(),
    pubKey,
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetTokenSupply

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.MainNetBeta_RPC
  client := rpc.New(endpoint)

  pubKey := solana.MustPublicKeyFromBase58("SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt") // serum token
  out, err := client.GetTokenSupply(
    context.TODO(),
    pubKey,
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetTransaction

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  txSig := solana.MustSignatureFromBase58("4bjVLV1g9SAfv7BSAdNnuSPRbSscADHFe4HegL6YVcuEBMY83edLEvtfjE4jfr6rwdLwKBQbaFiGgoLGtVicDzHq")
  {
    out, err := client.GetTransaction(
      context.TODO(),
      txSig,
      &rpc.GetTransactionOpts{
        Encoding: solana.EncodingBase64,
      },
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(out)
    spew.Dump(out.Transaction.GetBinary())

    decodedTx, err := solana.TransactionFromDecoder(bin.NewBinDecoder(out.Transaction.GetBinary()))
    if err != nil {
      panic(err)
    }
    spew.Dump(decodedTx)
  }
  {
    out, err := client.GetTransaction(
      context.TODO(),
      txSig,
      nil,
    )
    if err != nil {
      panic(err)
    }
    spew.Dump(out)
    spew.Dump(out.Transaction.GetParsedTransaction())
  }
}

index > RPC > GetTransactionCount

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetTransactionCount(
    context.TODO(),
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetVersion

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetVersion(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > GetVoteAccounts

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.GetVoteAccounts(
    context.TODO(),
    &rpc.GetVoteAccountsOpts{
      VotePubkey: solana.MustPublicKeyFromBase58("vot33MHDqT6nSwubGzqtc6m16ChcUywxV7tNULF19Vu"),
    },
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > IsBlockhashValid

package main

import (
  "context"
  "fmt"
  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.MainNetBeta_RPC
  client := rpc.New(endpoint)

  blockHash := solana.MustHashFromBase58("J7rBdM6AecPDEZp8aPq5iPSNKVkU5Q76F3oAV4eW5wsW")
  out, err := client.IsBlockhashValid(
    context.TODO(),
    blockHash,
    rpc.CommitmentFinalized,
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
  spew.Dump(out.Value) // true or false

  fmt.Println("is blockhash valid:", out.Value)
}

index > RPC > MinimumLedgerSlot

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  out, err := client.MinimumLedgerSlot(
    context.TODO(),
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > RequestAirdrop

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
)

func main() {
  endpoint := rpc.TestNet_RPC
  client := rpc.New(endpoint)

  amount := solana.LAMPORTS_PER_SOL // 1 sol
  pubKey := solana.MustPublicKeyFromBase58("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
  out, err := client.RequestAirdrop(
    context.TODO(),
    pubKey,
    amount,
    "",
  )
  if err != nil {
    panic(err)
  }
  spew.Dump(out)
}

index > RPC > SendTransaction

package main

func main() {

}

index > RPC > SimulateTransaction

package main

func main() {

}

Websocket Subscriptions

index > WS Subscriptions > AccountSubscribe

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
  "github.com/gagliardetto/solana-go/rpc/ws"
)

func main() {
  client, err := ws.Connect(context.Background(), rpc.MainNetBeta_WS)
  if err != nil {
    panic(err)
  }
  program := solana.MustPublicKeyFromBase58("9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin") // serum

  {
    sub, err := client.AccountSubscribe(
      program,
      "",
    )
    if err != nil {
      panic(err)
    }
    defer sub.Unsubscribe()

    for {
      got, err := sub.Recv()
      if err != nil {
        panic(err)
      }
      spew.Dump(got)
    }
  }
  if false {
    sub, err := client.AccountSubscribeWithOpts(
      program,
      "",
      // You can specify the data encoding of the returned accounts:
      solana.EncodingBase64,
    )
    if err != nil {
      panic(err)
    }
    defer sub.Unsubscribe()

    for {
      got, err := sub.Recv()
      if err != nil {
        panic(err)
      }
      spew.Dump(got)
    }
  }
}

index > WS Subscriptions > LogsSubscribe

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
  "github.com/gagliardetto/solana-go/rpc/ws"
)

func main() {
  client, err := ws.Connect(context.Background(), rpc.MainNetBeta_WS)
  if err != nil {
    panic(err)
  }
  program := solana.MustPublicKeyFromBase58("9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin") // serum

  {
    // Subscribe to log events that mention the provided pubkey:
    sub, err := client.LogsSubscribeMentions(
      program,
      rpc.CommitmentRecent,
    )
    if err != nil {
      panic(err)
    }
    defer sub.Unsubscribe()

    for {
      got, err := sub.Recv()
      if err != nil {
        panic(err)
      }
      spew.Dump(got)
    }
  }
  if false {
    // Subscribe to all log events:
    sub, err := client.LogsSubscribe(
      ws.LogsSubscribeFilterAll,
      rpc.CommitmentRecent,
    )
    if err != nil {
      panic(err)
    }
    defer sub.Unsubscribe()

    for {
      got, err := sub.Recv()
      if err != nil {
        panic(err)
      }
      spew.Dump(got)
    }
  }
}

index > WS Subscriptions > ProgramSubscribe

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
  "github.com/gagliardetto/solana-go/rpc/ws"
)

func main() {
  client, err := ws.Connect(context.Background(), rpc.MainNetBeta_WS)
  if err != nil {
    panic(err)
  }
  program := solana.MustPublicKeyFromBase58("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") // token

  sub, err := client.ProgramSubscribeWithOpts(
    program,
    rpc.CommitmentRecent,
    solana.EncodingBase64Zstd,
    nil,
  )
  if err != nil {
    panic(err)
  }
  defer sub.Unsubscribe()

  for {
    got, err := sub.Recv()
    if err != nil {
      panic(err)
    }
    spew.Dump(got)

    decodedBinary := got.Value.Account.Data.GetBinary()
    if decodedBinary != nil {
      // spew.Dump(decodedBinary)
    }

    // or if you requested solana.EncodingJSONParsed and it is supported:
    rawJSON := got.Value.Account.Data.GetRawJSON()
    if rawJSON != nil {
      // spew.Dump(rawJSON)
    }
  }
}

index > WS Subscriptions > RootSubscribe

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
  "github.com/gagliardetto/solana-go/rpc/ws"
)

func main() {
  client, err := ws.Connect(context.Background(), rpc.TestNet_WS)
  if err != nil {
    panic(err)
  }

  sub, err := client.RootSubscribe()
  if err != nil {
    panic(err)
  }

  for {
    got, err := sub.Recv()
    if err != nil {
      panic(err)
    }
    spew.Dump(got)
  }
}

index > WS Subscriptions > SignatureSubscribe

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go"
  "github.com/gagliardetto/solana-go/rpc"
  "github.com/gagliardetto/solana-go/rpc/ws"
)

func main() {
  client, err := ws.Connect(context.Background(), rpc.TestNet_WS)
  if err != nil {
    panic(err)
  }

  txSig := solana.MustSignatureFromBase58("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")

  sub, err := client.SignatureSubscribe(
    txSig,
    "",
  )
  if err != nil {
    panic(err)
  }
  defer sub.Unsubscribe()

  for {
    got, err := sub.Recv()
    if err != nil {
      panic(err)
    }
    spew.Dump(got)
  }
}

index > WS Subscriptions > SlotSubscribe

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
  "github.com/gagliardetto/solana-go/rpc/ws"
)

func main() {
  client, err := ws.Connect(context.Background(), rpc.TestNet_WS)
  if err != nil {
    panic(err)
  }

  sub, err := client.SlotSubscribe()
  if err != nil {
    panic(err)
  }
  defer sub.Unsubscribe()

  for {
    got, err := sub.Recv()
    if err != nil {
      panic(err)
    }
    spew.Dump(got)
  }
}

index > WS Subscriptions > VoteSubscribe

package main

import (
  "context"

  "github.com/davecgh/go-spew/spew"
  "github.com/gagliardetto/solana-go/rpc"
  "github.com/gagliardetto/solana-go/rpc/ws"
)

func main() {
  client, err := ws.Connect(context.Background(), rpc.MainNetBeta_WS)
  if err != nil {
    panic(err)
  }

  // NOTE: this subscription must be enabled by the node you're connecting to.
  // This subscription is disabled by default.
  sub, err := client.VoteSubscribe()
  if err != nil {
    panic(err)
  }
  defer sub.Unsubscribe()

  for {
    got, err := sub.Recv()
    if err != nil {
      panic(err)
    }
    spew.Dump(got)
  }
}

Contributing

We encourage everyone to contribute, submit issues, PRs, discuss. Every kind of help is welcome.

License

Apache 2.0

Credits

  • Gopher logo was originally created by Takuya Ueda (https://twitter.com/tenntenn). Licensed under the Creative Commons 3.0 Attributions license.

solana-go's People

Contributors

0ximalice avatar aalu1418 avatar abourget avatar billettc avatar d-quentin avatar datluongductuan avatar dimacantemir avatar fproulx-dfuse avatar gagliardetto avatar gcrispino avatar goudanwoo avatar hexdigest avatar jubeless avatar kelonye avatar lazar955 avatar lebdron avatar leoluk avatar mario-zh avatar martelev avatar mwei0210 avatar pikomonde avatar pires avatar poytr1 avatar rafaelvanoni avatar rengen12 avatar ricebin avatar riptl avatar sdrug avatar yakud avatar yuhanfang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

solana-go's Issues

How to use system.NewCreateAccountWithSeedInstruction properly?

I am trying to replicate this solana example hello world program in .ts using go. But I am stuck on using system.NewCreateAccountWithSeedInstruction. I got this error Transaction simulation failed: Error processing Instruction 0: invalid instruction data when executing confirm.SendAndConfirmTransaction using system.NewCreateAccountWithSeedInstruction instruction:


2021/12/24 11:57:11 (*jsonrpc.RPCError)(0xc0001f5890)({
 Code: (int) -32002,
 Message: (string) (len=87) "Transaction simulation failed: Error processing Instruction 0: invalid instruction data",
 Data: (map[string]interface {}) (len=3) {
  (string) (len=8) "accounts": (interface {}) <nil>,
  (string) (len=3) "err": (map[string]interface {}) (len=1) {
   (string) (len=16) "InstructionError": ([]interface {}) (len=2 cap=2) {
    (json.Number) (len=1) "0",
    (string) (len=22) "InvalidInstructionData"
   }
  },
  (string) (len=4) "logs": ([]interface {}) (len=2 cap=2) {
   (string) (len=51) "Program 11111111111111111111111111111111 invoke [1]",
   (string) (len=73) "Program 11111111111111111111111111111111 failed: invalid instruction data"
  }
 }
})

And here is my code in go:

func main() {
	// var
	ctx := context.Background()
	rpcCli := rpc.New(rpc.LocalNet_RPC)
	wsCli, _ := ws.Connect(ctx, rpc.LocalNet_WS)
	payerPrivateKey, _ := solana.PrivateKeyFromBase58("5LRLfrUP22VtiNaPGAEgHPucoJmG8ejmomMVmpn4fkXjexYsT7RQGfGuMePG5PKvecZxMGrqa6EP2RmYcm7TYQvX") // don't worry, I only use this private key in my local computer
	payerAccount, _ := solana.WalletFromPrivateKeyBase58(payerPrivateKey.String())
	programID := "4sCcZNQR8vfWckyi5L9KdptdaiLxdiMjVgKQay7HxzmK"
	programPubKey, _ := solana.PublicKeyFromBase58(programID)

	// create new subaccount (seed account)
	newSubAccount, err := solana.CreateWithSeed(
		payerAccount.PublicKey(),
		"hello",
		programPubKey,
	)
	if err != nil {
		log.Fatalln("Failed to CreateWithSeed")
	}

	instruction, err := system.NewCreateAccountWithSeedInstruction(
		payerAccount.PublicKey(),
		"hello",
		918720,
		4,
		programPubKey,
		payerAccount.PublicKey(),
		newSubAccount,
		payerAccount.PublicKey(),
	).ValidateAndBuild()
	if err != nil {
		log.Fatalln("Failed building NewCreateAccountInstruction instruction", err)
	}

	instructionData, _ := instruction.Data()
	fmt.Printf("------> instructionData length: %d bytes, data: %v\n", len(instructionData), instructionData)

	instructions := []solana.Instruction{instruction}
	signers := []solana.PrivateKey{payerAccount.PrivateKey}
	opts := []solana.TransactionOption{solana.TransactionPayer(payerAccount.PublicKey())}

	// create recent blockhash
	recent, err := rpcCli.GetRecentBlockhash(ctx, rpc.CommitmentFinalized)
	if err != nil {
		log.Fatalln(err)
	}

	// create transaction
	tx, err := solana.NewTransaction(
		instructions,
		recent.Value.Blockhash,
		opts...,
	)
	if err != nil {
		log.Fatalln(err)
	}

	// sign transaction
	_, err = tx.Sign(
		func(key solana.PublicKey) *solana.PrivateKey {
			for _, signer := range signers {
				if signer.PublicKey().Equals(key) {
					return &signer
				}
			}

			return nil
		},
	)
	if err != nil {
		log.Fatalln(err)
	}
	tx.EncodeTree(text.NewTreeEncoder(os.Stdout, "Transfer SOL"))

	// send and confirm transaction
	_, err = confirm.SendAndConfirmTransaction(
		ctx,
		rpcCli,
		wsCli,
		tx,
	)
	if err != nil {
		log.Fatalln(err)
	}
}

I tried to print the instruction.Data() in go and got this

------> instructionData length: 90 bytes, data: [3 0 0 0 204 95 77 127 148 25 135 127 89 146 22 90 233 80 113 3 70 176 165 222 81 200 100 223 117 165 155 44 53 225 124 20 5 104 101 108 108 111 192 4 14 0 0 0 0 0 4 0 0 0 0 0 0 0 57 111 59 111 183 248 249 251 128 174 206 0 81 22 3 173 244 104 15 249 239 112 33 255 66 169 29 66 7 106 231 230]

And here is the instruction data on the .ts from the solana helloworld example for comparison
console.log(instruction.data.buffer)

ArrayBuffer {
  [Uint8Contents]: <03 00 00 00 cc 5f 4d 7f 94 19 87 7f 59 92 16 5a e9 50 71 03 46 b0 a5 de 51 c8 64 df 75 a5 9b 2c 35 e1 7c 14 05 00 00 00 00 00 00 00 68 65 6c 6c 6f c0 04 0e 00 00 00 00 00 04 00 00 00 00 00 00 00 39 6f 3b 6f b7 f8 f9 fb 80 ae ce 00 51 16 03 ad f4 68 0f f9 ef 70 21 ff 42 a9 1d 42 07 6a e7 e6>,
  byteLength: 97
}

And here is the conversion from hex to 0-255

3 0 0 0 204 95 77 127 148 25 135 127 89 146 22 90 233 80 113 3 70 176 165 222 81 200 100 223 117 165 155 44 53 225 124 20 5 **0 0 0 0 0 0 0** 104 101 108 108 111 192 4 14 0 0 0 0 0 4 0 0 0 0 0 0 0 57 111 59 111 183 248 249 251 128 174 206 0 81 22 3 173 244 104 15 249 239 112 33 255 66 169 29 66 7 106 231 230

I see that there are 7 bytes difference (the one that I bold) in 0 0 0 0 0 0 0. What do I do wrong? Am I missing something? Is there any example on how to use this instruction? Thanks!

Can RPC clients be reused?

Can I create it only once and reuse it?

client := rpc.New("https://api.devnet.solana.com")
resp, err := client.GetAccountInfoWithOpts(.....)

resp2, err := client.SendTransaction(.....)

how to parse transactions

I'm currently working on a sol back-end wallet project. I'm familiar with eth series. I know that a TX contains from, to and amount.
However, I found that there is no explicit amount field in Sol's API. Instead, it is divided into postBalances and preBalances.

so,do I need to build postbalances, prebalances and accountkeys into a data struct and calculate the amount? I count found how to parse instructions.data.
Can you give me some advice?

Error when exporting to WASM

When I run this cli command to generate wasm binary:
GOOS=js GOARCH=wasm go build -o output/html/aneka_guess_number/script/app.wasm cmd/html/aneka_guess_number/app.go

I got this error:

vendor/github.com/fatih/color/color.go:21:5: undefined: isatty.IsTerminal

I tried to resolve this by bump up the version of github.com/fatih/color, from v1.7.0 to v1.9.0. After bumping up the version, I can compile to WASM. I create the related PR to bump up the version. #34


It's my first time creating PR to open source project, please correct me if there is mistake. Thanks!

Nonce account usage

Hey there,

How would one go about:

  1. Creating a nonce account
  2. Getting the nonce value
  3. Creating a tx with that nonce value instead of the recent block hash (I guess pass it instead of the block hash right?)

Thanks,

How to use filters with rpc.GetProgramAccountsOpts

Ask - Do you have an example of using GetProgramAccountsWithOpts that includes the dataslice and memcmp filters?

I am trying to use DataSlice and Filters with GetProgramAccountsWithOpts and I'm sure I'm making some rookie mistake here with the format but I can't figure out the proper format to include the memcmp filter. Thank you.

out, err := client.GetProgramAccountsWithOpts(
		context.TODO(),
		solana.MustPublicKeyFromBase58("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"),
		&rpc.GetProgramAccountsOpts{
			Encoding:   solana.EncodingBase64Zstd,
			Commitment: rpc.CommitmentFinalized,
			DataSlice: &rpc.DataSlice{
				Offset: pointer.ToUint64(0),
				Length: pointer.ToUint64(1024),
			},
			//TODO: what is the correct format for filters
			Filters: ,
		},
	)

Issues running with go 1.18

Here is the stack:

runtime.throw({0x175c318?, 0xc02ad833c0?})
/usr/lib/go-1.18/src/runtime/panic.go:992 +0x71 fp=0xc02ad83380 sp=0xc02ad83350 pc=0x449931
runtime.sigpanic()
/usr/lib/go-1.18/src/runtime/signal_unix.go:825 +0x305 fp=0xc02ad833d0 sp=0xc02ad83380 pc=0x45fbe5
aeshashbody()
/usr/lib/go-1.18/src/runtime/asm_amd64.s:1343 +0x39f fp=0xc02ad833d8 sp=0xc02ad833d0 pc=0x479cbf
runtime.mapiternext(0xc02f1e8e80)
/usr/lib/go-1.18/src/runtime/map.go:934 +0x2cb fp=0xc02ad83448 sp=0xc02ad833d8 pc=0x4233cb
runtime.mapiterinit(0xc02ad834e0?, 0x420be5?, 0xc02f1c9ea8?)
/usr/lib/go-1.18/src/runtime/map.go:861 +0x228 fp=0xc02ad83468 sp=0xc02ad83448 pc=0x4230a8
reflect.mapiterinit(0x4229bd?, 0x1536ba0?, 0xc02f1af3a8?)
/usr/lib/go-1.18/src/runtime/map.go:1373 +0x19 fp=0xc02ad83490 sp=0xc02ad83468 pc=0x476319
github.com/modern-go/reflect2.(*UnsafeMapType).UnsafeIterate(...)
/home/user/go/pkg/mod/github.com/modern-go/[email protected]/unsafe_map.go:112
github.com/json-iterator/go.(*sortKeysMapEncoder).Encode(0xc02f319020, 0xc02e443198, 0xc02f305140)
/home/user/go/pkg/mod/github.com/json-iterator/[email protected]/reflect_map.go:291 +0x225 fp=0xc02ad83600 sp=0xc02ad83490 pc=0x726cc5
github.com/json-iterator/go.(*onePtrEncoder).Encode(0xc02f301360, 0xc02f318810, 0xc02f1e8e80?)
/home/user/go/pkg/mod/github.com/json-iterator/[email protected]/reflect.go:219 +0x82 fp=0xc02ad83638 sp=0xc02ad83600 pc=0x71efc2
github.com/json-iterator/go.(*Stream).WriteVal(0xc02f305140, {0x158e020, 0xc02f318810})
/home/user/go/pkg/mod/github.com/json-iterator/[email protected]/reflect.go:98 +0x158 fp=0xc02ad836a8 sp=0xc02ad83638 pc=0x71e2d8

CancelOrder program

Hi folks, I'm trying to write a client that issues CancelOrder transactions and it seems that program hasn't been implemented yet. Is that correct? If so, I'd be happy to propose a PR with it.

To clarify, the problem I'm trying to solve is that I can't create a solana.NewTransaction() with a InstructionCancelOrder{} because the latter doesn't fully implement solana.Instruction. It seems that "fully" implementing CancelOrder similarly to what's done in programs/system/CreateAccount.go for example, would solve that.

dfuse-io logging module update to new URL

Since the module github.com/dfuse-io/logging now redirects to github.com/streamingfast/logging , when I do go get -u this error comes up:

go get: github.com/dfuse-io/[email protected] updating to
        github.com/dfuse-io/[email protected]: parsing go.mod:
        module declares its path as: github.com/streamingfast/logging
                but was required as: github.com/dfuse-io/logging

Any reason why this hasn't been fixed? Is the old logging module different from the new one at streamingfast?

Simulate transaction doesn't work

Hello, I have just found an issue with transaction simulation, I tried it with a different RPC, but the result is the same, can you help me, please?
image

Serum market

Is it possible to interact with Serum's market using this sdk?
How do i get market params like Request queue, Event queue etc?

SendRawTx

I have *Transaction how to convert it to base64TX

How to transfer usdt?

I tried many times to transfer usdt to other address, but failed.
Transferring sol was successful.
critical code

fromTokenAccount, _, _ := solana.FindAssociatedTokenAddress(s.PoolManager.PublicKey(), s.UsdtPublicKey)
g.Dump("from ", fromTokenAccount.String())
toTokenAccount, _, _ := solana.FindAssociatedTokenAddress(solana.MustPublicKeyFromBase58(toAddress), s.UsdtPublicKey)
g.Dump("to ", toTokenAccount.String())

instruction0 := system.NewTransferInstruction(
	uint64(amount*s.UsdtDecimal),
	fromTokenAccount,
	toTokenAccount,
).Build()
tx, err := solana.NewTransaction([]solana.Instruction{instruction0}, recent.Value.Blockhash, solana.TransactionPayer(s.PoolManager.PublicKey()))
if err != nil {
	return
}

_, err = tx.Sign(
	func(key solana.PublicKey) *solana.PrivateKey {
		if s.PoolManager.PublicKey().Equals(key) {
			return &s.PoolManager
		}
		return nil
	},
)
if err != nil {
	return
}
// Pretty print the transaction:
tx.EncodeTree(text.NewTreeEncoder(os.Stdout, "Transfer USDT"))

sig, err = client.SendTransaction(ctx, tx)
if err != nil {
	return
}

result
error = signer key "5m1GGanP4pqbdYECvAA6YAuhmvpbKnuzmnuu6wQ3Y3vo" not found. Ensure all the signer keys are in the vault

NPE in getAccountInfo() if result is nil

If a non-compliant RPC server returns result: null for getAccountInfo(), the client will panic with null pointer deref (line 127 on out.Value because out is nil).

err = cl.rpcClient.CallForInto(ctx, &out, "getAccountInfo", params)
if err != nil {
return nil, err
}
if out.Value == nil {

Ideally the RPC client would never panic under any circumstances

How can I use spl token?

I am trying to generate code to deploy FT and mint token like I did in cli following this site(https://spl.solana.com/token)

I could easily airdrop SOL and transfer SOL to another address following README.md. But there is no spl token example.
I generated code like below. I think some of parameters are wrong. Could anyone check what I did wrongly?

func TestFT(t *testing.T) {
	rpcClient := rpc.New(rpc.DevNet_RPC)
	wsClient, err := ws.Connect(context.Background(), rpc.DevNet_WS)
	assert.NoError(t, err)

	ctx := context.TODO()

	to := solana.MustPublicKeyFromBase58("9B5XszUGdMaxCZ7uSQhPzdks5ZQSmWxrmzCSvtJ6Ns6b")
	fmt.Println(to)
	from := solana.NewWallet()
	fmt.Println(from.PublicKey())

	// Airdrop 5 SOL to the new account:
	out, err := rpcClient.RequestAirdrop(
		ctx,
		from.PublicKey(),
		solana.LAMPORTS_PER_SOL*2,
		rpc.CommitmentFinalized,
	)
	fmt.Println(out)
	assert.NoError(t, err)

	time.Sleep(30 * time.Second)

	recent, err := rpcClient.GetRecentBlockhash(ctx, rpc.CommitmentFinalized)
	assert.NoError(t, err)

	FTAccount := solana.NewWallet()
	createInst, err := system.NewCreateAccountInstruction(0, 100, solana.TokenProgramID, from.PublicKey(), FTAccount.PublicKey()).ValidateAndBuild()
	assert.NoError(t, err)

	mintInst, err := token.NewInitializeMintInstructionBuilder().
		SetDecimals(9).
		SetMintAuthority(from.PublicKey()).
		SetMintAccount(FTAccount.PublicKey()).
		SetSysVarRentPubkeyAccount(solana.SysVarRentPubkey).ValidateAndBuild()
	assert.NoError(t, err)

	tx, err := solana.NewTransaction(
		[]solana.Instruction{
			createInst,
			mintInst,
		},
		recent.Value.Blockhash,
		solana.TransactionPayer(from.PublicKey()),
	)
	assert.NoError(t, err)

	_, err = tx.Sign(
		func(key solana.PublicKey) *solana.PrivateKey {
			if from.PublicKey().Equals(key) {
				return &from.PrivateKey
			}
			if FTAccount.PublicKey().Equals(key) {
				return &FTAccount.PrivateKey
			}
			return nil
		},
	)
	assert.NoError(t, err)

	sig, err := confirm.SendAndConfirmTransaction(
		ctx,
		rpcClient,
		wsClient,
		tx,
	)
	fmt.Println(sig)
	assert.NoError(t, err)
}

I got this errors. I think mintInst has wrong argument. But I do not know why it is wrong

 Error Trace:	solana_test.go:139
 Error:      	Received unexpected error:
        	     (*jsonrpc.RPCError)(0xc0008240f0)({
        	      Code: (int) -32002,
        	      Message: (string) (len=99) "Transaction simulation failed: Error processing Instruction 1: invalid account data for instruction",
        	      Data: (map[string]interface {}) (len=3) {
        	       (string) (len=8) "accounts": (interface {}) <nil>,
        	       (string) (len=3) "err": (map[string]interface {}) (len=1) {
        	        (string) (len=16) "InstructionError": ([]interface {}) (len=2 cap=2) {
        	         (json.Number) (len=1) "1",
        	         (string) (len=18) "InvalidAccountData"
        	        }
        	       },
        	       (string) (len=4) "logs": ([]interface {}) (len=7 cap=8) {
        	        (string) (len=51) "Program 11111111111111111111111111111111 invoke [1]",
        	        (string) (len=48) "Program 11111111111111111111111111111111 success",
        	        (string) (len=62) "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]",
        	        (string) (len=40) "Program log: Instruction: InitializeMint",
        	        (string) (len=38) "Program log: Error: InvalidAccountData",
        	        (string) (len=89) "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1705 of 200000 compute units",
        	        (string) (len=96) "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA failed: invalid account data for instruction"
        	       }
        	      }
        	     })

Default encoding for GetAccountInfoWithOpts

I tried to use GetAccountInfoWithOpts, I only need to change the Commitment option like this:

accountInfo, err := cli.rpcClient.GetAccountInfoWithOpts(
	context.Background(),
	accountPubKey,
	&rpc.GetAccountInfoOpts{
		Commitment: rpc.CommitmentConfirmed,
	},
)

but getting this error:

rpc.GetAccountInfoResult.Value: rpc.Account.Executable: Data: unmarshalerDecoder: Unknown kind: [34 74 110 114 80 57 34], error found in #10 byte of ...|a":"JnrP9","executab|..., bigger context ...|{"context":{"slot":395502},"value":{"data":"JnrP9","executable":false,"lamports":918720,"owner":"7te|...

I think the error is because I did not set the Encoding option. If I code like this, it works.

accountInfo, err := cli.rpcClient.GetAccountInfoWithOpts(
	context.Background(),
	accountPubKey,
	&rpc.GetAccountInfoOpts{
		Encoding: solana.EncodingBase64,
		Commitment: rpc.CommitmentConfirmed,
	},
)

I think, it's good to add something like default Encoding if the Encoding option is empty string. Something like this on GetAccountInfoWithOpts:

if opts.Encoding == "" {
	obj["encoding"] = solana.EncodingBase64
}

What do you think?

GetBlockWithOpts using `solana.EncodingJSONParsed` not working

I am attempting to pull blocks with the JSON Parsed option and repeatedly receive the following error:

2021/11/18 16:06:17 rpc.GetBlockResult.Transactions: []rpc.TransactionWithMeta: rpc.TransactionWithMeta.Transaction: solana.Transaction.Message: solana.Message.AccountKeys: []solana.PublicKey: unmarshalerDecoder: ReadString: expects " or n, but found {, error found in #1 byte of ...|{"pubkey":"|..., bigger context ...|{"pubkey":"2oz91K9pKf2sYr4oRtQvxBcxxo8gniZvXyNoMTQY|..., error found in #10 byte of ...|ble":true},{"pubkey"|..., bigger context ...|8gniZvXyNoMTQYhoqv","signer":true,"writable":true},{"pubkey":"7ycfa1ENNT5dVVoMtiMjsgVbkWKFJbu6nF2h1U|...
exit status 1

Version: github.com/gagliardetto/solana-go v1.0.2
Endpoint: rpc.MainNetBeta_RPC

Here is my code:

package main

import (
	"context"
	"log"

	"github.com/davecgh/go-spew/spew"
	"github.com/gagliardetto/solana-go"
	"github.com/gagliardetto/solana-go/rpc"
)

func main() {
	client := rpc.New(rpc.MainNetBeta_RPC)

	example, err := client.GetRecentBlockhash(context.TODO(), rpc.CommitmentFinalized)
	if err != nil {
		panic(err)
	}

	includeRewards := true
	out, err := client.GetBlockWithOpts(
		context.TODO(),
		uint64(example.Context.Slot),
		// You can specify more options here:
		&rpc.GetBlockOpts{
			Encoding:   solana.EncodingJSONParsed,
			Commitment: rpc.CommitmentFinalized,
			// Get only signatures:
			TransactionDetails: rpc.TransactionDetailsFull,
			// Exclude rewards:
			Rewards: &includeRewards,
		},
	)
	if err != nil {
		log.Fatal(err)
	}
	spew.Dump(out)
}

Any ideas on how to resolve this issue?

CreateProgramAddress working tests cases with Golang and TypeScript

Hey,

I am trying to mirror the behaviour of a typescript lib for Solana. I need to use CreateProgramAddress to derive a Serum Market address. To have a working example I looked through the tests cases:

I see that the resulting addresses are different and I don't really understand why. I might be missing something.
Any idea where the diff comes from? Do you by any chance have a example that work on both lib?
I don't know Rust so I also don't know if there are tests cases on the original lib.

rpc.Client struct needs to implement a close method for its own socket

gm,

may be this is an edge case - whenever you instance many rpc.New calls, macOS would throw tcp lookup not found errors even after ulimit -n 69420710 or ulimit > unlimited. so in my programs, i have to instance a global rpc.Client via rpc.New and then pass down to functions that require rpc interactions. this implies that many instances of rpc.New will exceed the OS max open sockets and fail due to not being closed after usage.

so i would like to know where to start on making the pr that implements this if you dont have time to. or i would be eternally grateful if this gets implemented in a future release.

much love <3,
D

How do I transfer tokens

Is there a way that I can use this library to send tokens from one wallet to another?

If so please tell me where.

Consuming buffer from magic eden

https://api.magiceden.dev/#auth-info-82874536-9430-4dae-81dc-1235baaa3ef3

in /instructions/buy it returns data that's array of integer. In their docs it will be converted into buffer and consumed by message decoder.

When I try to do that in golang it doesn't work and failed to decode the data

Golang code:

        data := responseTx.Tx.Data
	buf := make([]byte, len(data))
	for i, d := data {
		buf[i] = byte(d)
	}

	tx, err := solana.TransactionFromDecoder(bin.NewBinDecoder(buf))

Input:

data = [1,0,9,20,225,137,187,132,187,32,147,173,43,163,223,65,131,162,193,42,192,159,17,212,162,207,219,137,175,244,246,208,43,32,154,238,143,142,48,46,229,90,171,138,102,8,144,82,192,134,88,49,12,189,138,222,113,61,218,218,181,24,242,189,61,99,136,65,196,242,164,172,136,81,180,154,105,86,217,232,114,177,80,218,126,68,36,219,232,7,97,66,21,150,26,150,175,68,196,177,102,193,1,248,66,21,84,90,171,143,66,175,82,152,249,58,137,57,190,200,137,220,64,181,8,198,51,6,96,38,138,225,255,21,35,174,141,211,83,149,162,153,19,218,231,60,186,70,34,169,74,45,147,70,248,106,120,29,192,83,198,44,4,174,6,65,215,207,111,121,182,215,225,243,94,74,34,197,254,6,58,219,44,150,187,27,196,166,160,240,71,217,227,180,139,14,12,158,58,228,224,183,152,74,250,18,157,96,7,160,158,224,142,150,46,161,202,218,73,218,230,18,50,147,194,191,195,125,8,175,246,228,16,89,36,102,175,155,72,107,229,118,121,242,246,139,65,205,220,49,224,32,146,119,74,143,99,98,237,19,100,86,96,93,8,145,61,224,5,62,188,181,150,48,71,56,229,110,39,39,82,37,99,189,75,58,132,117,251,109,190,41,110,63,77,30,236,241,173,15,85,172,25,39,211,100,236,45,65,196,249,149,133,127,65,57,58,215,199,190,66,39,49,131,147,224,252,92,124,240,210,8,192,184,182,228,87,89,35,144,23,73,35,197,120,36,50,169,143,71,179,207,36,212,146,159,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,195,27,24,204,62,20,138,10,82,147,129,137,32,237,250,237,171,57,30,73,51,108,11,116,219,102,157,16,71,3,66,75,145,66,174,215,146,153,82,142,79,92,42,195,58,12,218,147,137,182,146,105,58,9,209,230,235,134,206,164,17,28,156,212,246,133,86,151,50,106,40,222,250,246,5,67,6,18,251,213,239,142,84,131,191,154,252,251,23,226,204,42,247,89,214,15,6,221,246,225,215,101,161,147,217,203,225,70,206,235,121,172,28,180,133,237,95,91,55,145,58,140,245,133,126,255,0,169,6,167,213,23,25,44,92,81,33,140,201,76,61,74,241,127,88,218,238,8,155,161,253,68,227,219,217,138,0,0,0,0,140,151,37,143,78,36,137,241,187,61,16,41,20,142,13,131,11,90,19,153,218,255,16,132,4,142,123,216,219,233,248,89,0,11,227,225,235,161,122,71,63,137,176,247,232,226,73,64,242,10,235,142,188,167,26,136,253,233,93,75,131,183,26,9,5,33,159,137,154,129,212,255,132,251,89,61,46,223,138,144,172,27,58,179,66,88,247,223,35,62,165,3,2,177,189,46,223,64,67,143,181,25,82,110,138,69,12,221,5,93,218,23,254,247,227,114,53,49,75,129,202,98,7,63,109,177,26,78,3,19,6,0,11,1,7,12,11,17,242,35,198,137,82,225,242,182,254,128,40,4,156,77,0,0,0,19,12,0,11,13,14,1,7,12,2,7,15,11,16,34,102,6,61,18,1,218,235,234,255,254,128,40,4,156,77,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,22,0,3,11,4,13,14,1,5,7,12,6,2,7,8,7,15,11,17,18,16,9,10,42,37,74,217,157,79,49,35,6,254,250,128,40,4,156,77,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255]

Error Exception:

panic: required [1] byte, remaining [0]

goroutine 1 [running]:
main.buy_listing({{0x1411560, 0xc000078700}, 0x0, {0x0, 0x0}, 0x0}, {0x139be6b?, 0x100e387?}, {0x0, 0x0}, ...)

compilation error on v0.4.2

# github.com/gagliardetto/solana-go
../../go/pkg/mod/github.com/gagliardetto/[email protected]/transaction.go:260:2: undefined: bin.EncodeCompactU16Length
../../go/pkg/mod/github.com/gagliardetto/[email protected]/transaction.go:276:16: encoder.WriteBytes undefined (type *bin.Encoder has no field or method WriteBytes)
../../go/pkg/mod/github.com/gagliardetto/[email protected]/transaction.go:281:25: undefined: bin.DecodeCompactU16LengthFromByteReader
../../go/pkg/mod/github.com/gagliardetto/[email protected]/transaction.go:287:28: decoder.ReadNBytes undefined (type *bin.Decoder has no field or method ReadNBytes)
../../go/pkg/mod/github.com/gagliardetto/[email protected]/types.go:36:7: undefined: bin.EncoderDecoder
../../go/pkg/mod/github.com/gagliardetto/[email protected]/types.go:64:7: undefined: bin.EncoderDecoder
../../go/pkg/mod/github.com/gagliardetto/[email protected]/types.go:93:2: undefined: bin.EncodeCompactU16Length
../../go/pkg/mod/github.com/gagliardetto/[email protected]/types.go:100:2: undefined: bin.EncodeCompactU16Length
../../go/pkg/mod/github.com/gagliardetto/[email protected]/types.go:103:3: undefined: bin.EncodeCompactU16Length
../../go/pkg/mod/github.com/gagliardetto/[email protected]/types.go:108:3: undefined: bin.EncodeCompactU16Length
../../go/pkg/mod/github.com/gagliardetto/[email protected]/types.go:108:3: too many errors

rpc.New leaks fds

rpc.New create a new http client and keepalive sessions, but there's no Close() method to clean them up.

Problem with getting token

➜  slnc git:(main) ~/sdk/go1.16.5/bin/go run main.go serum get market HWHvQhFmJB3NUcu1aihKmrKegfVxBEHzwVX6yZCKEsi1
Error: fetch market: getting quote mint: required [1] byte, remaining [0]
Usage:
  cmd serum get market {market_addr} [flags]

Flags:
  -h, --help   help for market

Global Flags:
  -H, --http-header strings      HTTP header to add to JSON-RPC requests
      --kms-gcp-keypath string   Path to the cryptoKeys within a keyRing on GCP
  -u, --rpc-url string           API endpoint of eos.io blockchain node (default "http://api.mainnet-beta.solana.com")
      --vault-file string        Wallet file that contains encrypted key material (default "./solana-vault.json")

fetch market: getting quote mint: required [1] byte, remaining [0]
exit status 1

HWHvQhFmJB3NUcu1aihKmrKegfVxBEHzwVX6yZCKEsi1 - its SOL/USDT

It seems that someting wrong with decoding USDT token info to token.Mint GetAccountInfo(Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB) //USDT

But its ok with some other tokens. With Cm4MmknScg7qbKqytb1mM92xgDxv3TNXos4tKbBqTDy7 RAY/SRM market it works fine.

am i doing something wrong?

does not contain package github.com/gagliardetto/solana-go/text/format

Hi, i'm running into this issue:

$ go mod tidy                                       
go: finding module for package github.com/gagliardetto/solana-go/text/format
github.com/johnbailon/soltest imports
        github.com/gagliardetto/metaplex-go/clients/token-metadata imports
        github.com/gagliardetto/solana-go/text/format: module github.com/gagliardetto/solana-go@latest found (v1.0.0), but does not contain package github.com/gagliardetto/solana-go/text/format 
$ go run main.go 
../../../../pkg/mod/github.com/gagliardetto/[email protected]/clients/token-metadata/ConvertMasterEditionV1ToV2.go:9:2: no required module provides package github.com/gagliardetto/solana-go/text/format; to add it:
        go get github.com/gagliardetto/solana-go/text/format
$ go get github.com/gagliardetto/solana-go/text/format
go get: module github.com/gagliardetto/solana-go@upgrade found (v1.0.0), but does not contain package github.com/gagliardetto/solana-go/text/format

InnerInstruction should support parsed structure.

Rn, it only supports compiled InnerInstruction.

{
  "parsed": {
    "info": {
      "amount": "1232000000",
      "authority": "XLVYxeZh7mFePq74jzU2Lsd51AeJ5txYbvWDAYutVNT",
      "destination": "75HgnSvXbWKZBpZHveX68ZzAhDqMzNDS29X6BGLtxMo1",
      "source": "AGcGa5sVMRT3PWVtLPTh13MAaQsNMdC3PTPiaAGzdG4v"
    },
    "type": "transfer"
  },
  "program": "spl-token",
  "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
}

Parsing account information with unknown data struct

Hello,
sorry for the disturbance. I am currently trying to make account info readable or usable. The problem is that I can't parse the data into a struct like in CMv2, because I don't know the data structure. Do you have an idea how I can solve this problem? An account would be for example: sSQ2Nv69cmb7AD7zMF9ka8mTUSzKXgDRghNLm6Dy3m9 (mainnet)

With kind regards,
Felix

Get Anchor Data with GetAccountInfoWithOpts

I want to fetch this data from https://explorer.solana.com/address/61CCEcc5LZCp9RJ2yPhmABHno3fPLKK6Lbxrpvqdj5Bu/anchor-account?cluster=devnet
image

The only way I have found to make this request:
image

This returns me that output:
["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","base64"]

But after trying to decode this with all possible ways I understood that nothing helps, could you explain me how to solve this problem, please?

getRecentBlockkhash

With the json rpc api stating that getRecentBlockhash is deprecated and will no longer function on newer versions, will the solana.NewTransaction soon switch over to the updated getFeeForMessage?

Add ws connect method with http header parameter

Hello,

A new connect method is needed that accepts a requestHeader http.Header parameter that passes that to the DialContext method.
The existing is missing it.

func Connect(ctx context.Context, rpcEndpoint string) (c *Client, err error) {

Reason: if you plan to pass in a user password for authentication, this is the prescribed way. gorilla WebSocket basic authentication

Thanks for enriching the Solana ecosystem with a Go SDK!

Error when decoding AccountInfo

Hello,

I am getting the following error byte array: varlen=3069866594, missing 3069866581 bytes when trying to read the AccountInfo of an account address. This is the account information in the dev net

Ultimately I am trying to read the account data so I can read the attributes of the NFT.

This is my code

import (
	"context"
	"fmt"
	"github.com/gagliardetto/binary"
	tokenmetadata "github.com/gagliardetto/metaplex-go/clients/token-metadata"
	"github.com/gagliardetto/solana-go"
	"github.com/gagliardetto/solana-go/rpc"
)
	c := rpc.New(rpc.DevNet_RPC)
	a := solana.MustPublicKeyFromBase58("Gv1VNiC7YTXb7FerKoWiB99RTXzs2Qrq6p5JpYnQ63aZ")
	resp, err := c.GetAccountInfo(context.TODO(), a)
	if err != nil {
		panic(err)
	}
	d := bin.NewBorshDecoder(resp.Value.Data.GetBinary())
	var meta tokenmetadata.Metadata
	err = d.Decode(&meta)
	if err != nil {
		panic(err)
	}

Any ideas what I could be doing wrong?

How to use serum place order instruction

hi,i want use the serum package to place a order,but when i create serum.instruction,have a problem。the ide tell me the serum.instruction have not implement solana.instruction(three method ProgramID, Accounts, Data).

i want to know how to use serum.instruction to send transaction?

what is my mistake?

thank you!

How to decode a raw transaction into a transaction object?

Hello,

I don't understand if it's possible to decode a raw transaction string to a solana.Transaction object in the SDK. I'd like to do this to support the feature of getting a raw transaction from a user and only submitting that to the network via the sendTransaction rpc method, which takes a transaction.

Maybe doing some borsh decoder like here could help, but don't really know.
Any tips?

Also, if there's the interest, there could exist a function in the rpc package to submit raw transaction strings directly, without the need to convert to a transaction, or provide a function that easily converts that, maybe in the transaction package (in the case that there doesn't exist one)

Transaction decoding with Meta property

Hey there,

I have asked this in another person's issue but wanted to open an official one.

When calling the TransactionFromDecoder method the returned struct is solana.Transaction which doesn't contain the Meta property which when calling RPC GetTransaction you do get.

Is there a reason for doing so and is it possible to have the Meta property from a decoded transaction?

Thanks

`blockSubscribe` feed doesn't work

Reference: https://docs.solana.com/developing/clients/jsonrpc-api#blocksubscribe---unstable-disabled-by-default

The docs are a bit ambiguous on this, probably be cause the endpoint is still considered unstable. In the endpoint description, it says the first parameter is filter: <string>|<object>, but the example indicates it should be <string>|<object>, like { "jsonrpc": "2.0", "id": "1", "method": "blockSubscribe", "params": ["all"] }. This library implements the first, e.g. "params": [{"filter": "all"}], which doesn't work.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.