Contracts, wrappers, and CLI tooling for running and integrating the Wit/Oracle stack on EVM-compatible networks.
- Install dependencies:
pnpm install- List supported chains:
npx witeth networks- Start a local signing gateway connected to your target network:
npx witeth gateway <ecosystem:chain>- In another terminal, inspect framework contracts in that chain:
npx witeth framework --verbose- For deployments or upgrades, use your internal deployment automation/playbook:
<run your deployment pipeline for ecosystem:chain>- Install package:
npm install @witnet/solidity- Browse subsidized feeds:
npx witeth priceFeeds- Browse randomness requests:
npx witeth randomness- Inspect oracle pull queries and pushed reports:
npx witeth queries --limit 20
npx witeth reports --limit 20 --parse- Inspect and dry-run Radon assets:
npx witeth assets --all --decode
npx witeth assets <assetName> --dry-run- Install dependencies:
npm install @witnet/solidity ethers- Instantiate wrappers from an ethers JsonRpcProvider:
import { ethers, utils } from "@witnet/solidity";
const provider = new ethers.JsonRpcProvider(process.env.ETH_RPC_URL!);
const framework = await utils.fetchWitOracleFramework(provider);
console.log(Object.keys(framework));- Build a strongly typed WitOracle wrapper:
import { WitOracle } from "@witnet/solidity";
const witOracle = await WitOracle.fromEthRpcProvider(provider);
const randomness = await witOracle._getWitRandomness();
console.log(await randomness.getEvmChainId());- Operator deep dive: docs/operator-guide.md
- Solidity deep dive: docs/solidity-guide.md
- JavaScript deep dive: docs/javascript-guide.md
- CLI appendix (examples, output shape, failures): docs/cli-appendix.md
Network-specific behavior is controlled by your network metadata, artifact mapping, and deployment specs sources of truth.
Recommended decision flow for WitOracle implementation selection:
- Start from your default implementation mapping.
- Add ecosystem override when many chains share behavior.
- Add chain-level override only when strictly needed.
- Keep deployment spec changes minimal and explicit.
Preflight:
pnpm run fmt
pnpm run compileRun selective upgrade using your internal release process for the targeted artifacts.
Run full upgrade only through your approved change-management process.
Validate upgraded state:
npx witeth gateway <ecosystem:chain>
npx witeth framework --verbose-
Add the network to your supported-network catalog using the name pattern ecosystem:chain.
-
Add artifact overrides when defaults are not enough.
-
Add deployment specs for mutables, immutables, dependencies, or libs.
-
Deploy using your approved deployment automation.
-
Verify and smoke-test:
npx witeth gateway <ecosystem:chain>
npx witeth framework --verbose
npx witeth priceFeeds
npx witeth randomnessYou can enumerate supported feeds both on-chain and from CLI.
Solidity path:
- Call
IWitPriceFeeds.lookupPriceFeeds(). - Return value is
PriceFeedInfo[], where each item includes: id: 32-byte feed id.exponent: decimals exponent for interpreting price values.symbol: human-readable caption.mapper: mapping definition when feed is derived from dependencies.oracle: oracle target and source identifiers.updateConditions: heartbeat, deviation, witness, and callback settings.lastUpdate: last knownPrice(exponent,price,deltaPrice,timestamp,trail).
CLI path:
- Run
npx witeth priceFeeds. - CLI table highlights:
ID4: 4-byte identifier used by nativeIWitPriceFeedsreads.CAPTION: price feed caption/symbol.FRESHNESS: relative age of last update (for example, "2 minutes ago").DATA PROVIDERS: upstream providers or composed dependencies used for the feed.
You can read the same subsidized feed through four compatibility paths:
- Witnet-native interface (
IWitPriceFeeds) - ERC-2362 compatibility (
IERC2362-stylevalueFor(bytes32)) - Pyth-adapted interface (
IWitPythmethods) - Chainlink-adapted interface (create adapter then consume
IWitPythChainlinkAggregator/ Chainlink V3 methods)
Methods:
getPrice(ID4 id4)getPriceNotOlderThan(ID4 id4, uint24 age)getPriceUnsafe(ID4 id4)
Arguments:
id4: 4-byte feed identifier, usually derived from caption (for example viacomputeID4("Price-ETH/USD-6")).age: max accepted staleness in seconds (getPriceNotOlderThanonly).
Possible reverts:
PriceFeedNotFound()when the feed is not supported.StalePrice()on stale updates (getPrice,getPriceNotOlderThan).InvalidGovernanceTarget()if EMA-governed conditions are unmet for the feed.
Expected return:
Pricestruct withexponent,price,deltaPrice,timestamp,trail.- Effective numeric value is typically interpreted as
price * 10^exponent.
Method:
valueFor(bytes32 id)
Arguments:
id: 32-byte feed id (typically fromcomputeID32(caption)).
Possible reverts:
- Typically no sanity-check revert for stale/missing values in this path.
- In normal operation, status codes signal health instead of reverting.
Expected return:
(int256 value, uint256 timestamp, uint256 status).- Status semantics in current implementation:
200: fresh value.400: stale value.404: feed not found / no value yet.
Methods:
getPrice(bytes32 id)getPriceNotOlderThan(bytes32 id, uint64 age)getPriceUnsafe(bytes32 id)getEmaPrice(bytes32 id)getEmaPriceNotOlderThan(bytes32 id, uint64 age)getEmaPriceUnsafe(bytes32 id)
Arguments:
id: 32-byte feed id (IWitPyth.ID, backed bybytes32).age: max accepted staleness in seconds for*NotOlderThanvariants.
Possible reverts:
PriceFeedNotFound()when feed is unsupported.StalePrice()on stale values in sanity-checked variants.InvalidGovernanceTarget()for invalid EMA/governance configuration.
Expected return:
PythPricestruct:price(int64),conf(uint64),expo(int32),publishTime(uint).Unsafevariants prioritize availability over freshness guarantees.
Flow:
- Call
IWitPriceFeeds.createChainlinkAggregator(string caption). - Use returned aggregator address through
IWitPythChainlinkAggregator(which extends Chainlink V3 interface).
Key methods after creation:
- Chainlink V3 reads:
latestRoundData(),getRoundData(uint80),decimals(),description(),version(). - Adapter metadata:
id4(),priceId(),symbol(),witOracle().
Arguments:
caption: feed caption used in WitPriceFeeds (for examplePrice-ETH/USD-6).roundId: Chainlink-compatible round selector when usinggetRoundData.
Possible reverts:
createChainlinkAggregatorreverts if caption is not supported.- Read methods may bubble up underlying feed lookup failures.
Expected return:
- Chainlink-compatible tuple from round methods:
(roundId, answer, startedAt, updatedAt, answeredInRound).answeris the price value adapted to Chainlink-style consumers.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
import { IWitPriceFeeds, IWitPriceFeedsTypes } from "@witnet/solidity/contracts/interfaces/IWitPriceFeeds.sol";
import { IWitPyth } from "@witnet/solidity/contracts/interfaces/legacy/IWitPyth.sol";
import { IWitPythChainlinkAggregator } from "@witnet/solidity/contracts/interfaces/legacy/IWitPythChainlinkAggregator.sol";
interface IERC2362 {
function valueFor(bytes32 id) external view returns (int256 value, uint256 timestamp, uint256 status);
}
contract FeedReadExamples {
IWitPriceFeeds public immutable feeds;
constructor(address feedsAddress) {
feeds = IWitPriceFeeds(feedsAddress);
}
// 1) Witnet-native
function readNative(bytes4 id4)
external
view
returns (IWitPriceFeedsTypes.Price memory checked, IWitPriceFeedsTypes.Price memory unsafe_)
{
checked = feeds.getPrice(IWitPriceFeedsTypes.ID4.wrap(id4));
unsafe_ = feeds.getPriceUnsafe(IWitPriceFeedsTypes.ID4.wrap(id4));
}
// 2) ERC-2362 compatibility
function readErc2362(bytes32 id32) external view returns (int256 value, uint256 timestamp, uint256 status) {
return IERC2362(address(feeds)).valueFor(id32);
}
// 3) Pyth-adapted compatibility
function readPyth(bytes32 id32)
external
view
returns (IWitPyth.PythPrice memory spot, IWitPyth.PythPrice memory ema)
{
IWitPyth.ID id = IWitPyth.ID.wrap(id32);
spot = feeds.getPriceNotOlderThan(id, 300);
ema = feeds.getEmaPriceUnsafe(id);
}
// 4) Chainlink-adapted compatibility
function createAndReadChainlink(string calldata caption)
external
returns (address aggregator, int256 answer, uint256 updatedAt)
{
aggregator = feeds.createChainlinkAggregator(caption);
(, answer, , updatedAt, ) = IWitPythChainlinkAggregator(aggregator).latestRoundData();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
import { IWitPythChainlinkAggregator } from "@witnet/solidity/contracts/interfaces/legacy/IWitPythChainlinkAggregator.sol";
contract FeedReadChainlinkOnly {
IWitPythChainlinkAggregator public immutable adapter;
constructor(address adapterAddress) {
adapter = IWitPythChainlinkAggregator(adapterAddress);
}
function readLatest()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)
{
return adapter.latestRoundData();
}
function metadata()
external
view
returns (bytes4 id4, bytes32 priceId, string memory symbol, address witOracle, uint8 decimals)
{
return (adapter.id4(), adapter.priceId(), adapter.symbol(), adapter.witOracle(), adapter.decimals());
}
}See the @witnet/price-feeds README:
See the @witnet/price-feeds README:
See the @witnet/price-feeds README:
Call randomize on the WitRandomness contract from your contract flow, then consume finalized entropy once available.
npx witeth randomness --target <wit_randomness_address> --randomize --signer <evm_address>
npx randomizer --target <wit_randomness_address>Pattern:
- Clone a WitRandomness instance:
npx witeth randomness --target <wit_randomness_address> --clone --signer <evm_address>- Trigger randomization by bot or by randomize calls.
- Implement IWitRandomnessConsumer callback entrypoint in your consumer contract.
Radon Request is the programmable query definition in Witnet: sources, transforms, aggregation, and commit/reveal consensus knobs.
- Solidity path: verify and refer requests from contracts in this framework.
- JavaScript path: compose assets using @witnet/sdk.
npx witeth assets --all --decode
npx witeth assets <request_or_template> --dry-run
npx witeth assets <request_or_template> --deployUse queries and reports commands to inspect pull and push workflows by RAD hash:
npx witeth queries --filter-radHash <rad_hash_fragment>
npx witeth reports --filter-radHash <rad_hash_fragment> --parseCommonly used functions:
- getNetworkTagsFromString
- fetchWitOracleFramework
- fetchEvmNetworkFromProvider
- getEvmNetworkAddresses
- getEvmNetworkByChainId
- getEvmNetworkId
- getEvmNetworkSymbol
- getEvmNetworks
- isEvmNetworkMainnet
- isEvmNetworkSupported
- abiDecodeQueryStatus
- abiEncodeDataPushReport
- abiEncodeDataPushReportMessage
- abiEncodeDataPushReportDigest
- abiEncodePriceFeedUpdateConditions
- abiEncodeWitOracleQueryParams
- abiEncodeRadonAsset
import { ethers, utils } from "@witnet/solidity";
const provider = new ethers.JsonRpcProvider(process.env.ETH_RPC_URL!);
const framework = await utils.fetchWitOracleFramework(provider);
for (const [name, artifact] of Object.entries(framework)) {
console.log(name, artifact.address, artifact.class, artifact.semVer);
}- Build invariable or parameterized Radon definitions with @witnet/sdk.
- Use CLI for decode and dry-run checks.
- Inspect trace-back for feeds, queries, and reports to validate end-to-end behavior.
- npx witeth networks
- npx witeth gateway ecosystem:chain
- npx witeth accounts
- npx witeth framework
- npx witeth assets
- npx witeth priceFeeds
- npx witeth queries
- npx witeth randomness
- npx witeth reports
- npx randomizer
- --trace-back, --parse, --randomize, --clone, --deploy, --dry-run, --decode, --verbose
- --target, --signer, --filter-radHash, --filter-requester, --filter-consumer, --since, --limit, --offset, --push, --into
- Unsupported chain id in CLI usually means your gateway is connected to a network that is not yet configured as supported.
- Missing framework artifacts generally means the selected network has no deployed addresses configured or deployment is incomplete.
- Upgrade no-op with selected artifacts usually indicates same implementation bytecode/version is already active.
- PriceFeeds wrapper fallback to legacy can happen on older deployments that only expose legacy interfaces.
MIT