A multi-source price feed for the Nockchain ecosystem. Prices are pulled from public venues, aggregated to a median inside a Hoon kernel running on the NockApp runtime, and served as JSON with every input disclosed — so any consumer can re-run the aggregation and check the number.
Coverage: NOCK and PRL as first-class pairs (per-venue, multi-source), plus ~49 liquid majors for reference. 51 pairs from ~5 upstream requests per minute, all free public APIs, no keys.
Public instance: https://nockoracle.xyz — try /price/nock-usd.
GET /prices all pairs
GET /price/<pair> one pair, e.g. /price/nock-usd
GET /funding donation wallet balance and anchoring runway
GET /anchors daily on-chain anchors: sha-256, txid, data snapshot
GET /snapshots/<f> the exact price set a given anchor hashed
GET /api endpoint and pair index (JSON; / serves the web page)
{
"pair": "nock-usd",
"price": 0.02031,
"method": "median",
"sources": [
{ "source": "coingecko", "price": 0.02027908, "ts": 1782948684 },
{ "source": "kraken", "price": 0.02031, "ts": 1782948684 },
{ "source": "dexscreener", "price": 0.02069, "ts": 1782948684 }
],
"live_sources": 3,
"updated": 1782948684,
"stale": false
}Pair ids are lowercase <ticker>-usd. Unknown pairs return 404. stale is
true when no source has reported for over 300 seconds.
The Rust wrapper is plumbing; the Hoon kernel is the authority.
- A fetch driver polls the venues every 60 s and pokes each observation into
the kernel as
[%observe pair source price ts](prices fixed-point 1e8). - The kernel keeps one observation per source per pair (newer reports replace older ones), evicts sources unseen for 300 s, and recomputes the median (mean of the two middle values when the count is even).
- The HTTP layer answers by peeking kernel state. Nothing is served that the kernel did not compute.
The computation is deterministic from the disclosed inputs: sort the sources
array from any response by price and take the middle — you get price.
| Venue | Feeds | Notes |
|---|---|---|
| DexScreener | NOCK | deepest-liquidity Base pool |
| Kraken | NOCK | NOCKUSD last trade |
| CoinGecko (simple price) | NOCK + majors | one batched call |
| CoinGecko (tickers) | PRL | per-venue: SafeTrade, CoinEx, BigONE, … each a separate source; tickers flagged stale/anomalous by CoinGecko are skipped |
| Binance | majors | one batched call |
Honesty note: CoinGecko's simple price is itself an aggregate that already
includes venues we also query directly, so the majors are reference-grade
(two partially-correlated sources), while NOCK and PRL are genuinely
multi-venue. live_sources in every response tells you which case you are
looking at. New PRL venue listings join the median automatically.
This service is value-added aggregation with sources credited per response — not raw data resale.
Nockchain fees are per word of transaction data: 16,384 nicks (0.25 NOCK) per seed word, witness words at a quarter rate, so cost scales with payload size, not with computation. We measured the real numbers on a fakenet with the actual wallet planner rather than trusting documentation:
plain send: seed_words=13 witness_words=62 fee=3,648 nicks
with 49-byte payload: seed_words=21 witness_words=56 fee=4,480 nicks
A 49-byte data entry costs 1 + ceil(49/8) = 8 extra seed words, exactly as
the fee code predicts. Translated to mainnet constants, one data-carrying
transaction costs 8.5 NOCK (measured on mainnet: 557,056 nicks). Which means:
| Cadence | Cost/month |
|---|---|
| every 5 minutes | ~$1,500 — not viable |
| hourly | ~$130 — not viable for a free feed |
| daily anchor | ~$5 — planned |
So the design is: the live feed stays off-chain and free, and a single daily commitment — a hash of the published price set — anchors it on-chain for tamper-evidence. Anyone can hash the served data and compare it with the anchored note. The commitment payload is versioned and reserves a slot for a succinct proof, so if app-level proving ships on Nockchain, it slots in without a redesign.
The stock nockchain-wallet cannot attach arbitrary note-data to an output;
tools/nockchain-wallet-note-data.patch
adds an opt-in NOCK_NOTE_DATA=key:hex environment variable to create-tx
for that purpose.
Prerequisites: the Nockchain toolchain built from the
monorepo (cargo install --path crates/nockup and crates/hoonc). The pinned nightly in
rust-toolchain.toml is required — nockvm uses feature gates that stable
rejects.
# from the directory containing this project
nockup project build nock-oracle
# or directly
cargo build --release
hoonc hoon/app/app.hoon # writes out.jam
# run (reads ./out.jam; binds 127.0.0.1)
./target/release/nock-oracleThe port is HTTP_PORT, else NOCKD_APP_PORT, else 8087. Tests:
cargo test --release. On virtualized CPUs without an invariant TSC the
binary sets TRACY_NO_INVARIANT_CHECK=1 for itself; export it manually when
running hoonc.
nockvmneeds the pinned nightly (#![feature(cold_path)]); project templates omitrust-toolchain.toml, so builds fail on stable.- The Tracy profiler compiled into the runtime aborts on CPUs without an
invariant TSC (most cloud VMs).
TRACY_NO_INVARIANT_CHECK=1is the escape hatch — and it is not inherited by non-interactive shells, so set it in-process if your supervisor cannot inject environment. poke_sync/peek_syncpanic inside a tokio runtime. The supported pattern is IO drivers:make_driver(|handle| …),handle.poke/peek, andapp.run()to drive them.- The API at your pinned rev is not the API at HEAD. Read the sources cargo
actually builds (
~/.cargo/git/checkouts/…/<rev>/), not the repo tip. noun-serdeat rev336f744prints debug lines to stdout from its bool, Option, HashMap and Result decoders. Unwrap Hoon units by hand and decode only clean types (u64, String, tuples, Vec).hoonckeeps global state in~/.nockapp/hoonc; two concurrent instances corrupt its event log. Never parallelize kernel builds.- Wallet CLI: global flags go before the subcommand; pass
--fakenetor a fakenet node's coinbase notes appear as zero balance; balances go through the node's private gRPC;create-txwrites./txs/<name>.txrather than printing the transaction.
Donations in $NOCK fund the daily on-chain anchors and the server:
9WzHyhnanLweqrPJe3KzKNsU8srmzjkXE2oiKZpV1BecK3XuPXS3Ges
(also shown with a QR on the web page). The /funding endpoint reports the
wallet balance and how many days of anchoring it covers.
MIT