[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-10603":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":22,"archived":23,"fork":23,"defaultBranch":24,"hasWiki":23,"hasPages":23,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":31,"readmeContent":32,"aiSummary":33,"trendingCount":16,"starSnapshotCount":16,"syncStatus":34,"lastSyncTime":35,"discoverSource":36},10603,"solana-go","solana-foundation\u002Fsolana-go","solana-foundation","Go SDK library and RPC client for the Solana Blockchain","",null,"Go",1559,434,18,93,0,1,3,14,5,60.82,"Apache License 2.0",false,"main",[26,27,28,29,30],"blockchain","golang","rpc","sdk","solana","2026-06-12 04:00:51","# Solana SDK library for Go\n\n[![GoDoc](https:\u002F\u002Fpkg.go.dev\u002Fbadge\u002Fgithub.com\u002Fgagliardetto\u002Fsolana-go?status.svg)](https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Fgagliardetto\u002Fsolana-go@v1.16.0?tab=doc)\n[![GitHub tag (latest SemVer pre-release)](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fv\u002Ftag\u002Fgagliardetto\u002Fsolana-go?include_prereleases&label=release-tag)](https:\u002F\u002Fgithub.com\u002Fgagliardetto\u002Fsolana-go\u002Freleases)\n[![Build Status](https:\u002F\u002Fgithub.com\u002Fgagliardetto\u002Fsolana-go\u002Fworkflows\u002Ftests\u002Fbadge.svg?branch=main)](https:\u002F\u002Fgithub.com\u002Fgagliardetto\u002Fsolana-go\u002Factions?query=branch%3Amain)\n[![Lint Status](https:\u002F\u002Fgithub.com\u002Fgagliardetto\u002Fsolana-go\u002Fworkflows\u002Flint\u002Fbadge.svg?branch=main)](https:\u002F\u002Fgithub.com\u002Fgagliardetto\u002Fsolana-go\u002Factions?query=branch%3Amain+workflow%3Alint)\n[![TODOs](https:\u002F\u002Fbadgen.net\u002Fhttps\u002Fapi.tickgit.com\u002Fbadgen\u002Fgithub.com\u002Fgagliardetto\u002Fsolana-go\u002Fmain)](https:\u002F\u002Fwww.tickgit.com\u002Fbrowse?repo=github.com\u002Fgagliardetto\u002Fsolana-go&branch=main)\n[![Go Report Card](https:\u002F\u002Fgoreportcard.com\u002Fbadge\u002Fgithub.com\u002Fgagliardetto\u002Fsolana-go)](https:\u002F\u002Fgoreportcard.com\u002Freport\u002Fgithub.com\u002Fgagliardetto\u002Fsolana-go)\n\nGo library to interface with Solana JSON RPC and WebSocket interfaces.\n\nMore contracts to come.\n\n**If you're using\u002Fdeveloping Solana programs written in [Anchor Framework](https:\u002F\u002Fgithub.com\u002Fcoral-xyz\u002Fanchor), you can use [anchor-go](https:\u002F\u002Fgithub.com\u002Fgagliardetto\u002Fanchor-go) to generate Golang clients**\n\n\u003Cdiv align=\"center\">\n    \u003Cimg src=\"https:\u002F\u002Fuser-images.githubusercontent.com\u002F15271561\u002F128235229-1d2d9116-23bb-464e-b2cc-8fb6355e3b55.png\" margin=\"auto\" height=\"175\"\u002F>\n\u003C\u002Fdiv>\n\n## Contents\n\n- [Solana SDK library for Go](#solana-sdk-library-for-go)\n  - [Contents](#contents)\n  - [Features](#features)\n  - [Current development status](#current-development-status)\n  - [Note](#note)\n  - [Requirements](#requirements)\n  - [Installation](#installation)\n  - [Pretty-Print transactions\u002Finstructions](#pretty-print-transactionsinstructions)\n  - [SendAndConfirmTransaction](#sendandconfirmtransaction)\n  - [Address Lookup Tables](#address-lookup-tables)\n  - [Parse\u002Fdecode an instruction from a transaction](#parsedecode-an-instruction-from-a-transaction)\n  - [Borsh encoding\u002Fdecoding](#borsh-encodingdecoding)\n  - [ZSTD account data encoding](#zstd-account-data-encoding)\n  - [Working with rate-limited RPC providers](#working-with-rate-limited-rpc-providers)\n  - [Custom Headers for authenticating with RPC providers](#custom-headers-for-authenticating-with-rpc-providers)\n  - [Timeouts and Custom HTTP Clients](#timeouts-and-custom-http-clients)\n  - [Examples](#examples)\n    - [Create account (wallet)](#create-account-wallet)\n    - [Load\u002Fparse private and public keys](#loadparse-private-and-public-keys)\n    - [Transfer Sol from one wallet to another wallet](#transfer-sol-from-one-wallet-to-another-wallet)\n  - [RPC Methods](#rpc-methods)\n  - [WebSocket Subscriptions](#websocket-subscriptions)\n  - [Contributing](#contributing)\n  - [License](#license)\n  - [Credits](#credits)\n\n## Features\n\n- [x] [Full JSON RPC API](#rpc-usage-examples)\n- [x] Full WebSocket JSON streaming API\n- [ ] Wallet, account, and keys management\n- [ ] Clients for native programs\n  - [x] [system](\u002Fprograms\u002Fsystem)\n  - [ ] config\n  - [ ] stake\n  - [ ] vote\n  - [x] BPF Loader\n  - [ ] Secp256k1\n- [ ] Clients for Solana Program Library (SPL)\n  - [x] [SPL token](\u002Fprograms\u002Ftoken)\n  - [x] [associated-token-account](\u002Fprograms\u002Fassociated-token-account)\n  - [x] memo\n  - [ ] name-service\n  - [ ] ...\n- [x] [Metaplex](https:\u002F\u002Fgithub.com\u002Fgagliardetto\u002Fmetaplex-go):\n  - [x] auction\n  - [x] metaplex\n  - [x] token-metadata\n  - [x] token-vault\n  - [x] nft-candy-machine\n- [ ] More programs\n\n## Current development status\n\nThere is currently **no stable release**. The SDK is actively developed and latest is `v1.16.0` which is an `alpha` release.\n\nThe RPC and WS client implementation is based on the [Solana RPC API documentation](https:\u002F\u002Fsolana.com\u002Fdocs\u002Frpc).\n\n## Note\n\n- solana-go is in active development, so all APIs are subject to change.\n- This code is unaudited. Use at your own risk.\n\n## Requirements\n\n- Go 1.24 or later\n\n## Installation\n\n```bash\n$ cd my-project\n$ go get github.com\u002Fgagliardetto\u002Fsolana-go@v1.16.0\n```\n\n## Pretty-Print transactions\u002Finstructions\n\n![pretty-printed](https:\u002F\u002Fuser-images.githubusercontent.com\u002F15271561\u002F136708519-399c9498-3d20-48d6-89fa-bdf43aac6d83.png)\n\nInstructions can be pretty-printed with the `String()` method on a `Transaction`:\n\n```go\ntx, err := solana.NewTransaction(\n  []solana.Instruction{\n    system.NewTransferInstruction(\n      amount,\n      accountFrom.PublicKey(),\n      accountTo,\n    ).Build(),\n  },\n  recent.Value.Blockhash,\n  solana.TransactionPayer(accountFrom.PublicKey()),\n)\n\n...\n\n\u002F\u002F Pretty print the transaction:\nfmt.Println(tx.String())\n\u002F\u002F OR you can choose a destination and a title:\n\u002F\u002F tx.EncodeTree(text.NewTreeEncoder(os.Stdout, \"Transfer SOL\"))\n```\n\n## SendAndConfirmTransaction\n\nYou can wait for a transaction confirmation using the `github.com\u002Fgagliardetto\u002Fsolana-go\u002Frpc\u002FsendAndConfirmTransaction` package tools (for a complete example: [see here](#transfer-sol-from-one-wallet-to-another-wallet))\n\n```go\n\u002F\u002F Send transaction, and wait for confirmation:\nsig, err := confirm.SendAndConfirmTransaction(\n  context.TODO(),\n  rpcClient,\n  wsClient,\n  tx,\n)\nif err != nil {\n  panic(err)\n}\nspew.Dump(sig)\n```\n\nThe above command will send the transaction, and wait for its confirmation.\n\n## Address Lookup Tables\n\nResolve lookups for a transaction:\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com\u002Fdavecgh\u002Fgo-spew\u002Fspew\"\n\t\"github.com\u002Fgagliardetto\u002Fsolana-go\"\n\tlookup \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Fprograms\u002Faddress-lookup-table\"\n\t\"github.com\u002Fgagliardetto\u002Fsolana-go\u002Frpc\"\n\t\"golang.org\u002Fx\u002Ftime\u002Frate\"\n)\n\nfunc main() {\n\tcluster := rpc.MainNetBeta\n\n\trpcClient := rpc.NewWithCustomRPCClient(rpc.NewWithLimiter(\n\t\tcluster.RPC,\n\t\trate.Every(time.Second), \u002F\u002F time frame\n\t\t5,                       \u002F\u002F limit of requests per time frame\n\t))\n\n\tversion := uint64(0)\n\ttx, err := rpcClient.GetTransaction(\n\t\tcontext.Background(),\n\t\tsolana.MustSignatureFromBase58(\"24jRjMP3medE9iMqVSPRbkwfe9GdPmLfeftKPuwRHZdYTZJ6UyzNMGGKo4BHrTu2zVj4CgFF3CEuzS79QXUo2CMC\"),\n\t\t&rpc.GetTransactionOpts{\n\t\t\tMaxSupportedTransactionVersion: &version,\n\t\t\tEncoding:                       solana.EncodingBase64,\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tparsed, err := tx.Transaction.GetTransaction()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tprocessTransactionWithAddressLookups(parsed, rpcClient)\n}\n\nfunc processTransactionWithAddressLookups(txx *solana.Transaction, rpcClient *rpc.Client) {\n\tif !txx.Message.IsVersioned() {\n\t\tfmt.Println(\"tx is not versioned; only versioned transactions can contain lookups\")\n\t\treturn\n\t}\n\ttblKeys := txx.Message.GetAddressTableLookups().GetTableIDs()\n\tif len(tblKeys) == 0 {\n\t\tfmt.Println(\"no lookup tables in versioned transaction\")\n\t\treturn\n\t}\n\tnumLookups := txx.Message.GetAddressTableLookups().NumLookups()\n\tif numLookups == 0 {\n\t\tfmt.Println(\"no lookups in versioned transaction\")\n\t\treturn\n\t}\n\tfmt.Println(\"num lookups:\", numLookups)\n\tfmt.Println(\"num tbl keys:\", len(tblKeys))\n\tresolutions := make(map[solana.PublicKey]solana.PublicKeySlice)\n\tfor _, key := range tblKeys {\n\t\tfmt.Println(\"Getting table\", key)\n\n\t\tinfo, err := rpcClient.GetAccountInfo(\n\t\t\tcontext.Background(),\n\t\t\tkey,\n\t\t)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tfmt.Println(\"got table \"+key.String())\n\n\t\ttableContent, err := lookup.DecodeAddressLookupTableState(info.GetBinary())\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\n\t\tfmt.Println(\"table content:\", spew.Sdump(tableContent))\n\t\tfmt.Println(\"isActive\", tableContent.IsActive())\n\n\t\tresolutions[key] = tableContent.Addresses\n\t}\n\n\terr := txx.Message.SetAddressTables(resolutions)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\terr = txx.Message.ResolveLookups()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Println(txx.String())\n}\n```\n\n\n## Parse\u002Fdecode an instruction from a transaction\n\n```go\npackage main\n\nimport (\n  \"context\"\n  \"encoding\u002Fbase64\"\n  \"os\"\n  \"reflect\"\n\n  \"github.com\u002Fdavecgh\u002Fgo-spew\u002Fspew\"\n  bin \"github.com\u002Fgagliardetto\u002Fbinary\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Fprograms\u002Fsystem\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Frpc\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Ftext\"\n)\n\nfunc main() {\n  exampleFromGetTransaction()\n}\n\nfunc exampleFromBase64() {\n  encoded := \"AfjEs3XhTc3hrxEvlnMPkm\u002FcocvAUbFNbCl00qKnrFue6J53AhEqIFmcJJlJW3EDP5RmcMz+cNTTcZHW\u002FWJYwAcBAAEDO8hh4VddzfcO5jbCt95jryl6y8ff65UcgukHNLWH+UQGgxCGGpgyfQVQV02EQYqm4QwzUt2qf9f1gVLM7rI4hwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6ANIF55zOZWROWRkeh+lExxZBnKFqbvIxZDLE7EijjoBAgIAAQwCAAAAOTAAAAAAAAA=\"\n\n  data, err := base64.StdEncoding.DecodeString(encoded)\n  if err != nil {\n    panic(err)\n  }\n\n  \u002F\u002F parse transaction:\n  tx, err := solana.TransactionFromDecoder(bin.NewBinDecoder(data))\n  if err != nil {\n    panic(err)\n  }\n\n  decodeSystemTransfer(tx)\n}\n\nfunc exampleFromGetTransaction() {\n  endpoint := rpc.TestNet_RPC\n  client := rpc.New(endpoint)\n\n  txSig := solana.MustSignatureFromBase58(\"3hZorctJtD3QLCRV3zF6JM6FDbFR5kAvsuKEG1RH9rWdz8YgnDzAvMWZFjdJgoL8KSNzZnx7aiExm1JEMC8KHfyy\")\n  {\n    out, err := client.GetTransaction(\n      context.TODO(),\n      txSig,\n      &rpc.GetTransactionOpts{\n        Encoding: solana.EncodingBase64,\n      },\n    )\n    if err != nil {\n      panic(err)\n    }\n\n    tx, err := solana.TransactionFromDecoder(bin.NewBinDecoder(out.Transaction.GetBinary()))\n    if err != nil {\n      panic(err)\n    }\n\n    decodeSystemTransfer(tx)\n  }\n}\n\nfunc decodeSystemTransfer(tx *solana.Transaction) {\n  spew.Dump(tx)\n\n  \u002F\u002F Get (for example) the first instruction of this transaction\n  \u002F\u002F which we know is a `system` program instruction:\n  i0 := tx.Message.Instructions[0]\n\n  \u002F\u002F Find the program address of this instruction:\n  progKey, err := tx.ResolveProgramIDIndex(i0.ProgramIDIndex)\n  if err != nil {\n    panic(err)\n  }\n\n  \u002F\u002F Find the accounts of this instruction:\n  accounts, err := i0.ResolveInstructionAccounts(&tx.Message)\n  if err != nil {\n    panic(err)\n  }\n\n  \u002F\u002F Feed the accounts and data to the system program parser\n  \u002F\u002F OR see below for alternative parsing when you DON'T know\n  \u002F\u002F what program the instruction is for \u002F you don't have a parser.\n  inst, err := system.DecodeInstruction(accounts, i0.Data)\n  if err != nil {\n    panic(err)\n  }\n\n  \u002F\u002F inst.Impl contains the specific instruction type (in this case, `inst.Impl` is a `*system.Transfer`)\n  spew.Dump(inst)\n  if _, ok := inst.Impl.(*system.Transfer); !ok {\n    panic(\"the instruction is not a *system.Transfer\")\n  }\n\n  \u002F\u002F OR\n  {\n    \u002F\u002F There is a more general instruction decoder: `solana.DecodeInstruction`.\n    \u002F\u002F It looks up the decoder for `progKey` in a central registry, so it\n    \u002F\u002F works for any program ID regardless of what you know at compile time.\n    \u002F\u002F\n    \u002F\u002F Each `programs\u002F\u003Cname>` package registers its decoder via init(),\n    \u002F\u002F which only runs when the package is imported. If you are not\n    \u002F\u002F already using the package's builders (e.g. `system.NewTransferInstruction`),\n    \u002F\u002F blank-import it so the decoder is available - same idiom as\n    \u002F\u002F database\u002Fsql drivers:\n    \u002F\u002F\n    \u002F\u002F     import (\n    \u002F\u002F         _ \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Fprograms\u002Fsystem\"\n    \u002F\u002F         _ \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Fprograms\u002Ftoken\"\n    \u002F\u002F         \u002F\u002F ...add more as needed\n    \u002F\u002F     )\n    \u002F\u002F\n    \u002F\u002F For a program that solana-go does not ship (e.g. a custom Anchor\n    \u002F\u002F program), register its decoder yourself:\n    \u002F\u002F\n    \u002F\u002F     solana.MustRegisterInstructionDecoder(myProgramID, myDecoderFunc)\n    decodedInstruction, err := solana.DecodeInstruction(\n      progKey,\n      accounts,\n      i0.Data,\n    )\n    if err != nil {\n      panic(err)\n    }\n    \u002F\u002F The returned `decodedInstruction` is the decoded instruction.\n    spew.Dump(decodedInstruction)\n\n    \u002F\u002F decodedInstruction == inst\n    if !reflect.DeepEqual(inst, decodedInstruction) {\n      panic(\"they are NOT equal (this would never happen)\")\n    }\n  }\n\n  {\n    \u002F\u002F pretty-print whole transaction:\n    _, err := tx.EncodeTree(text.NewTreeEncoder(os.Stdout, text.Bold(\"TEST TRANSACTION\")))\n    if err != nil {\n      panic(err)\n    }\n  }\n}\n\n```\n\n## Borsh encoding\u002Fdecoding\n\nYou can use the `github.com\u002Fgagliardetto\u002Fbinary` package for encoding\u002Fdecoding borsh-encoded data:\n\nDecoder:\n\n```go\n  resp, err := client.GetAccountInfo(\n    context.TODO(),\n    pubKey,\n  )\n  if err != nil {\n    panic(err)\n  }\n\n  borshDec := bin.NewBorshDecoder(resp.GetBinary())\n  var meta token_metadata.Metadata\n  err = borshDec.Decode(&meta)\n  if err != nil {\n    panic(err)\n  }\n```\n\nEncoder:\n\n```go\nbuf := new(bytes.Buffer)\nborshEncoder := bin.NewBorshEncoder(buf)\nerr := borshEncoder.Encode(meta)\nif err != nil {\n  panic(err)\n}\n\u002F\u002F fmt.Print(buf.Bytes())\n```\n\n## ZSTD account data encoding\n\nYou can request account data to be encoded with base64+zstd in the `Encoding` parameter:\n\n```go\nresp, err := client.GetAccountInfoWithOpts(\n  context.TODO(),\n  pubKey,\n  &rpc.GetAccountInfoOpts{\n    Encoding:   solana.EncodingBase64Zstd,\n    Commitment: rpc.CommitmentFinalized,\n  },\n)\nif err != nil {\n  panic(err)\n}\nspew.Dump(resp)\n\nvar mint token.Mint\nerr = bin.NewDecoder(resp.GetBinary()).Decode(&mint)\nif err != nil {\n  panic(err)\n}\nspew.Dump(mint)\n```\n\n## Working with rate-limited RPC providers\n\n```go\npackage main\n\nimport (\n  \"context\"\n\n  \"golang.org\u002Fx\u002Ftime\u002Frate\"\n  \"github.com\u002Fdavecgh\u002Fgo-spew\u002Fspew\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Frpc\"\n)\n\nfunc main() {\n  cluster := rpc.MainNetBeta\n  client := rpc.NewWithCustomRPCClient(rpc.NewWithLimiter(\n\t\tcluster.RPC,\n\t\trate.Every(time.Second), \u002F\u002F time frame\n\t\t5,                       \u002F\u002F limit of requests per time frame\n\t))\n\n  out, err := client.GetVersion(\n    context.TODO(),\n  )\n  if err != nil {\n    panic(err)\n  }\n  spew.Dump(out)\n}\n```\n\n## Custom Headers for authenticating with RPC providers\n\n```go\npackage main\n\nimport (\n  \"context\"\n\n  \"golang.org\u002Fx\u002Ftime\u002Frate\"\n  \"github.com\u002Fdavecgh\u002Fgo-spew\u002Fspew\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Frpc\"\n)\n\nfunc main() {\n  cluster := rpc.MainNetBeta\n  client := rpc.NewWithHeaders(\n    cluster.RPC,\n    map[string]string{\n      \"x-api-key\": \"...\",\n    },\n  )\n\n  out, err := client.GetVersion(\n    context.TODO(),\n  )\n  if err != nil {\n    panic(err)\n  }\n  spew.Dump(out)\n}\n```\n\nThe data will **AUTOMATICALLY get decoded** and returned (**the right decoder will be used**) when you call the `resp.GetBinary()` method.\n\n## Timeouts and Custom HTTP Clients\n\nYou can use a timeout context:\n\n```go\nctx, cancel := context.WithTimeout(context.Background(), time.Second*3)\ndefer cancel()\nacc, err := rpcClient.GetAccountInfoWithOpts(\n  ctx,\n  accountID,\n  &rpc.GetAccountInfoOpts{\n    Commitment: rpc.CommitmentProcessed,\n  },\n)\n```\n\nOr you can initialize the RPC client using a custom HTTP client using `rpc.NewWithCustomRPCClient`:\n\n```go\nimport (\n  \"net\"\n  \"net\u002Fhttp\"\n  \"time\"\n\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Frpc\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Frpc\u002Fjsonrpc\"\n)\n\nfunc NewHTTPTransport(\n  timeout time.Duration,\n  maxIdleConnsPerHost int,\n  keepAlive time.Duration,\n) *http.Transport {\n  return &http.Transport{\n    IdleConnTimeout:     timeout,\n    MaxIdleConnsPerHost: maxIdleConnsPerHost,\n    Proxy:               http.ProxyFromEnvironment,\n    Dial: (&net.Dialer{\n      Timeout:   timeout,\n      KeepAlive: keepAlive,\n    }).Dial,\n  }\n}\n\n\u002F\u002F NewHTTP returns a new Client from the provided config.\nfunc NewHTTP(\n  timeout time.Duration,\n  maxIdleConnsPerHost int,\n  keepAlive time.Duration,\n) *http.Client {\n  tr := NewHTTPTransport(\n    timeout,\n    maxIdleConnsPerHost,\n    keepAlive,\n  )\n\n  return &http.Client{\n    Timeout:   timeout,\n    Transport: tr,\n  }\n}\n\n\u002F\u002F NewRPC creates a new Solana JSON RPC client.\nfunc NewRPC(rpcEndpoint string) *rpc.Client {\n  var (\n    defaultMaxIdleConnsPerHost = 10\n    defaultTimeout             = 25 * time.Second\n    defaultKeepAlive           = 180 * time.Second\n  )\n  opts := &jsonrpc.RPCClientOpts{\n    HTTPClient: NewHTTP(\n      defaultTimeout,\n      defaultMaxIdleConnsPerHost,\n      defaultKeepAlive,\n    ),\n  }\n  rpcClient := jsonrpc.NewClientWithOpts(rpcEndpoint, opts)\n  return rpc.NewWithCustomRPCClient(rpcClient)\n}\n```\n\n## Examples\n\n### Create account (wallet)\n\n```go\npackage main\n\nimport (\n  \"context\"\n  \"fmt\"\n\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Frpc\"\n)\n\nfunc main() {\n  \u002F\u002F Create a new account:\n  account := solana.NewWallet()\n  fmt.Println(\"account private key:\", account.PrivateKey)\n  fmt.Println(\"account public key:\", account.PublicKey())\n\n  \u002F\u002F Create a new RPC client:\n  client := rpc.New(rpc.TestNet_RPC)\n\n  \u002F\u002F Airdrop 1 SOL to the new account:\n  out, err := client.RequestAirdrop(\n    context.TODO(),\n    account.PublicKey(),\n    solana.LAMPORTS_PER_SOL*1,\n    rpc.CommitmentFinalized,\n  )\n  if err != nil {\n    panic(err)\n  }\n  fmt.Println(\"airdrop transaction signature:\", out)\n}\n```\n\n### Load\u002Fparse private and public keys\n\n```go\n{\n  \u002F\u002F Load private key from a json file generated with\n  \u002F\u002F $ solana-keygen new --outfile=standard.solana-keygen.json\n  privateKey, err := solana.PrivateKeyFromSolanaKeygenFile(\"\u002Fpath\u002Fto\u002Fstandard.solana-keygen.json\")\n  if err != nil {\n    panic(err)\n  }\n  fmt.Println(\"private key:\", privateKey.String())\n  \u002F\u002F To get the public key, you need to call the `PublicKey()` method:\n  publicKey := privateKey.PublicKey()\n  \u002F\u002F To get the base58 string of a public key, you can call the `String()` method:\n  fmt.Println(\"public key:\", publicKey.String())\n}\n\n{\n  \u002F\u002F Load private key from base58:\n  {\n    privateKey, err := solana.PrivateKeyFromBase58(\"66cDvko73yAf8LYvFMM3r8vF5vJtkk7JKMgEKwkmBC86oHdq41C7i1a2vS3zE1yCcdLLk6VUatUb32ZzVjSBXtRs\")\n    if err != nil {\n      panic(err)\n    }\n    fmt.Println(\"private key:\", privateKey.String())\n    fmt.Println(\"public key:\", privateKey.PublicKey().String())\n  }\n  \u002F\u002F OR:\n  {\n    privateKey := solana.MustPrivateKeyFromBase58(\"66cDvko73yAf8LYvFMM3r8vF5vJtkk7JKMgEKwkmBC86oHdq41C7i1a2vS3zE1yCcdLLk6VUatUb32ZzVjSBXtRs\")\n    _ = privateKey\n  }\n}\n\n{\n  \u002F\u002F Generate a new key pair:\n  {\n    privateKey, err := solana.NewRandomPrivateKey()\n    if err != nil {\n      panic(err)\n    }\n    _ = privateKey\n  }\n  {\n    { \u002F\u002F Generate a new private key (a Wallet struct is just a wrapper around a private key)\n      account := solana.NewWallet()\n      _ = account\n    }\n  }\n}\n\n{\n  \u002F\u002F Parse a public key from a base58 string:\n  {\n    publicKey, err := solana.PublicKeyFromBase58(\"F8UvVsKnzWyp2nF8aDcqvQ2GVcRpqT91WDsAtvBKCMt9\")\n    if err != nil {\n      panic(err)\n    }\n    _ = publicKey\n  }\n  \u002F\u002F OR:\n  {\n    publicKey := solana.MustPublicKeyFromBase58(\"F8UvVsKnzWyp2nF8aDcqvQ2GVcRpqT91WDsAtvBKCMt9\")\n    _ = publicKey\n  }\n}\n```\n\n### Transfer Sol from one wallet to another wallet\n\n```go\npackage main\n\nimport (\n  \"context\"\n  \"fmt\"\n  \"os\"\n  \"time\"\n\n  \"github.com\u002Fdavecgh\u002Fgo-spew\u002Fspew\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Fprograms\u002Fsystem\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Frpc\"\n  confirm \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Frpc\u002FsendAndConfirmTransaction\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Frpc\u002Fjsonrpc\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Frpc\u002Fws\"\n  \"github.com\u002Fgagliardetto\u002Fsolana-go\u002Ftext\"\n)\n\nfunc main() {\n  \u002F\u002F Create a new RPC client:\n  rpcClient := rpc.New(rpc.DevNet_RPC)\n\n  \u002F\u002F Create a new WS client (used for confirming transactions)\n  wsClient, err := ws.Connect(context.Background(), rpc.DevNet_WS)\n  if err != nil {\n    panic(err)\n  }\n\n  \u002F\u002F Load the account that you will send funds FROM:\n  accountFrom, err := solana.PrivateKeyFromSolanaKeygenFile(\"\u002Fpath\u002Fto\u002F.config\u002Fsolana\u002Fid.json\")\n  if err != nil {\n    panic(err)\n  }\n  fmt.Println(\"accountFrom private key:\", accountFrom)\n  fmt.Println(\"accountFrom public key:\", accountFrom.PublicKey())\n\n  \u002F\u002F The public key of the account that you will send sol TO:\n  accountTo := solana.MustPublicKeyFromBase58(\"TODO\")\n  \u002F\u002F The amount to send (in lamports);\n  \u002F\u002F 1 sol = 1000000000 lamports\n  amount := uint64(3333)\n\n  if true {\n    \u002F\u002F Airdrop 1 sol to the account so it will have something to transfer:\n    out, err := rpcClient.RequestAirdrop(\n      context.TODO(),\n      accountFrom.PublicKey(),\n      solana.LAMPORTS_PER_SOL*1,\n      rpc.CommitmentFinalized,\n    )\n    if err != nil {\n      panic(err)\n    }\n    fmt.Println(\"airdrop transaction signature:\", out)\n    time.Sleep(time.Second * 5)\n  }\n  \u002F\u002F---------------\n\n  recent, err := rpcClient.GetLatestBlockhash(context.TODO(), rpc.CommitmentFinalized)\n  if err != nil {\n    panic(err)\n  }\n\n  tx, err := solana.NewTransaction(\n    []solana.Instruction{\n      system.NewTransferInstruction(\n        amount,\n        accountFrom.PublicKey(),\n        accountTo,\n      ).Build(),\n    },\n    recent.Value.Blockhash,\n    solana.TransactionPayer(accountFrom.PublicKey()),\n  )\n  if err != nil {\n    panic(err)\n  }\n\n  _, err = tx.Sign(\n    func(key solana.PublicKey) *solana.PrivateKey {\n      if accountFrom.PublicKey().Equals(key) {\n        return &accountFrom\n      }\n      return nil\n    },\n  )\n  if err != nil {\n    panic(fmt.Errorf(\"unable to sign transaction: %w\", err))\n  }\n  spew.Dump(tx)\n  \u002F\u002F Pretty print the transaction:\n  tx.EncodeTree(text.NewTreeEncoder(os.Stdout, \"Transfer SOL\"))\n\n  \u002F\u002F Send transaction, and wait for confirmation:\n  sig, err := confirm.SendAndConfirmTransaction(\n    context.TODO(),\n    rpcClient,\n    wsClient,\n    tx,\n  )\n  if err != nil {\n    panic(err)\n  }\n  spew.Dump(sig)\n\n  \u002F\u002F Or just send the transaction WITHOUT waiting for confirmation:\n  \u002F\u002F sig, err := rpcClient.SendTransactionWithOpts(\n  \u002F\u002F   context.TODO(),\n  \u002F\u002F   tx,\n  \u002F\u002F   false,\n  \u002F\u002F   rpc.CommitmentFinalized,\n  \u002F\u002F )\n  \u002F\u002F if err != nil {\n  \u002F\u002F   panic(err)\n  \u002F\u002F }\n  \u002F\u002F spew.Dump(sig)\n}\n\n```\n\n## RPC Methods\n\nAll RPC methods from the [Solana JSON RPC API](https:\u002F\u002Fsolana.com\u002Fdocs\u002Frpc) are supported.\nEach method has a testable example in [`rpc\u002Fexample_test.go`](rpc\u002Fexample_test.go) that is rendered on\n[pkg.go.dev](https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Fgagliardetto\u002Fsolana-go@v1.16.0\u002Frpc#pkg-examples).\n\n\n## WebSocket Subscriptions\n\nAll WebSocket subscriptions from the [Solana WebSocket API](https:\u002F\u002Fsolana.com\u002Fdocs\u002Frpc\u002Fwebsocket) are supported.\nEach subscription has a testable example in [`rpc\u002Fws\u002Fexample_test.go`](rpc\u002Fws\u002Fexample_test.go) that is rendered on\n[pkg.go.dev](https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Fgagliardetto\u002Fsolana-go@v1.16.0\u002Frpc\u002Fws#pkg-examples).\n\n\n## Contributing\n\nWe encourage everyone to contribute, submit issues, PRs, discuss. Every kind of help is welcome.\n\nPlease read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on commit messages, semver policy, linting, and CI checks.\n\nBefore opening a PR, run:\n\n```bash\ngo test .\u002F... -count=1\ngolangci-lint run\n```\n\nBoth must pass in CI.\n\n## License\n\n[Apache 2.0](LICENSE)\n\n## Credits\n\n- Gopher logo was originally created by Takuya Ueda (https:\u002F\u002Ftwitter.com\u002Ftenntenn). Licensed under the Creative Commons 3.0 Attributions license.\n","solana-foundation\u002Fsolana-go 是一个用于与 Solana 区块链进行交互的 Go 语言 SDK 库和 RPC 客户端。该项目提供了完整的 JSON RPC API 和 WebSocket 接口支持，使得开发者能够轻松地构建、发送和确认交易，同时支持地址查找表、Borsh 编解码以及 ZSTD 账户数据编码等功能。此外，它还具备处理限流的 RPC 提供商、自定义 HTTP 客户端设置等特性，以满足不同网络环境下的需求。此项目适用于任何需要通过 Go 语言与 Solana 网络进行交互的应用场景，如开发钱包应用、DeFi 服务或其他基于 Solana 的去中心化应用程序。",2,"2026-06-11 03:29:19","top_topic"]