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?)
| Field | Type | Default | Purpose |
|---|---|---|---|
network | "testnet" | "mainnet" | "testnet" | Stellar network the oracle contract is deployed on |
attestationUrl | string | https://api.noeracle.org | Override the attestation service base URL |
contractId | string | — | Default oracle contract id, used when toUpdateOp is called with none |
freshnessLimitSeconds | number | 2 | Maximum 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 responseAssetUnavailableError— requested asset not in the current snapshotStalePriceError— any returned attestation is older thanfreshnessLimitSecondsat 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.
| Member | Type | Purpose |
|---|---|---|
attestations | Attestation[] | Raw signed messages, one per requested asset |
prices | PriceEntry[] | Decoded prices |
price(asset) | (asset: string) => PriceEntry | Look up the decoded price for one asset |
toUpdateOp(contractId?) | (id?: string) => xdr.Operation | Build 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.
| Class | When thrown |
|---|---|
AttestationServiceError | Network / non-2xx / malformed response from the attestation service |
AssetUnavailableError | Requested asset is not in the snapshot |
StalePriceError | A returned attestation is older than freshnessLimitSeconds |
InconsistentRoundError | Attestations in a single Fresh don't share one round (should not happen via fetchLatest) |