RPC Quick Start
Send Solana transactions through Solana Gun using your preferred Solana SDK.
Before you begin
Use your Solana Gun endpoint:
https://<HOST>/<TOKEN>. Replace the placeholders with your connection details.Have a funded Solana wallet and its local keypair JSON file. The examples send 0.00001 SOL (10,000 lamports) to an existing wallet, plus the network fee.
Use a regular Solana RPC to fetch a recent blockhash. The examples use
https://solana-rpc.publicnode.com.
Send a transaction
Choose your language below. Each example signs locally and submits directly through the SDK. skipPreflight must be enabled because Solana Gun does not simulate individual transactions; the examples set it for you.
JavaScript (Node.js)
Use Node.js 22.12 or later with @solana/web3.js:
npm install @solana/web3.js@1
Save the code as
send.mjsand replace the endpoint, keypair path, and recipient address:import {
Connection, Keypair, PublicKey, SystemProgram,
TransactionMessage, VersionedTransaction,
} from "@solana/web3.js";
import { readFileSync } from "node:fs";
const KEYPAIR_PATH = "/path/to/keypair.json";
const RPC_URL = "https://solana-rpc.publicnode.com";
const GUN_URL = "https://<HOST>/<TOKEN>";
const RECIPIENT_ADDRESS = "<RECIPIENT_ADDRESS>";
const AMOUNT_LAMPORTS = 10_000;
const payer = Keypair.fromSecretKey(
Uint8Array.from(JSON.parse(readFileSync(KEYPAIR_PATH, "utf8"))),
);
const recipient = new PublicKey(RECIPIENT_ADDRESS);
const rpc = new Connection(RPC_URL, "confirmed");
const { blockhash } = await rpc.getLatestBlockhash();
const message = new TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: blockhash,
instructions: [
SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: recipient,
lamports: AMOUNT_LAMPORTS,
}),
],
}).compileToV0Message();
const transaction = new VersionedTransaction(message);
transaction.sign([payer]);
const gun = new Connection(GUN_URL, {
fetch: (url, options) => fetch(url, {
...options, signal: AbortSignal.timeout(30_000),
}),
});
try {
const signature = await gun.sendRawTransaction(transaction.serialize(), {
skipPreflight: true,
});
console.log("Submitted. Transaction signature:", signature);
} catch (error) {
console.error("Submission failed:", error.message);
process.exitCode = 1;
}node send.mjs
Python
Install the SDK version used by this example:
python3 -m pip install solana==0.36.9
Save the code as
send.pyand replace the endpoint, keypair path, and recipient address:import asyncio
from pathlib import Path
from solana.rpc.async_api import AsyncClient
from solana.rpc.types import TxOpts
from solders.keypair import Keypair
from solders.message import MessageV0
from solders.pubkey import Pubkey
from solders.system_program import TransferParams, transfer
from solders.transaction import VersionedTransaction
KEYPAIR_PATH = "/path/to/keypair.json"
RPC_URL = "https://solana-rpc.publicnode.com"
GUN_URL = "https://<HOST>/<TOKEN>"
RECIPIENT_ADDRESS = "<RECIPIENT_ADDRESS>"
AMOUNT_LAMPORTS = 10_000
async def main():
payer = Keypair.from_json(Path(KEYPAIR_PATH).read_text())
recipient = Pubkey.from_string(RECIPIENT_ADDRESS)
async with AsyncClient(RPC_URL, timeout=30) as rpc:
blockhash = (await rpc.get_latest_blockhash(commitment="confirmed")).value.blockhash
instruction = transfer(TransferParams(
from_pubkey=payer.pubkey(),
to_pubkey=recipient,
lamports=AMOUNT_LAMPORTS,
))
message = MessageV0.try_compile(payer.pubkey(), [instruction], [], blockhash)
transaction = VersionedTransaction(message, [payer])
async with AsyncClient(GUN_URL, timeout=30) as gun:
response = await gun.send_raw_transaction(
bytes(transaction), opts=TxOpts(skip_preflight=True),
)
print("Submitted. Transaction signature:", response.value)
asyncio.run(main())python3 send.py
Go
Create a directory for the example and install solana-go:
mkdir solana-gun-go
cd solana-gun-go
go mod init solana-gun-example
go get github.com/gagliardetto/[email protected]Save the code as
main.goand replace the endpoint, keypair path, and recipient address:package main
import (
"context"
"fmt"
"time"
"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/programs/system"
"github.com/gagliardetto/solana-go/rpc"
)
const (
KEYPAIR_PATH = "/path/to/keypair.json"
RPC_URL = "https://solana-rpc.publicnode.com"
GUN_URL = "https://<HOST>/<TOKEN>"
RECIPIENT_ADDRESS = "<RECIPIENT_ADDRESS>"
AMOUNT_LAMPORTS uint64 = 10_000
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
payer, err := solana.PrivateKeyFromSolanaKeygenFile(KEYPAIR_PATH)
if err != nil {
panic(err)
}
recipient := solana.MustPublicKeyFromBase58(RECIPIENT_ADDRESS)
source := rpc.New(RPC_URL)
latest, err := source.GetLatestBlockhash(ctx, rpc.CommitmentConfirmed)
if err != nil {
panic(err)
}
transaction, err := solana.NewTransaction(
[]solana.Instruction{
system.NewTransferInstruction(AMOUNT_LAMPORTS, payer.PublicKey(), recipient).Build(),
},
latest.Value.Blockhash,
solana.TransactionPayer(payer.PublicKey()),
)
if err != nil {
panic(err)
}
_, err = transaction.Sign(func(key solana.PublicKey) *solana.PrivateKey {
if key == payer.PublicKey() {
return &payer
}
return nil
})
if err != nil {
panic(err)
}
gun := rpc.New(GUN_URL)
signature, err := gun.SendTransactionWithOpts(ctx, transaction, rpc.TransactionOpts{SkipPreflight: true})
if err != nil {
panic(err)
}
fmt.Println("Submitted. Transaction signature:", signature)
}go mod tidy
go run .
Rust
Create a Rust project:
cargo new solana-gun-rpc-example
cd solana-gun-rpc-exampleReplace its
[dependencies]section inCargo.tomlwith:[dependencies]
anyhow = "1"
solana-client = "=2.3.13"
solana-sdk = "=2.3.1"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }Save the code as
src/main.rsand replace the endpoint, keypair path, and recipient address:use solana_client::{
nonblocking::rpc_client::RpcClient,
rpc_config::RpcSendTransactionConfig,
};
use solana_sdk::{
commitment_config::CommitmentConfig,
pubkey::Pubkey,
signature::{read_keypair_file, Signer},
system_instruction,
transaction::{Transaction, VersionedTransaction},
};
use std::time::Duration;
const KEYPAIR_PATH: &str = "/path/to/keypair.json";
const RPC_URL: &str = "https://solana-rpc.publicnode.com";
const GUN_URL: &str = "https://<HOST>/<TOKEN>";
const RECIPIENT_ADDRESS: &str = "<RECIPIENT_ADDRESS>";
const AMOUNT_LAMPORTS: u64 = 10_000;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let payer = read_keypair_file(KEYPAIR_PATH)
.map_err(|error| anyhow::anyhow!(error.to_string()))?;
let recipient: Pubkey = RECIPIENT_ADDRESS.parse()?;
let rpc = RpcClient::new_with_timeout(RPC_URL.to_string(), Duration::from_secs(30));
let (blockhash, _) = rpc
.get_latest_blockhash_with_commitment(CommitmentConfig::confirmed())
.await?;
let instruction =
system_instruction::transfer(&payer.pubkey(), &recipient, AMOUNT_LAMPORTS);
let transaction = VersionedTransaction::from(Transaction::new_signed_with_payer(
&[instruction],
Some(&payer.pubkey()),
&[&payer],
blockhash,
));
let gun = RpcClient::new_with_timeout(GUN_URL.to_string(), Duration::from_secs(30));
let signature = gun
.send_transaction_with_config(
&transaction,
RpcSendTransactionConfig { skip_preflight: true, ..Default::default() },
)
.await?;
println!("Submitted. Transaction signature: {signature}");
Ok(())
}cargo run --release
Submission response
A successful call returns the transaction signature and means Solana Gun accepted it for forwarding. It does not guarantee confirmation on Solana.