Supra
Lumia L2 integrates with Supra's high-performance oracle system to provide fast, reliable price feeds through their Distributed Oracle Agreement (DORA) protocol. This guide explains how to integrate Supra oracles into your dApps on Lumia L2.
Overview
Supra provides two types of oracle implementations:
Pull Oracle: On-demand price data with sub-second response time
Push Oracle: Automated price updates with layer-1 security guarantees
This guide focuses on the Pull Oracle implementation, which gives you maximum control over when and how to fetch price data.
Integration Process
1. Smart Contract Setup
First, create your smart contract that will receive and process oracle data:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import "@openzeppelin/contracts/access/Ownable.sol";
interface ISupraOraclePull {
struct PriceData {
uint256[] pairs; // List of pairs
uint256[] prices; // prices[i] is the price of pairs[i]
uint256[] decimals; // decimals[i] is the decimals of pairs[i]
}
function verifyOracleProof(bytes calldata _bytesproof)
external
returns (PriceData memory);
}
contract SupraPriceConsumer is Ownable {
ISupraOraclePull internal oracle;
// Store latest prices
mapping(uint256 => uint256) public latestPrices;
constructor(address oracle_) Ownable(msg.sender) {
oracle = ISupraOraclePull(oracle_);
}
function deliverPriceData(bytes calldata _bytesProof)
external
onlyOwner
{
ISupraOraclePull.PriceData memory prices =
oracle.verifyOracleProof(_bytesProof);
// Store the latest prices
for (uint256 i = 0; i < prices.pairs.length; i++) {
latestPrices[prices.pairs[i]] = prices.prices[i];
}
}
function updateOracleAddress(address oracle_)
external
onlyOwner
{
oracle = ISupraOraclePull(oracle_);
}
}
2. Web2 Integration
You'll need a Node.js application to fetch price data from Supra's gRPC server and send it to your smart contract. Here's a basic implementation:
const Web3 = require('web3');
const { PullServiceClient } = require('@supraoracles/sdk');
// Configuration
const config = {
grpc: {
address: "YOUR_GRPC_SERVER",
pairIndexes: [1, 2, 3], // Asset pairs you want to track
chainType: "EVM"
},
client: {
rpcUrl: "https://testnet-rpc.lumia.org", // Lumia L2 RPC
contractAddress: "YOUR_CONTRACT_ADDRESS",
walletAddress: "YOUR_WALLET_ADDRESS",
privateKey: "YOUR_PRIVATE_KEY"
}
};
async function main() {
// Initialize gRPC client
const client = new PullServiceClient(
config.grpc.address,
config.grpc.pairIndexes,
config.grpc.chainType
);
// Get price data
const priceData = await client.getPrice();
// Send to contract
await sendToContract(priceData);
}
async function sendToContract(priceData) {
const web3 = new Web3(config.client.rpcUrl);
const contract = new web3.eth.Contract(ABI, config.client.contractAddress);
const tx = {
from: config.client.walletAddress,
to: config.client.contractAddress,
data: contract.methods.deliverPriceData(priceData).encodeABI(),
gas: await contract.methods.deliverPriceData(priceData)
.estimateGas({from: config.client.walletAddress})
};
const signedTx = await web3.eth.accounts.signTransaction(
tx,
config.client.privateKey
);
await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
}
// Run price updates every minute
setInterval(main, 60000);
3. Contract Deployment
Deploy your contract using your preferred method (Hardhat, Truffle, etc.) with the appropriate Supra Oracle address:
Lumia Mainnet
Oracle Address: 0x16f70cAD28dd621b0072B5A8a8c392970E87C3dD
Best Practices
Error Handling
function deliverPriceData(bytes calldata _bytesProof)
external
onlyOwner
{
try oracle.verifyOracleProof(_bytesProof) returns (
ISupraOraclePull.PriceData memory prices
) {
for (uint256 i = 0; i < prices.pairs.length; i++) {
latestPrices[prices.pairs[i]] = prices.prices[i];
}
} catch {
revert("Invalid oracle proof");
}
}
Price Validation
function validatePrice(uint256 price, uint256 oldPrice)
internal
pure
returns (bool)
{
// Example: Reject prices that changed more than 50%
if (oldPrice > 0) {
uint256 change = price > oldPrice ?
price - oldPrice : oldPrice - price;
if (change * 100 / oldPrice > 50) {
return false;
}
}
return true;
}
Update Frequency
Consider implementing a minimum time between updates
Use price deviation thresholds to optimize gas costs
implement redundancy in your web2 infrastructure
Technical Specifications
Response Time: Sub-second for pull oracle
Data Sources: 40+ sources aggregated
Security: Byzantine Fault Tolerant consensus with DORA
Price Calculation: Median-of-medians with coherent cluster validation
Update Frequency: Customizable (recommended: 1-5 minutes)
Gas Optimization: Batch price updates supported
Support & Resources
Last updated
Was this helpful?