Sig is a Solana validator client implementation written in Zig.
Zig's own definition: Zig is a general-purpose programming language and toolchain for maintaining robust, optimal and reusable software.
-
Optimized performance: Zig provides control over how your program runs at a low level, similar to languages like C. It allows fine-grained control over aspects such as memory management and system calls, which can lead to improved performance.
-
Safety focus: Zig has features built in to prevent common bugs and safety issues common in C. For example, it includes built-in testing and bounds checking, which can help avoid problems such as buffer overflows and undefined behavior.
-
Readability and maintainability: Zig syntax is designed to be straightforward and clear. This can make the code easier to understand, more maintainable, and less prone to bugs.
-
No hidden control flow: Zig doesn't allow hidden control-flow like exceptions in some other languages. This can make it easier to reason about what your program is doing.
-
Integration with C: Zig has excellent interoperation with C. You can directly include C libraries and headers in a Zig program, which can save time when using existing C libraries.
-
Custom allocators: Zig allows you to define custom memory allocation strategies for different parts of your program. This provides the flexibility to optimize memory usage for specific use-cases or workloads.
- Zig is still a evolving language.
- Many of the low-level APIs have been stabilized but
std.http.Client
andstd.json
are still WIP targetting stable implementations by>=0.11
. - This library was compiled and tested using
0.11.0-dev.3997+546212ff7
(master). - Zig is targeting end of Q2 2023 for
0.11
milestone. - Currently,
std.http.Client
leaks and is failing some tests, fix is in works.
-
Gossip - A gossip spy node, run by:
sig gossip
orzig build run -- gossip
-
Core - Core data structures shared across modules
-
RPC Client - A fully featured HTTP RPC client with ability to query all on-chain data along with sending transactions
Add Sig
to your Zig project using build.zig.zon
file (available for Zig >= 0.11).
Steps
- how to install Sig in your Zig project
-
Declare Sig as a dependency in
build.zig.zon
:.{ .name = "my-project", .version = "1.0.0", .dependencies = .{ + .sig = .{ + .url = "https://github.com/syndica/sig/archive/<COMMIT>.tar.gz", + }, }, }
-
Expose Sig as a module in
build.zig
:const std = @import("std"); pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); + const opts = .{ .target = target, .optimize = optimize }; + const sig_module = b.dependency("sig", opts).module("sig"); const exe = b.addExecutable(.{ .name = "test", .root_source_file = .{ .path = "src/main.zig" }, .target = target, .optimize = optimize, }); + exe.addModule("sig", sig_module); exe.install(); ... }
-
Obtain Sig's package hash:
$ zig build my-project/build.zig.zon:6:20: error: url field is missing corresponding hash field .url = "https://github.com/syndica/sig/archive/<COMMIT>.tar.gz", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ note: expected .hash = "<HASH>",
-
Update
build.zig.zon
with hash value:.{ .name = "my-project", .version = "1.0.0", .dependencies = .{ .sig = .{ .url = "https://github.com/syndica/sig/archive/<COMMIT>.tar.gz", + .hash = "<HASH>", }, }, }
A struct which holds a Public Key of a Solana account ([32]u8
).
From a string:
const Pubkey = @import("sig").core.Pubkey;
fn main() !void {
const pubkey = try Pubkey.fromString("4rL4RCWHz3iNCdCaveD8KcHfV9YWGsqSHFPo7X2zBNwa");
}
From raw bytes:
const Pubkey = @import("sig").core.Pubkey;
fn main() !void {
// Automatically encodes and caches the string value
const pubkey = try Pubkey.fromBytes(
&[32]u8{
44, 64, 232, 153, 35, 67, 7, 9, 46, 6, 87, 76, 55, 55, 65, 5,
99, 0, 48, 64, 75, 8, 127, 53, 57, 12, 7, 54, 8, 133, 246, 4,
},
.{},
);
// Optionally skip encoding if (in the rare scenario) you will never call the string() method, you can
// set this option to true and it will not decode & cache the encoded value. This can be helpful in
// scenarios where you plan to only use the bytes and want to save on expensive base58 encoding.
const pubkey = try Pubkey.fromBytes(
&[32]u8{
44, 64, 232, 153, 35, 67, 7, 9, 46, 6, 87, 76, 55, 55, 65, 5,
99, 0, 48, 64, 75, 8, 127, 53, 57, 12, 7, 54, 8, 133, 246, 4,
},
.{ .skip_encoding = true },
);
}
A struct which allows you to interact with a Solana cluster via JSON RPC. You can instantiate a client like so:
const rpc = @import("sig").rpc;
const HTTP_ENDPOINT = "https://api.mainnet-beta.solana.com";
fn main() !void {
var customHeaders = [_][2][]const u8{
.{ "Cache-Control", "no-cache" },
.{ "Authorization", "Bearer <SOME-TOKEN>" },
};
var client = try rpc.Client.init(allocator, .{
.http_endpoint = HTTP_ENDPOINT,
.http_headers = &customHeaders,
});
defer client.deinit();
}
getAccountInfo
- Returns all information associated with the account of provided Pubkey
Params: (address: Pubkey, options: GetAccountInfoOptions)
Options
const GetAccountInfoOptions = struct {
commitment: ?types.Commitment = null,
encoding: types.Encoding = .Base64,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const Pubkey = sig.core.Pubkey;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
const pubkey = try Pubkey.fromString("4rL4RCWHz3iNCdCaveD8KcHfV9YWGsqSHFPo7X2zBNwa");
var resp = try client.getAccountInfo(pubkey, .{ .encoding = .Base64 });
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("Account info: {any}", .{resp.result().value.data});
}
getBalance
- Returns the balance of the account of provided Pubkey
Params: (pubkey: Pubkey)
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const Pubkey = sig.core.Pubkey;
const allocator = std.heap.page_allocator;
pub fn main() !void {
const pubkey = try Pubkey.fromString("4rL4RCWHz3iNCdCaveD8KcHfV9YWGsqSHFPo7X2zBNwa");
var resp = try client.getBalance(pubkey);
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("balance info: {any}", .{resp.result().value});
}
getBlockHeight
- Returns the current block height of the node
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getBlockHeight();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("block height: {any}", .{resp.result()});
}
getBlock
- Returns identity and transaction information about a confirmed block in the ledger
Params: (slot: u64, options: GetBlockOptions)
Options
const GetBlockOptions = struct {
commitment: ?types.Commitment = null,
maxSupportedTransactionVersion: i64 = 0,
transactionDetails: []const u8 = "full",
rewards: bool = false,
/// NOTE: must be json for now
encoding: types.Encoding = .Json,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getBlock(500, .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("block info: {any}", .{resp.result()});
}
getBlockProduction
- Returns recent block production information from the current or previous epoch.
Params: (options: GetBlockOptions)
Options
const GetBlockProductionOptions = struct {
commitment: ?types.Commitment = null,
identity: ?[]const u8 = null,
range: ?struct {
firstSlot: u64,
lastSlot: ?u64,
} = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getBlockProduction(.{ .identity = "1EWZm7aZYxfZHbyiELXtTgN1yT2vU1HF9d8DWswX2Tp" });
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("block production info: {any}", .{resp.result()});
}
getBlockCommitment
- Returns commitment for particular block
Params: (slot: u64)
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getBlockCommitment(400);
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("block commitment info: {any}", .{resp.result()});
}
getBlocks
- Returns a list of confirmed blocks between two slots.
Params: (startSlot: u64, endSlot: ?u64, options: GetBlocksOptions)
Options
const GetBlocksOptions = struct {
commitment: ?types.Commitment = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getBlocks(400, 500, .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("blocks: {any}", .{resp.result()});
}
getBlocksWithLimit
- Returns a list of confirmed blocks starting at the given slot
Params: (startSlot: u64, limit: ?u64, options: GetBlocksOptions)
Options
const GetBlocksOptions = struct {
commitment: ?types.Commitment = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getBlocksWithLimit(400, 25, .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("blocks: {any}", .{resp.result()});
}
getBlockTime
- Returns the estimated production time of a block
Params: (slot: u64)
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getBlockTime(163954396);
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("block time: {any}", .{resp.result()});
}
getClusterNodes
- Returns information about all the nodes participating in the cluster
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getClusterNodes();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("cluster nodes: {any}", .{resp.result()});
}
getEpochInfo
- Returns information about the current epoch
Params: (options: GetEpochInfoOptions)
Options
const GetEpochInfoOptions = struct {
commitment: ?types.Commitment = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getEpochInfo(.{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("epoch info: {any}", .{resp.result()});
}
getEpochSchedule
- Returns the epoch schedule information from this cluster
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getEpochSchedule();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("epoch schedule: {any}", .{resp.result()});
}
getFeeForMessage
- Get the fee the network will charge for a particular Message
Params: (message: []const u8, options: GetFeeForMessageOptions)
Options
const GetFeeForMessageOptions = struct {
commitment: ?types.Commitment = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getFeeForMessage("AQABAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAA", .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("message fee info: {any}", .{resp.result()});
}
getFirstAvailableBlock
- Returns the slot of the lowest confirmed block that has not been purged from the ledger
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getFirstAvailableBlock();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("first available block: {any}", .{resp.result()});
}
getGenesisHash
- Returns the genesis hash
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var resp = try client.getGenesisHash();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("genesis hash: {any}", .{resp.result()});
}
getHealth
- Returns the current health of the node
NOTE: If one or more --known-validator arguments are provided to solana-validator - "ok" is returned when the node has within HEALTH_CHECK_SLOT_DISTANCE slots of the highest known validator, otherwise an error is returned. "ok" is always returned if no known validators are provided.
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getHealth();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("health: {any}", .{resp.result()});
}
getHighestSnapshotSlot
- Returns the highest slot information that the node has snapshots for
NOTE: This will find the highest full snapshot slot, and the highest incremental snapshot slot based on the full snapshot slot, if there is one.
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getHighestSnapshotSlot();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("snapshot info: {any}", .{resp.result()});
}
getIdentity
- Returns the identity pubkey for the current node
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getIdentity();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("indentity info: {any}", .{resp.result()});
}
getInflationGovernor
- Returns the current inflation governor
Params: (options: GetInflationGovernorOptions)
Options
const GetInflationGovernorOptions = struct {
commitment: ?types.Commitment = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getInflationGovernor(.{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("inflation info: {any}", .{resp.result()});
}
getInflationRate
- Returns the specific inflation values for the current epoch
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getInflationRate();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("inflation rate: {any}", .{resp.result()});
}
getInflationReward
- Returns the inflation / staking reward for a list of addresses for an epoch
Params: (accounts: []Pubkey, options: GetInflationRewardOptions)
Options
const GetInflationRewardOptions = struct {
commitment: ?types.Commitment = null,
epoch: ?u64 = null,
minContextSlot: ?u64 = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var accounts = [2]Pubkey{
try Pubkey.fromString(
"6dmNQ5jwLeLk5REvio1JcMshcbvkYMwy26sJ8pbkvStu",
) ,
try Pubkey.fromString(
"BGsqMegLpV6n6Ve146sSX2dTjUMj3M92HnU8BbNRMhF2",
),
};
var resp = try client.getInflationReward(&accounts, .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("inflation reward info: {any}", .{resp.result()});
}
getLargestAccounts
- Returns the 20 largest accounts, by lamport balance (results may be cached up to two hours)
Params: (options: GetLargestAccountsOptions)
Options
const GetLargestAccountsOptions = struct {
commitment: ?types.Commitment = null,
filter: ?enum { Circulating, NonCirculating } = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getLargestAccounts(.{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("largest accounts: {any}", .{resp.result()});
}
getLatestBlockhash
- Returns the latest blockhash
.
Params: (options: GetLatestBlockhashOptions)
Options
const GetLatestBlockhashOptions = struct {
commitment: ?types.Commitment = null,
minContextSlot: ?u64 = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getLatestBlockhash(.{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("latest blockhash: {any}", .{resp.result()});
}
getLeaderSchedule
- Returns the leader schedule for an epoch
Params: (epoch: ?u64, options: GetLeaderScheduleOptions)
Options
const GetLeaderScheduleOptions = struct {
commitment: ?types.Commitment = null,
identity: ?[]const u8 = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getLeaderSchedule(null, .{ .identity = "GRmtMtAeSL8HgX1p815ATQjaYU4Sk7XCP21i4yoFd3KS" });
// defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("leader schedule: {any}", .{resp.result()});
}
getMaxRetransmitSlot
- Get the max slot seen from retransmit stage
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getMaxRetransmitSlot();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("max retransmit slot: {any}", .{resp.result()});
}
getMaxShredInsertSlot
- Get the max slot seen from after shred insert
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getMaxShredInsertSlot();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("max shred insert slot: {any}", .{resp.result()});
}
getMinimumBalanceForRentExemption
- Returns minimum balance required to make account rent exempt
Params: (size: usize)
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getMinimumBalanceForRentExemption(1000);
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("minimum balance: {any}", .{resp.result()});
}
getMultipleAccounts
- Returns the account information for a list of Pubkeys
Params: (pubkeys: []Pubkey, options: GetMultipleAccountsOptions)
Options
const GetMultipleAccountsOptions = struct {
commitment: ?types.Commitment = null,
encoding: types.Encoding = .Base64,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var accounts2 = [2]Pubkey{
try Pubkey.fromString(
"4rL4RCWHz3iNCdCaveD8KcHfV9YWGsqSHFPo7X2zBNwa",
),
try Pubkey.fromString(
"BGsqMegLpV6n6Ve146sSX2dTjUMj3M92HnU8BbNRMhF2",
),
};
var resp = try client.getMultipleAccounts(&accounts2, .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("multiple accounts: {any}", .{resp.result()});
}
getProgramAccounts
- Returns all accounts owned by the provided program Pubkey
Params: (pubkeys: []Pubkey, options: GetMultipleAccountsOptions)
Options
pub const GetProgramAccountsOptions = struct {
commitment: ?types.Commitment = null,
/// NOTE: this needs to base64 if want to convert to `core.Account` type
encoding: types.Encoding = .Base64,
minContextSlot: ?u64 = null,
/// NOTE: needs to be true
withContext: bool = true,
dataSlice: ?DataSlice = null,
filters: ?[]Filter = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var filters = [1]Filter{.{ .memcmp = .{ .offset = 0, .bytes = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" } }};
var resp = try client.getProgramAccounts(
try Pubkey.fromString("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
.{ .filters = &filters },
);
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("program accounts: {any}", .{resp.result()});
}
getRecentPerformanceSamples
- Returns a list of recent performance samples, in reverse slot order
NOTE: Performance samples are taken every 60 seconds and include the number of transactions and slots that occur in a given time window.
Params: (limit: ?u64)
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getRecentPerformanceSamples(null);
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("recent performance samples: {any}", .{resp.result()});
}
getRecentPrioritizationFees
- Returns a list of prioritization fees from recent blocks
Params: (pubkeys: ?[]Pubkey)
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getRecentPrioritizationFees(null);
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("recent prioritization fees: {any}", .{resp.result()});
}
getSignaturesForAddress
- Returns signatures for confirmed transactions that include the given address in their accountKeys list
NOTE: Returns signatures backwards in time from the provided signature or most recent confirmed block.
Params: (pubkey: Pubkey, options: GetSignaturesForAddressOptions)
Options
pub const GetSignaturesForAddressOptions = struct {
commitment: ?types.Commitment = null,
minContextSlot: ?u64 = null,
limit: u32 = 1000,
before: ?[]const u8 = null,
until: ?[]const u8 = null,
};
```
**Usage**
<br/>
```zig
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getSignaturesForAddress(try Pubkey.fromString("4rL4RCWHz3iNCdCaveD8KcHfV9YWGsqSHFPo7X2zBNwa"), .{ .limit = 10 });
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("signatures: {any}", .{resp.result()});
}
getSignatureStatuses
- Returns the statuses of a list of signatures
Params: (pubkey: Pubkey, options: GetSignatureStatusesOptions)
Options
const GetSignatureStatusesOptions = struct {
searchTransactionHistory: bool = false,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var signatures = [2][]const u8{
"3oK4vMqnRbLhdNVq9Cb81JwHim4QaxvgcNEyA4jTySFFtFtBhJgmLwT3rMFAGakKHE9iMiymVNZsTbnrzNjuxXJc",
"5fqHdfeY1GbshDFzTdybqDbR3mwj5tkgHEP28dFWFZDcvQkkJUynVWrsfMYip8SsfAaFYTFmRdeC3K1CQRC7Ukkb",
};
var resp = try client.getSignatureStatuses(&signatures, .{ .searchTransactionHistory = true });
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("signature statuses: {any}", .{resp.result()});
}
getSlotLeader
- Returns the current slot leader
Params: (options: GetSlotLeaderOptions)
Options
const GetSlotLeaderOptions = struct {
commitment: ?types.Commitment = null,
minContextSlot: ?u64 = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getSlotLeader(.{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("slot leader: {any}", .{resp.result()});
}
getSlotLeaders
- Returns the slot leaders for a given slot range
Params: (startSlot: ?u64, limit: ?u64)
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getSlotLeaders(193536000, 10);
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("slot leaders: {any}", .{resp.result()});
}
getStakeActivation
- Returns epoch activation information for a stake account
Params: (pubkey: Pubkey, options: GetStakeActivationOptions)
Options
pub const GetStakeActivationOptions = struct {
commitment: ?types.Commitment = null,
minContextSlot: ?u64 = null,
epoch: ?u64 = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getStakeActivation(try Pubkey.fromString(
"CWrKSEDYhj6VHGocZowq2BUncKESqD7rdLTSrsoasTjU",
), .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("stake activation: {any}", .{resp.result()});
}
getStakeMinimumDelegation
- Returns epoch activation information for a stake account
Params: (options: GetStakeMinimumDelegationOptions)
Options
const GetStakeMinimumDelegationOptions = struct {
commitment: ?types.Commitment = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getStakeMinimumDelegation(.{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("min stake delegation: {any}", .{resp.result()});
}
getSupply
- Returns information about the current supply
Params: (options: GetSupplyOptions)
Options
const GetSupplyOptions = struct {
commitment: ?types.Commitment = null,
excludeNonCirculatingAccountsList: ?bool = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getSupply(.{ .excludeNonCirculatingAccountsList = false });
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("get supply: {any}", .{resp.result()});
}
getTokenAccountBalance
- Returns the token balance of an SPL Token account
Params: (pubkey: Pubkey, options: GetTokenAccountBalanceOptions)
Options
const GetTokenAccountBalanceOptions = struct {
commitment: ?types.Commitment = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var pubkey = try Pubkey.fromString(
"6A5NHCj1yF6urc9wZNe6Bcjj4LVszQNj5DwAWG97yzMu",
);
var resp = try client.getTokenAccountBalance(pubkey, .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("token account balance: {any}", .{resp.result()});
}
getTokenAccountsByDelegate
- Returns all SPL Token accounts by approved Delegate
Params: (pubkey: Pubkey, mintOrProgramId: MintOrProgramIdParam, options: GetTokenAccountsByDelegateOptions)
Options
const MintOrProgramIdParam = struct {
mint: ?Pubkey = null,
programId: ?Pubkey = null,
};
const GetTokenAccountsByDelegateOptions = struct {
commitment: ?types.Commitment = null,
encoding: types.Encoding = .Base64,
minContextSlot: ?u64 = null,
dataSlice: ?DataSlice = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var programPubkey = try Pubkey.fromString(
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
);
var pubkey = try Pubkey.fromString(
"CTz5UMLQm2SRWHzQnU62Pi4yJqbNGjgRBHqqp6oDHfF7",
);
var resp = try client.getTokenAccountsByDelegate(pubkey, .{ .programId = programPubkey }, .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("token accounts: {any}", .{resp.result()});
}
getTokenAccountsByOwner
- Returns all SPL Token accounts by token owner
Params: (pubkey: Pubkey, mintOrProgramId: MintOrProgramIdParam, options: GetTokenAccountsByOwnerOptions)
Options
const MintOrProgramIdParam = struct {
mint: ?Pubkey = null,
programId: ?Pubkey = null,
};
const GetTokenAccountsByOwnerOptions = struct {
commitment: ?types.Commitment = null,
encoding: types.Encoding = .Base64,
minContextSlot: ?u64 = null,
dataSlice: ?DataSlice = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var mintPubkey = try Pubkey.fromString(
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
);
var pubkey = try Pubkey.fromString(
"CTz5UMLQm2SRWHzQnU62Pi4yJqbNGjgRBHqqp6oDHfF7",
);
var resp = try client.getTokenAccountsByOwner(pubkey, .{ .mint = mintPubkey }, .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("token accounts: {any}", .{resp.result()});
}
getTokenLargestAccounts
- Returns the 20 largest accounts of a particular SPL Token type
Params: (pubkey: Pubkey, options: GetTokenLargestAccountsOptions)
Options
const GetTokenLargestAccountsOptions = struct {
commitment: ?types.Commitment = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var mintPubkey = try Pubkey.fromString(
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
);
var resp = try client.getTokenLargestAccounts(mintPubkey, .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("token largest accounts: {any}", .{resp.result()});
}
getTokenSupply
- Returns the total supply of an SPL Token type
Params: (pubkey: Pubkey, options: GetTokenSupplyOptions)
Options
const GetTokenSupplyOptions = struct {
commitment: ?types.Commitment = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var mintPubkey = try Pubkey.fromString(
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
);
var resp = try client.getTokenSupply(mintPubkey, .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("token supply: {any}", .{resp.result()});
}
getTransaction
- Returns transaction details for a confirmed transaction
Params: (signature: []const u8, options: GetTransactionOptions)
Options
const GetTransactionOptions = struct {
commitment: ?types.Commitment = null,
maxSupportedTransactionVersion: u8 = 0,
/// NOTE: must be Json for now
encoding: types.Encoding = .Json,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var txSig = "5UfDuX7WXY18keiz9mZ6zKkY8JyNuLDFz2QycQcr7skRkgVaNmo6tgFbsePRrX5C6crvycJ2A3txSdGgjPHvPbTZ";
var resp = try client.getTransaction(txSig, .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("transaction: {any}", .{resp.result()});
}
getTransactionCount
- Returns the current Transaction count from the ledger
Params: (options: GetTransactionOptions)
Options
const GetTransactionCountOptions = struct {
commitment: ?types.Commitment = null,
minContextSlot: ?u64 = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getTransactionCount(.{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("transaction count: {any}", .{resp.result()});
}
getVersion
- Returns the current Solana version running on the node
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.getVersion();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("version: {any}", .{resp.result()});
}
getVoteAccounts
- Returns the account info and associated stake for all the voting accounts in the current bank
Params: (options: GetVoteAccountsOptions)
Options
const GetVoteAccountsOptions = struct {
commitment: ?types.Commitment = null,
votePubkey: ?Pubkey = null,
keepUnstakedDelinquents: ?bool = false,
delinquentSlotDistance: ?u64 = 0,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var votePubkey = try Pubkey.fromString(
"CertusDeBmqN8ZawdkxK5kFGMwBXdudvWHYwtNgNhvLu",
);
var resp = try client.getVoteAccounts(.{ .votePubkey = votePubkey });
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("vote accounts: {any}", .{resp.result()});
}
isBlockhashValid
- Returns whether a blockhash is still valid or not
Params: (blockhash: []const u8, options: IsBlockhashValidOptions)
Options
pub const IsBlockhashValidOptions = struct {
commitment: ?types.Commitment = null,
minContextSlot: ?u64 = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.isBlockhashValid("AaPs8sYJjnDLMMAADYj2fPyDyNzp9to9v4J6c5gevxpX", .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("blockhash valid: {any}", .{resp.result()});
}
minimumLedgerSlot
- Returns the lowest slot that the node has information about in its ledger
Params: None
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.minimumLedgerSlot();
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("minimum ledger slot: {any}", .{resp.result()});
}
requestAirdrop
- Requests an airdrop of lamports to a Pubkey
Params: (pubkey: Pubkey, lamports: u64, options: RequestAirdropOptions)
Options
const RequestAirdropOptions = struct {
commitment: ?types.Commitment = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var pubkey = try Pubkey.fromString(
"Bvg7GuhqwNmV2JVyeZjhAcTPFqPktfmq25VBaZipozda",
);
var resp = try client.requestAirdrop(pubkey, 10000, .{});
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("airdrop result: {any}", .{resp.result()});
}
sendTransaction
- Submits a signed transaction to the cluster for processing
NOTE: This method does not alter the transaction in any way; it relays the transaction created by clients to the node as-is.
If the node's rpc service receives the transaction, this method immediately succeeds, without waiting for any confirmations. A successful response from this method does not guarantee the transaction is processed or confirmed by the cluster.
While the rpc service will reasonably retry to submit it, the transaction could be rejected if transaction's recent_blockhash expires before it lands.
Use getSignatureStatuses to ensure a transaction is processed and confirmed.
Before submitting, the following preflight checks are performed:
The transaction signatures are verified The transaction is simulated against the bank slot specified by the preflight commitment. On failure an error will be returned. Preflight checks may be disabled if desired. It is recommended to specify the same commitment and preflight commitment to avoid confusing behavior. The returned signature is the first signature in the transaction, which is used to identify the transaction (transaction id). This identifier can be easily extracted from the transaction data before submission.
Params: (encoded: []const u8)
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.sendTransaction(
"4hXTCkRzt9WyecNzV1XPgCDfGAZzQKNxLXgynz5QDuWWPSAZBZSHptvWRL3BjCvzUXRdKvHL2b7yGrRQcWyaqsaBCncVG7BFggS8w9snUts67BSh3EqKpXLUm5UMHfD7ZBe9GhARjbNQMLJ1QD3Spr6oMTBU6EhdB4RD8CP2xUxr2u3d6fos36PD98XS6oX8TQjLpsMwncs5DAMiD4nNnR8NBfyghGCWvCVifVwvA8B8TJxE1aiyiv2L429BCWfyzAme5sZW8rDb14NeCQHhZbtNqfXhcp2tAnaAT",
.{},
);
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("tx signature: {any}", .{resp.result()});
}
simulateTransaction
- Simulate sending a transaction
Params: (encoded: []const u8, options: SimulateTransactionOptions)
Options
const SimulateTransactionOptions = struct {
commitment: ?types.Commitment = null,
/// NOTE: must be base64 for now
encoding: types.Encoding = .Base64,
sigVerify: ?bool = null,
replaceRecentBlockhash: ?[]const u8 = null,
minContextSlot: ?u64 = null,
accounts: ?struct {
addresses: []Pubkey,
/// NOTE: must be base64 for now
encoding: types.Encoding = .Base64,
} = null,
};
Usage
const std = @import("std");
const sig = @import("sig");
const rpc = sig.rpc;
const allocator = std.heap.page_allocator;
pub fn main() !void {
var client = try rpc.Client.init(allocator, .{ .http_endpoint = HTTP_ENDPOINT });
defer client.deinit();
var resp = try client.simulateTransaction(
"AdYOLBh+RlElmqIY08YZ4OvkWzmGz5ccQLKOENWccchuSluWO7ZTy6B4x/A/WJAFvSFfUhXEcG/PZajL5EmZBQMBAAEDb3Q4CUF/hTg/MgAsYv45KRoWu+9GafjMndSktv5KzQ3fydC+bF4RL7cMFn8iCnd9sKVJp3K3PwOxVZ3agBBUWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkczsB8wv5yFAgAKUdvb4irHybi2IEEHJcAJrfdhMfgBAgIAAQwCAAAAgJaYAAAAAAA=",
.{},
);
defer resp.deinit();
if (resp.err()) |err| {
std.log.err("error response: {any}", .{err});
return;
}
std.log.debugf("simulate tx info: {any}", .{resp.result()});
}