SDK Reference: Solana Client
This page provides a reference for SolanaClient, the TypeScript SDK interface for reading from and writing to Solana programs. It covers the client class, all exported helper functions, and the chain selector reference for Solana networks.
Client instantiation
Instantiate SolanaClient with the bigint chain selector for the Solana network you are targeting.
import { SolanaClient } from "@chainlink/cre-sdk"
// Solana Mainnet
const client = new SolanaClient(124615329519749607n)
// Or use the supported chain selectors constant
const client = new SolanaClient(SolanaClient.SUPPORTED_CHAIN_SELECTORS["solana-mainnet"])
Static constants
| Constant | Type | Value |
|---|---|---|
SolanaClient.CAPABILITY_ID | string | "solana@1.0.0" |
SolanaClient.CAPABILITY_NAME | string | "solana" |
SolanaClient.CAPABILITY_VERSION | string | "1.0.0" |
SolanaClient.SUPPORTED_CHAIN_SELECTORS["solana-mainnet"] | bigint | 124615329519749607n |
SolanaClient.SUPPORTED_CHAIN_SELECTORS["solana-devnet"] | bigint | 16423721717087811551n |
Write methods
writeReport()
Submits a cryptographically signed report to a Solana program via the Keystone Forwarder. This is the primary method for writing data onchain from a CRE workflow. In practice, you call this indirectly through generated binding methods (writeReportFrom<StructName>()), which handle Borsh encoding and account hashing for you.
Signature:
writeReport(
runtime: Runtime<unknown>,
input: SolanaWriteCreReportRequest | SolanaWriteCreReportRequestJson
): { result: () => WriteReportReply }
SolanaWriteCreReportRequestJson
The plain-object form accepted by writeReport. Generated binding methods build this internally.
| Field | Type | Required | Description |
|---|---|---|---|
receiver | string | Yes | Hex-encoded 32-byte program ID of the receiver program |
remainingAccounts | AccountMetaJson[] | Yes | Ordered list of accounts required by the forwarder and receiver |
report | Report | Yes | The signed report returned by runtime.report() |
computeConfig | ComputeConfigJson | No | Optional compute budget configuration |
AccountMetaJson
| Field | Type | Required | Description |
|---|---|---|---|
publicKey | string | Yes | Base64-encoded 32-byte public key |
isWritable | boolean | No | Whether the account is writable (default: false) |
Use solanaAccountMetasToJson() to convert SolanaAccountMeta[] to this format.
ComputeConfigJson
| Field | Type | Required | Description |
|---|---|---|---|
computeUnitLimit | string | No | Maximum compute units for the transaction (default: 290000) |
WriteReportReply
| Field | Type | Description |
|---|---|---|
txStatus | SolanaTxStatus | TX_STATUS_SUCCESS, TX_STATUS_ABORTED, or TX_STATUS_FATAL |
txSignature | Uint8Array | Transaction signature bytes (optional) |
errorMessage | string | Error message if the transaction failed (optional) |
Usage example
The low-level call, shown for reference. In most workflows, use a generated binding instead.
import {
SolanaClient,
solanaAccountMeta,
solanaAccountMetasToJson,
calculateAccountsHash,
encodeForwarderReport,
prepareSolanaReportRequest,
bytesToHex,
solanaAddressToBytes,
type Runtime,
} from "@chainlink/cre-sdk"
const client = new SolanaClient(124615329519749607n)
const forwarderStateBytes = solanaAddressToBytes("ForwarderStateBase58...")
const forwarderAuthBytes = solanaAddressToBytes("ForwarderAuthBase58...")
const reportStateBytes = solanaAddressToBytes("ReportStateBase58...")
const remainingAccounts = [
solanaAccountMeta(forwarderStateBytes, false),
solanaAccountMeta(forwarderAuthBytes, false),
solanaAccountMeta(reportStateBytes, true),
]
// 1. Borsh-encode your payload (generated bindings do this automatically)
const payload: Uint8Array = borshEncode({ price: 500000n, timestamp: BigInt(Date.now()) })
// 2. Generate a signed report
const report = runtime
.report(
prepareSolanaReportRequest(
encodeForwarderReport({
accountHash: calculateAccountsHash(remainingAccounts),
payload,
})
)
)
.result()
// 3. Submit the report
const result = client
.writeReport(runtime, {
receiver: bytesToHex(solanaAddressToBytes("ReceiverProgramBase58...")),
remainingAccounts: solanaAccountMetasToJson(remainingAccounts),
report,
computeConfig: { computeUnitLimit: "290000" },
})
.result()
Read methods
SolanaClient exposes read methods for fetching consensus-verified data from Solana accounts and programs, served by a ContractReader on the Solana capability DON. There is no generated per-account "fetch" helper — you call these directly, then decode the result with the generated decode<AccountName>Account() function for your account type.
SolanaClient.getAccountInfoWithOpts()
Fetches a single account's info, including its raw data.
Signature:
getAccountInfoWithOpts(
runtime: Runtime<unknown>,
input: GetAccountInfoWithOptsRequest | GetAccountInfoWithOptsRequestJson
): { result: () => GetAccountInfoWithOptsReply }
GetAccountInfoWithOptsRequestJson
| Field | Type | Required | Description |
|---|---|---|---|
account | string | Yes | Base64-encoded 32-byte account public key. Use bytesToBase64(solanaAddressToBytes(base58Address)) to build it from a base58 address. |
opts | GetAccountInfoOptsJson | No | Encoding, commitment, and slicing options. |
GetAccountInfoOptsJson
| Field | Type | Description |
|---|---|---|
encoding | EncodingTypeJson | "ENCODING_TYPE_BASE58" (accounts under 129 bytes only), "ENCODING_TYPE_BASE64" (any size), "ENCODING_TYPE_BASE64_ZSTD", "ENCODING_TYPE_JSON_PARSED", or "ENCODING_TYPE_JSON". |
commitment | CommitmentTypeJson | "COMMITMENT_TYPE_FINALIZED", "COMMITMENT_TYPE_CONFIRMED", or "COMMITMENT_TYPE_PROCESSED". |
dataSlice | DataSliceJson | Optional {offset, length} window to fetch only part of the account data. |
minContextSlot | string | Optional lower-bound slot for the read. |
GetAccountInfoWithOptsReply
The value returned by .result(). Unlike the request, this comes back with real typed fields (not the ...Json
form) — byte fields are Uint8Array, not base64 strings.
| Field | Type | Description |
|---|---|---|
value | Account | The account, or undefined if it does not exist. |
Account
| Field | Type | Description |
|---|---|---|
lamports | bigint | Balance in lamports. |
owner | Uint8Array | 32-byte program ID that owns the account. |
data | DataBytesOrJSON | Account data, a oneof: data.body is {case: "raw", value: Uint8Array} or {case: "json", value: Uint8Array} depending on the requested encoding. |
executable | boolean | true if this is a program account. |
rentEpoch | bigint | Next rent epoch. |
space | bigint | Data length in bytes. |
Usage: see the Onchain Read guide for a full,
step-by-step example, including decoding the returned bytes with a generated decode<AccountName>Account().
Other read methods
SolanaClient also exposes these lower-level read methods, following the same (runtime, input): { result: () => XReply } shape:
| Method | Description |
|---|---|
getBalance() | Lamport balance of an account. |
getBlock() | A block's contents at a given slot. |
getMultipleAccountsWithOpts() | getAccountInfoWithOpts(), batched for multiple accounts. |
getProgramAccounts() | All accounts owned by a program, with optional filters. |
getSignatureStatuses() | Confirmation status for one or more transaction signatures. |
getSlotHeight() | The current slot height. |
getTransaction() | A confirmed transaction's details, given its signature. |
getFeeForMessage() | The fee a compiled message would cost. |
Helper functions
These functions are exported from @chainlink/cre-sdk and used when building Solana write requests, either directly or through generated bindings.
solanaAccountMeta()
Builds an account entry for the remainingAccounts list.
Signature:
function solanaAccountMeta(publicKey: Uint8Array | string, isWritable?: boolean): SolanaAccountMeta
Parameters:
publicKey: The 32-byte public key as raw bytes or a base58-encoded stringisWritable: Whether the account is writable. Defaults tofalse.
Usage:
import { solanaAccountMeta } from "@chainlink/cre-sdk"
// From a base58 string
const account = solanaAccountMeta("ECL8142j2YQAvs9R9geSsRnkVH2wLEi7soJCRyJ74cfL", true)
// From raw bytes
const account = solanaAccountMeta(rawBytes, false)
solanaAddressToBytes()
Converts a base58-encoded Solana address to its raw 32-byte representation.
Signature:
function solanaAddressToBytes(base58Address: string): Uint8Array
Usage:
import { solanaAddressToBytes } from "@chainlink/cre-sdk"
const bytes = solanaAddressToBytes("ECL8142j2YQAvs9R9geSsRnkVH2wLEi7soJCRyJ74cfL")
// → Uint8Array(32)
solanaAccountMetasToJson()
Converts SolanaAccountMeta[] to the AccountMetaJson[] shape expected by SolanaClient.writeReport(). Generated bindings call this internally.
Signature:
function solanaAccountMetasToJson(accounts: ReadonlyArray<SolanaAccountMeta>): AccountMetaJson[]
calculateAccountsHash()
Computes the SHA-256 hash of the concatenated public keys of the given accounts. This hash is embedded in the report payload and verified on-chain by the Keystone Forwarder.
Signature:
function calculateAccountsHash(accounts: ReadonlyArray<SolanaAccountInput | null | undefined>): Uint8Array
The hash is computed over the raw 32-byte public keys in the order provided. Account order matters: swapping two accounts produces a different hash.
Usage:
import { calculateAccountsHash, solanaAccountMeta } from "@chainlink/cre-sdk"
const accounts = [
solanaAccountMeta(forwarderState, false),
solanaAccountMeta(forwarderAuthority, false),
solanaAccountMeta(reportState, true),
]
const accountHash = calculateAccountsHash(accounts)
// → Uint8Array(32) [SHA-256 of concatenated public keys]
encodeForwarderReport()
Borsh-encodes a ForwarderReport struct for the Keystone Forwarder program. The encoding format is [32-byte accountHash][u32-LE payload length][payload bytes].
Signature:
function encodeForwarderReport(report: ForwarderReport): Uint8Array
interface ForwarderReport {
accountHash: Uint8Array // must be exactly 32 bytes
payload: Uint8Array // your Borsh-encoded struct
}
Usage:
import { encodeForwarderReport, calculateAccountsHash, solanaAccountMeta } from "@chainlink/cre-sdk"
const encoded = encodeForwarderReport({
accountHash: calculateAccountsHash(remainingAccounts),
payload: borshEncodedPayload,
})
prepareSolanaReportRequest()
Prepares a ReportRequestJson for runtime.report() using the Solana default encoder (solana / ecdsa / keccak256). Pass the result directly to runtime.report().
Signature:
function prepareSolanaReportRequest(payload: Uint8Array, reportEncoder?: ReportEncoder): ReportRequestJson
Parameters:
payload: The encoded payload bytes — typically the output ofencodeForwarderReport()reportEncoder: Optional. Defaults toSOLANA_DEFAULT_REPORT_ENCODER
Usage:
import { prepareSolanaReportRequest, encodeForwarderReport } from "@chainlink/cre-sdk"
const reportRequest = prepareSolanaReportRequest(encodeForwarderReport({ accountHash, payload }))
const report = runtime.report(reportRequest).result()
SOLANA_DEFAULT_REPORT_ENCODER
The default encoder configuration for Solana write operations.
const SOLANA_DEFAULT_REPORT_ENCODER = {
encoderName: "solana",
signingAlgo: "ecdsa",
hashingAlgo: "keccak256",
}
Pass to prepareSolanaReportRequest() to override encoding parameters.
encodeBorshVecU32()
Encodes a Vec<Bytes> in Borsh format: [u32-LE element count][concatenated element payloads]. Use this when your receiver program's on_report accepts a Vec<T> of items.
Signature:
function encodeBorshVecU32(elementPayloads: ReadonlyArray<Uint8Array>): Uint8Array
Usage:
import { encodeBorshVecU32 } from "@chainlink/cre-sdk"
const vec = encodeBorshVecU32([item1Bytes, item2Bytes, item3Bytes])
Generated binding methods ending in s (e.g., writeReportFromPriceDatas()) use this internally to encode arrays.
Chain selectors
| Network | String Name | Numeric ID |
|---|---|---|
| Solana Mainnet | solana-mainnet | 124615329519749607 |
| Solana Devnet | solana-devnet | 16423721717087811551 |
In your workflow config (e.g., config.staging.json), store the numeric ID as a string to avoid JSON precision loss, then convert with BigInt():
{
"chainSelector": "124615329519749607"
}
const client = new SolanaClient(BigInt(config.chainSelector))
Related resources
- Solana Read & Write Capabilities: Architecture reference and account layout
- Generating Solana Bindings: How to generate typed binding classes from your Anchor IDL
- Reading from Solana guide: Step-by-step tutorial
- Writing to Solana guide: Step-by-step tutorial
- Solana Log Trigger reference: Filter configuration and payload fields
- Supported Networks: Chain selector values for all supported networks