v0.3.0TypeScriptMIT

s0nar SDK

Read Solana network health from on-chain oracle accounts. s0nar-sdk wraps oracle accounts into typed objects and exposes read methods, instruction builders, event listeners, PDA helpers, and score utilities.

Package: s0nar-sdkPeer dep: @solana/web3.jsView on npm ↗

Install

shell
pnpm add s0nar-sdk @solana/web3.js

A wallet is optional — only required when composing write transactions.

Quick start

typescript
import { Connection } from "@solana/web3.js";
import { createS0narClient } from "s0nar-sdk";

const connection = new Connection("https://api.devnet.solana.com");
const client = createS0narClient({ connection });

const health = await client.getNetworkHealth();

console.log(health.healthScore);         // 0–100
console.log(health.tpuReachabilityPct);  // validator reachability %
console.log(health.avgSlotLatencyMs);    // slot propagation latency
console.log(health.agaveCount);          // validator client diversity
Client diversity counts and stake-weighted reach are returned on NetworkHealth, RegionScore, and Attestation.

Client

typescript
const client = createS0narClient({
  connection,   // required — Solana RPC connection
  programId,    // optional — defaults to s0nar devnet program
  wallet,       // optional — needed for instruction builders
});
OptionTypeRequiredDescription
connectionConnectionYesSolana RPC connection.
programIdPublicKeyNoOverride the default s0nar devnet program ID.
walletWalletNoAnchor wallet for instruction builders.

Read methods

MethodReturnsDescription
getNetworkHealth()Promise<NetworkHealth>Global score, latency, reachability, and per-region scores.
getRegistry()Promise<Registry>Program authority, observer counts, stake config, and pause state.
getObserver(pubkey)Promise<Observer>Single observer account by wallet public key.
getAllObservers()Promise<Observer[]>All observer accounts via getProgramAccounts.
getObserversByRegion(region)Promise<Observer[]>Observer accounts filtered by Region enum.

Read methods perform direct RPC account reads and return plain TypeScript objects. For production UIs, wrap reads in retry and cache logic.

Types

NetworkHealth
FieldTypeDescription
healthScorenumberGlobal 0–100 health score.
tpuReachabilityPctnumberPercent of probed TPU endpoints reachable.
avgSlotLatencyMsnumberAverage slot propagation latency in ms.
activeObserverCountnumberObservers included in the current score.
activeRegionCountnumberRegions with active data.
lastUpdatedSlotbigintSlot of the last score update.
lastUpdatedTsbigintUnix timestamp of the last score update.
totalAttestationsbigintLifetime submitted attestations.
regionScoresRegionScore[]Per-region score breakdown.
minHealthEvernumber | nullLowest global score observed.
maxHealthEvernumberHighest global score observed.
agaveCountnumberNetwork-wide Agave validators seen.
firedancerCountnumberNetwork-wide Firedancer validators seen.
jitoCountnumberNetwork-wide Jito validators seen.
solanaLabsCountnumberNetwork-wide Solana Labs validators seen.
otherCountnumberNetwork-wide other-client validators seen.
RegionScore
FieldTypeDescription
regionRegionRegion enum value.
observerCountnumberObserver contributions in this aggregate.
healthScorenumberRegional 0-100 health score.
reachabilityPctnumberRegional TPU reachability percent.
avgRttUsnumberAverage RTT in microseconds.
slotLatencyMsnumberSlot propagation latency in ms.
agaveCountnumberAgave validators seen in this region.
firedancerCountnumberFiredancer validators seen in this region.
jitoCountnumberJito validators seen in this region.
solanaLabsCountnumberSolana Labs validators seen in this region.
otherCountnumberOther-client validators seen in this region.
reachableStakePctnumberStake-weighted reachability for this region.
Observer
FieldTypeDescription
publicKeyPublicKeyObserver account address.
authorityPublicKeyWallet authorized to report.
regionRegionObserver region enum value.
stakeLamportsbigintRegistered stake amount.
lastAttestationSlotbigintLatest submitted attestation slot.
attestationCountbigintTotal attestations submitted.
latestAttestationAttestationLatest measurement payload.
isActivebooleanWhether the observer is active.
Attestation
FieldTypeDescription
slotbigintSolana slot measured.
timestampbigintMeasurement timestamp.
avgRttUsnumberAverage RTT in microseconds.
p95RttUsnumberP95 RTT in microseconds.
slotLatencyMsnumberSlot propagation latency in ms.
tpuReachablenumberReachable validators probed.
tpuProbednumberTotal validators probed.
agaveCountnumberAgave validators seen.
firedancerCountnumberFiredancer validators seen.
jitoCountnumberJito validators seen.
solanaLabsCountnumberSolana Labs validators seen.
otherCountnumberOther-client validators seen.
reachableStakePctnumberReachable stake share.
Registry
FieldTypeDescription
authorityPublicKeyProgram authority.
pendingAuthorityPublicKey | nullIn-progress authority transfer target.
minStakeLamportsbigintMinimum observer stake to register.
observerCountnumberTotal registered observers.
activeCountnumberCurrently active observers.
maxObserversnumberRegistry capacity.
pausedbooleanWhether writes are paused.
versionnumberRegistry schema version.

Helpers

FunctionReturnsDescription
healthStatus(health, currentSlot?)"healthy" | "degraded" | "critical" | "stale"Human-readable health state.
isStale(health, currentSlot)booleanTrue when oracle data is older than 150 slots.
isObserverStale(observer, currentSlot)booleanTrue when an observer has not reported recently.
isDegraded(health, threshold?)booleanTrue when score is below threshold (default 70).
regionLabel(region)stringUI label for a Region enum value.
lamportsToSol(lamports)numberConverts bigint lamports to SOL.
latencyScore(slotLatencyMs)numberComputes the latency component of the score formula.
isConsensusCritical(reachableStakePct)booleanTrue when stake reach is below the 67% finality threshold.
stakeReachStatus(reachableStakePct)"healthy" | "degraded" | "critical"Classifies stake-weighted reachability.
dominantClient(region)"agave" | "firedancer" | "jito" | "other"Returns the largest validator client count in a region.
clientDiversityIndex(region)number0-100 score; higher means a more even client distribution.

Score formula

healthScore = (reachabilityPct × 0.70) + (latencyScore × 0.30)

latencyScore = max(0, (400 − slotLatencyMs) × 100 / 400)

Events

typescript
const id = client.onAttestationSubmitted((event, slot) => {
  console.log(event.observer.toBase58(), event.score, slot);
});

await client.removeEventListener(id);
MethodEvent type
onAttestationSubmitted(cb)AttestationSubmittedEvent
onObserverRegistered(cb)ObserverRegisteredEvent
onObserverDeregistered(cb)ObserverDeregisteredEvent
onObserverSlashed(cb)ObserverSlashedEvent
onConfigUpdated(cb)ConfigUpdatedEvent
removeEventListener(id)Promise<void>

Instruction builders

All builders return Promise<TransactionInstruction>. Compose the instruction into your own transaction and signing flow.

BuilderCallerDescription
registerObserver(observer, region)New observerRegister a new observer with a region.
submitAttestation(authority, params)Existing observerSubmit a new attestation payload.
deregisterObserver(caller, observerWallet)Observer or authorityRemove an observer from the registry.
crankAggregation(cranker, observerAccounts)AnyoneAggregate observer scores on-chain.
initialize(authority, minStakeLamports, maxObservers)AuthorityFirst-time program setup.
slashObserver(authority, observerWallet, treasury, slashBps)AuthoritySlash an observer's stake by basis points.
updateConfig(authority, params)AuthorityUpdate program configuration.
proposeAuthority(authority, newAuthority)AuthorityInitiate a two-step authority transfer.
acceptAuthority(newAuthority)New authorityConfirm a pending authority transfer.
Two-step transfer: call proposeAuthority first, then acceptAuthority from the new authority wallet to confirm.

PDAs & regions

HelperReturns
getRegistryPDA(programId?)[PublicKey, number]
getNetworkHealthPDA(programId?)[PublicKey, number]
getObserverPDA(observer, programId?)[PublicKey, number]

Region enum

Region.AsiaRegion.USRegion.EURegion.SouthAmericaRegion.AfricaRegion.OceaniaRegion.Other