Skip to main content

SDK reference

@noeracle/sdk — the TypeScript client for Noeracle.

Package: @noeracle/sdk on npm.

Install

npm install @noeracle/sdk @stellar/stellar-sdk

Quickstart

import { Noeracle } from "@noeracle/sdk";

const oracle = new Noeracle({ network: "testnet" });

// Fetch a freshly signed price.
const fresh = await oracle.fetchLatest(["BTC/USD"]);

// Prepend the verification op, then your own application op(s).
tx.addOperation(fresh.toUpdateOp(ORACLE_CONTRACT_ID));
tx.addOperation(myContract.call("open_position" /* , ... */));

Asset names follow the "BASE/QUOTE" convention (e.g. "BTC/USD", "ETH/USD").

new Noeracle(config?)

FieldTypeDefaultPurpose
network"testnet" | "mainnet""testnet"Stellar network the oracle contract is deployed on
attestationUrlstringhttps://api.noeracle.orgOverride the attestation service base URL
contractIdstringDefault oracle contract id, used when toUpdateOp is called with none
freshnessLimitSecondsnumber2Maximum age (in seconds) of a fetched attestation before fetchLatest throws StalePriceError

fetchLatest(assets)

oracle.fetchLatest(assets: string[]): Promise<Fresh>

Fetches the latest signed attestation for each requested asset from a single consistent snapshot. All returned attestations share one round.

Throws:

  • AttestationServiceError — service unreachable or non-2xx response
  • AssetUnavailableError — requested asset not in the current snapshot
  • StalePriceError — any returned attestation is older than freshnessLimitSeconds at fetch

subscribe(assets, onUpdate, onError?)

oracle.subscribe(
assets: string[],
onUpdate: (fresh: Fresh) => void,
onError?: (err: NoeracleError) => void,
): Subscription

Opens an SSE connection that delivers a Fresh for the requested assets each time the attestation service signs a new round (~500 ms cadence on testnet). Reconnects automatically on transient errors. This is the Pattern C integration.

const sub = oracle.subscribe(
["BTC/USD"],
(fresh) => console.log(fresh.price("BTC/USD").priceHuman),
);

// Later, stop the stream:
sub.close();

Subscription

interface Subscription {
close(): void;
}

Fresh

Returned by fetchLatest. Carries the raw signed attestations and the helpers for building Soroban operations.

MemberTypePurpose
attestationsAttestation[]Raw signed messages, one per requested asset
pricesPriceEntry[]Decoded prices
price(asset)(asset: string) => PriceEntryLook up the decoded price for one asset
toUpdateOp(contractId?)(id?: string) => xdr.OperationBuild the standalone update_batch_ed25519_args operation — Pattern A
updateArgs()() => xdr.ScVal[]The six ScVal arguments for in-contract verification

updateArgs() returns [assets, prices, timestamp, round_id, pubkey, sigs]. Spread into your own contract call when using Pattern B.

PriceEntry

type PriceEntry = {
asset: string; // e.g. "BTC/USD"
price: bigint; // i128 scaled by 1e7
priceHuman: number; // decoded float
timestamp: number; // unix seconds
roundId: number; // monotonic per-asset
sources: number; // exchanges aggregated
};

Attestation

The raw signed attestation, exactly as served by the attestation service.

type Attestation = {
asset: string; // display name, e.g. "BTC/USD"
tag: string; // 8-byte on-chain asset tag, hex — e.g. "4254435553440000".
// Pass to a Soroban consumer's `BytesN<8>` field when validating.
price: string; // i128 scaled by 1e7, as decimal string
price_human: number;
timestamp: number; // unix seconds
round_id: number;
sources: number;
publisher: string; // Ed25519 public key, 32-byte hex
message: string; // signed 40-byte payload, hex
signature: string; // Ed25519 signature, 64-byte hex
};

The asset field is the human-readable display name the SDK accepts as input; the tag field is the 8-byte identifier the on-chain contract sees in the signed message. They are not interchangeable — for BTC/USD the display is "BTC/USD" but the on-chain tag is "4254435553440000" (= b"BTCUSD\0\0"). See Asset tags.

Errors

All errors extend NoeracleError.

ClassWhen thrown
AttestationServiceErrorNetwork / non-2xx / malformed response from the attestation service
AssetUnavailableErrorRequested asset is not in the snapshot
StalePriceErrorA returned attestation is older than freshnessLimitSeconds
InconsistentRoundErrorAttestations in a single Fresh don't share one round (should not happen via fetchLatest)

Source

noeracle/noeracle · sdk/