Guides › Read prices
Option 1 — REST, the simplest
curl -s https://btcw.tech/api/price
{
"symbol": "BTCw", "chain_id": 482120, "decimals": 18,
"price_usd": 83380.39, // oracle price × peg ratio
"bid_usd": 83130.25, // OracleAMM buys your BTCw at this price
"ask_usd": 83630.53, // OracleAMM sells you BTCw at this price
"spread_pct": 0.3,
"updated_at": 1790739823, "age_seconds": 5, "max_age_seconds": 300,
"stale": false, "paused": false, "tradable": true,
"liquidity": { "btcw": 1001, "usdw": 49916961.49, "max_trade_btcw": 10 },
"oracle": { "address": "0x6E06…a96c", "decimals": 8, "sources": "median of 6: …" },
"usdw_total_supply": 122171970.27, …
}
Safe to use when stale == false and paused == false. tradable combines both conditions with liquidity.
Prices of the 200 price-tracker tokens (crypto and US stocks)
curl -s https://btcw.tech/api/v2/pools # per pool: oracleUsd, poolUsd, devBps, depthBtcw, priceAgeS…
curl -s https://btcw.tech/api/v2/swap/assets # 202 assets: address, symbol, decimals, logoURI, priceUsd
Filter by class with the class field (crypto · stock · stable). oracleUsd is the oracle price (PriceHub); poolUsd is the current pool price; devBps is the deviation between the two.
Staleness: check priceAgeS (a sensible threshold: 300 seconds).
Responses are cached for 5 seconds (cache-control: public, max-age=5) — polling more often won't return fresher data. Rate limit: 20 requests/second per IP.
Option 2 — on-chain, trust no server
BtcwPriceFeed follows the Chainlink interface, so any tool that reads Chainlink feeds can read it:
cast call 0x6E0687A5D5a5b98CC5fb05c4d8d742fBD75ba96c \
"latestRoundData()(uint80,int256,uint256,uint256,uint80)" --rpc-url https://rpc.btcw.tech
import { JsonRpcProvider, Contract } from "ethers";
const p = new JsonRpcProvider("https://rpc.btcw.tech", 482120);
const feed = new Contract("0x6E0687A5D5a5b98CC5fb05c4d8d742fBD75ba96c",
["function latestRoundData() view returns (uint80,int256,uint256,uint256,uint80)"], p);
const [, answer, , updatedAt] = await feed.latestRoundData();
const age = Math.floor(Date.now() / 1000) - Number(updatedAt);
if (age > 300) throw new Error("oracle price is stale");
console.log("BTC/USD", Number(answer) / 1e8);
From a Solidity contract on chain 482120
interface AggregatorV3Interface {
function latestRoundData() external view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}
(, int256 answer,, uint256 updatedAt,) = AggregatorV3Interface(0x6E0687A5D5a5b98CC5fb05c4d8d742fBD75ba96c).latestRoundData();
require(block.timestamp - updatedAt <= 300, "stale"); // 8 decimals
Price-tracker token prices — PriceHub
# ETHw price (18 decimals) — substitute a token address from /api/v2/swap/assets
cast call 0xE87FDdCC0b668564a20B23F3bE1EE108C805ecb4 \
"latestRoundData(address)(uint80,int256,uint256,uint256,uint80)" <token-address> --rpc-url https://rpc.btcw.tech
Several tokens at once: prices(address[]) returns two arrays, answers and updatedAts; tokens without a price return (0, 0)
(whereas latestRoundData reverts with NoData).
Watch for price changes
Instead of polling, subscribe to events over WebSocket at wss://rpc.btcw.tech/ws:
// BtcwPriceFeed: AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt)
// PriceHub: AnswerUpdated(address indexed asset, int256 answer, uint256 roundId, uint256 updatedAt)
const ws = new WebSocketProvider("wss://rpc.btcw.tech/ws", 482120);
feed.connect(ws).on("AnswerUpdated", (current) => console.log(Number(current) / 1e8));