Consumer Contract Integration
Learn how to read high-frequency price data from PolkaOracle directly into your smart contracts or frontend applications. We support both Solidity interfaces for on-chain protocols and standard ethers.js calls for off-chain services.
1. Solidity Integration
To interact with the oracle on-chain, use the IPriceOracle interface. We recommend using the bytes32 feed ID to save gas, but we also provide a string-based convenience function.
interface IPriceOracle {
function getPrice(bytes32 feedId) external view returns (uint256 price, uint256 timestamp);
function getFreshPrice(bytes32 feedId, uint256 maxAge) external view returns (uint256 price, uint256 timestamp);
function getTWAP(bytes32 feedId, uint256 window) external view returns (uint256 twapPrice);
function getTwapHistory(bytes32 feedId) external view returns (TWAPEntry[] memory);
function getPriceByName(string calldata name) external view returns (uint256 price, uint256 timestamp);
function getSupportedFeeds() external view returns (bytes32[] memory);
}
contract MyDeFiApp {
IPriceOracle public oracle;
bytes32 constant DOT_USD = keccak256("DOT/USD");
constructor(address _oracle) {
oracle = IPriceOracle(_oracle);
}
function borrow() external {
// Option A: Get latest price using bytes32 (Recommended)
(uint256 price, uint256 timestamp) = oracle.getPrice(DOT_USD);
// Option B: Get price and revert if older than 1 hour
(uint256 freshPrice, ) = oracle.getFreshPrice(DOT_USD, 1 hours);
// Option C: Use TWAP for manipulation resistance (e.g. 6 hours)
uint256 twap = oracle.getTWAP(DOT_USD, 6 hours);
// Option D: Convenience string lookup (Higher gas cost)
(uint256 stringPrice, ) = oracle.getPriceByName("DOT/USD");
// Use price (Note: price is scaled by 1e8)
}
}Deployed Example: OracleConsumer
A reference consumer contract is live on Paseo Hub at 0xa442...5146. It demonstrates:
getDOTPrice(),getBTCPrice(),getETHPrice()— read live pricesgetDOTTWAP()— 5-minute time-weighted averagecalculateDOTValue(uint256 dotAmount)— convert DOT to USD on-chainisCollateralSufficient()— DeFi collateral ratio check
See live results on the Dashboard.
2. JavaScript / ethers.js
You can read oracle prices directly from any JavaScript or TypeScript environment using ethers.js. Note that prices are returned with 8 decimal places.
import { ethers } from "ethers";
async function fetchPrice() {
// 1. Connect to Polkadot Hub Testnet (Paseo)
const provider = new ethers.JsonRpcProvider("https://eth-rpc-testnet.polkadot.io/");
// 2. Initialize Oracle Contract
const ORACLE_ADDRESS = "0xaf781298fE769738eF529816c11C121Ea8887Fc9";
const abi = ["function getPrice(bytes32 feedId) view returns (uint256 price, uint256 timestamp)"];
const oracle = new ethers.Contract(ORACLE_ADDRESS, abi, provider);
// 3. Compute feedId for DOT/USD
const feedId = ethers.keccak256(ethers.toUtf8Bytes("DOT/USD"));
// 4. Fetch and format
const [price, timestamp] = await oracle.getPrice(feedId);
console.log(`DOT/USD Price: $${Number(price) / 1e8}`);
}
fetchPrice();3. Available Functions Reference
| Function | Parameters | Returns | Description |
|---|---|---|---|
| getPrice | bytes32 feedId | (uint256, uint256) | Latest aggregated price and timestamp |
| getFreshPrice | bytes32 feedId, uint256 maxAge | (uint256, uint256) | Reverts if price is older than maxAge |
| getTWAP | bytes32 feedId, uint256 window | uint256 | Time-weighted average price over window |
| getPriceByName | string name | (uint256, uint256) | Convenience string lookup |
| getFeedId | string name | bytes32 | Convert string to bytes32 format |
| isPriceStale | bytes32 feedId | bool | Checks staleness config |
| getTwapHistory | bytes32 feedId | TWAPEntry[] | Full circular buffer of up to 60 TWAP entries |
| getSupportedFeeds | — | bytes32[] | All registered feed IDs |
| getSubmission | bytes32 feedId, address reporter | (uint256, uint256) | A specific reporter's submission for a feed |
| getRoundSubmissionCount | bytes32 feedId | uint256 | Number of submissions in the current round |
About TWAP (Time-Weighted Average Price)
For DeFi protocols such as lending markets or synthetic asset minters, using the spot price can expose your protocol to flash loan manipulation. We highly recommend using the getTWAP function for these use cases.
"The TWAP is calculated by keeping a historical cumulative record of prices multiplied by the time they were active. By taking two snapshots and dividing the difference in cumulative prices by the time elapsed, we get a highly manipulation-resistant average."
Price History (getTwapHistory)
The oracle maintains a circular buffer of up to 60 historical TWAP entries per feed. Each entry records the cumulative price and timestamp, enabling clients to compute custom time-weighted averages over arbitrary windows.
// Solidity — read full TWAP history
TWAPEntry[] memory history = oracle.getTwapHistory(DOT_USD);
// Each TWAPEntry contains:
// uint256 cumulativePrice — running sum of (price × elapsed time)
// uint256 timestamp — block timestamp of the snapshot
// JavaScript — fetch and display history
const abi = ["function getTwapHistory(bytes32 feedId) view returns (tuple(uint256 cumulativePrice, uint256 timestamp)[])"];
const oracle = new ethers.Contract(ORACLE_ADDRESS, abi, provider);
const history = await oracle.getTwapHistory(feedId);
for (const entry of history) {
console.log(` cumPrice: ${entry.cumulativePrice}, time: ${entry.timestamp}`);
}Tip: To compute a custom TWAP between two points, take the difference in cumulativePrice and divide by the difference in timestamp. This gives you the average price over that exact interval.