Skip to Content

Oracle Precompile Usage

Address: 0x0000000000000000000000000000000000001008

The Sei Oracle precompile enables EVM applications to query real-time price feed data directly from Sei’s native Oracle module. This provides access to exchange rates, Time-Weighted Average Prices (TWAPs), and other economic data essential for DeFi applications.

What is a precompile? A precompile is a special smart contract deployed at a fixed address by the Sei protocol itself, that exposes custom native chain logic to EVM-based applications. It acts like a regular contract from the EVM’s perspective, but executes privileged, low-level logic efficiently.

How Does the Oracle Precompile Work?

The Oracle precompile at address 0x0000000000000000000000000000000000001008 exposes functions like getExchangeRates() and getOracleTwaps().

  • Direct Integration: EVM contracts and dApps can query price data like any other smart contract method.
  • Native Execution: Oracle queries are executed at the Cosmos SDK level for maximum efficiency.
  • Real-Time Data: Access live price feeds maintained by Sei’s validator network.

Use Cases

  • DeFi Protocols: Build lending platforms, DEXs, and derivatives with reliable price feeds.
  • Stablecoins: Implement price-stable tokens with accurate exchange rate data.
  • Liquidation Systems: Create robust liquidation mechanisms using real-time prices.
  • Trading Bots: Develop automated trading strategies with TWAP data.
  • Risk Management: Build portfolio management tools with accurate asset valuations.

Functions

The Oracle precompile exposes the following functions:

Query Functions

struct OracleExchangeRate { string exchangeRate; string lastUpdate; int64 lastUpdateTimestamp; } struct DenomOracleExchangeRatePair { string denom; OracleExchangeRate oracleExchangeRateVal; } /// Retrieves the exchange rates for all denominations. /// @return An array of denomination and exchange rate pairs. function getExchangeRates() external view returns (DenomOracleExchangeRatePair[] memory); struct OracleTwap { string denom; string twap; int64 lookbackSeconds; } /// Retrieves Oracle Time-Weighted Average Prices (TWAPs) for the specified lookback period. /// @param lookback_seconds The lookback period in seconds (min: 60, max: 86400). /// @return An array of denomination and TWAP pairs. function getOracleTwaps( uint64 lookback_seconds ) external view returns (OracleTwap[] memory);
Price Format: Exchange rates are returned as decimal strings (e.g., “1.234567” represents $1.234567). Prices are denominated in USD unless otherwise specified.
⚠️
TWAP Limitations: Lookback periods are limited to 1 minute (60 seconds) minimum and 24 hours (86400 seconds) maximum. Requesting data outside this range may result in empty results.

Supported Denominations

Common denominations available in the oracle include:

  • usei - Micro SEI (1 SEI = 1,000,000 usei)
  • uusdc - Micro USDC
  • uatom - Micro ATOM
  • uosmo - Micro OSMO
  • ueth - Micro Ethereum
  • ubtc - Micro Bitcoin
  • uusdt - Micro USDT
The exact list of supported denominations may vary by network. Use getExchangeRates() to see all currently available price feeds.

Using the Contract

Setup

Prerequisites

Before getting started, ensure you have:

  • Node.js (v18 or higher recommended)
  • npm or yarn package manager
  • MetaMask or compatible EVM wallet
  • SEI tokens for gas fees (typically 0.001-0.01 SEI per oracle query)

Install Dependencies

Install the required packages for interacting with Sei precompiles:

# Install ethers.js for smart contract interactions npm install ethers # Install Sei EVM bindings for precompile addresses and ABIs npm install @sei-js/precompiles@2.1.2 # Install dotenv for managing private keys (optional but recommended) npm install dotenv

Import Precompile Components

// Import Oracle precompile address and ABI // View the entire ABI here: https://github.com/sei-protocol/sei-chain/tree/main/precompiles/oracle import { ORACLE_PRECOMPILE_ABI, ORACLE_PRECOMPILE_ADDRESS } from '@sei-js/precompiles'; import { ethers } from 'ethers';
Precompile Address: The Oracle precompile is deployed at 0x0000000000000000000000000000000000001008

Get SEI Tokens

Purchase SEI tokens from supported exchanges. You will need a small amount of SEI in your wallet to pay for gas fees when making calls to the Oracle precompile.

Contract Initialization

Set up your provider, signer, and contract instance:

// Using MetaMask as the signer and provider (browser environment) const provider = new ethers.BrowserProvider(window.ethereum); await provider.send('eth_requestAccounts', []); const signer = await provider.getSigner(); // Or for Node.js environment const provider = new ethers.JsonRpcProvider('https://evm-rpc.sei-apis.com'); const signer = new ethers.Wallet('YOUR_PRIVATE_KEY', provider); // Create a contract instance for the Oracle precompile const oracle = new ethers.Contract(ORACLE_PRECOMPILE_ADDRESS, ORACLE_PRECOMPILE_ABI, signer);

Helper Functions

Use these helper functions for price data handling:

// Helper functions for Oracle data conversion class OracleDataHelper { // Convert exchange rate string to number static rateToNumber(rateString: string): number { try { const rate = parseFloat(rateString); if (isNaN(rate) || !isFinite(rate)) { throw new Error(`Invalid rate: ${rateString}`); } return rate; } catch (error) { console.error('Error parsing rate:', rateString, error); return 0; } } // Format timestamp to readable date static formatTimestamp(timestamp: bigint | number): string { try { return new Date(Number(timestamp) * 1000).toISOString(); } catch (error) { console.error('Error formatting timestamp:', timestamp, error); return 'Invalid timestamp'; } } // Calculate price from exchange rate (assuming USD base) static calculatePrice(exchangeRate: string, amount: number = 1): number { return this.rateToNumber(exchangeRate) * amount; } // Find specific denom in exchange rates static findDenom(rates: any[], denom: string): any { return rates.find((rate) => rate.denom === denom); } // Check if price data is stale (older than 5 minutes) static isPriceStale(timestamp: bigint | number): boolean { const now = Math.floor(Date.now() / 1000); const priceTime = Number(timestamp); return now - priceTime > 300; // 5 minutes } }

Step-by-Step Guide: Using the Oracle Precompile

Get Exchange Rates

// Get all exchange rates const exchangeRates = await oracle.getExchangeRates(); // Display rates exchangeRates.forEach((rate) => { const price = OracleDataHelper.rateToNumber(rate.oracleExchangeRateVal.exchangeRate); const timestamp = rate.oracleExchangeRateVal.lastUpdateTimestamp; const isStale = OracleDataHelper.isPriceStale(timestamp); console.log(`${rate.denom}: $${price.toFixed(6)}${isStale ? ' (STALE)' : ''}`); console.log(`Last Update: ${OracleDataHelper.formatTimestamp(timestamp)}`); });

Get TWAP Data

// Get 1-hour TWAP (3600 seconds) const lookbackSeconds = 3600; const twaps = await oracle.getOracleTwaps(lookbackSeconds); // Display TWAPs twaps.forEach((twap) => { console.log(`${twap.denom} TWAP: ${twap.twap}`); console.log(`Lookback: ${twap.lookbackSeconds} seconds`); });

Query Specific Token Price

// Get exchange rates and find specific token const rates = await oracle.getExchangeRates(); const seiRate = rates.find((r) => r.denom === 'usei'); if (seiRate) { const price = parseFloat(seiRate.oracleExchangeRateVal.exchangeRate); console.log(`SEI Price: $${price}`); }

Monitor Price Changes

// Monitor price changes every 30 seconds (recommended minimum for mainnet) async function monitorPrices() { const previousPrices = new Map(); const monitor = async () => { try { const rates = await oracle.getExchangeRates(); rates.forEach((rate) => { const currentPrice = OracleDataHelper.rateToNumber(rate.oracleExchangeRateVal.exchangeRate); const previousPrice = previousPrices.get(rate.denom); if (previousPrice) { const change = ((currentPrice - previousPrice) / previousPrice) * 100; console.log(`${rate.denom}: $${currentPrice.toFixed(6)} (${change >= 0 ? '+' : ''}${change.toFixed(2)}%)`); } previousPrices.set(rate.denom, currentPrice); }); } catch (error) { console.error('Monitor error:', error); } }; // Initial fetch await monitor(); // Monitor every 30 seconds setInterval(monitor, 30000); }

Complete Integration Example

Create a file named oracle-demo.js:

const { ethers } = require('ethers'); const { ORACLE_PRECOMPILE_ABI, ORACLE_PRECOMPILE_ADDRESS } = require('@sei-js/precompiles'); require('dotenv').config(); // Helper functions function safeParseFloat(str) { try { const num = parseFloat(str); return isNaN(num) ? 0 : num; } catch { return 0; } } function formatTimestamp(timestamp) { try { return new Date(Number(timestamp) * 1000).toISOString(); } catch { return 'Invalid timestamp'; } } function isPriceStale(timestamp, maxAgeSeconds = 300) { const now = Math.floor(Date.now() / 1000); return now - Number(timestamp) > maxAgeSeconds; } async function main() { try { // Connect to Sei Mainnet console.log('🔗 Connecting to Sei Mainnet...'); const provider = new ethers.JsonRpcProvider('https://evm-rpc.sei-apis.com'); // Verify connection to mainnet const network = await provider.getNetwork(); if (Number(network.chainId) !== 1329) { throw new Error(`Expected Sei Mainnet (1329), but connected to chain ${network.chainId}`); } console.log(`✅ Connected to Sei Mainnet (Chain ID: 1329)`); // Setup wallet const privateKey = process.env.PRIVATE_KEY; if (!privateKey) { throw new Error('Please set PRIVATE_KEY in .env file'); } const wallet = new ethers.Wallet(privateKey, provider); console.log('👛 Wallet address:', wallet.address); // Check balance const balance = await provider.getBalance(wallet.address); const balanceInSei = ethers.formatEther(balance); console.log('💰 Wallet balance:', balanceInSei, 'SEI'); if (parseFloat(balanceInSei) < 0.01) { console.warn('⚠️ Low balance detected. You may need more SEI for gas fees.'); console.log('💡 Purchase SEI from supported exchanges like Binance, Coinbase, or KuCoin'); } // Initialize Oracle precompile contract const oracle = new ethers.Contract(ORACLE_PRECOMPILE_ADDRESS, ORACLE_PRECOMPILE_ABI, wallet); console.log('\n' + '='.repeat(50)); console.log('🔮 Oracle Precompile Demo - Sei Mainnet'); console.log('='.repeat(50)); // 1. Get all exchange rates console.log('\n1️⃣ Fetching current exchange rates...'); const exchangeRates = await oracle.getExchangeRates(); if (!exchangeRates || exchangeRates.length === 0) { console.log('📭 No exchange rates available on mainnet'); return; } console.log(`📊 Found ${exchangeRates.length} price feeds on Sei Mainnet:`); // Display all available rates exchangeRates.forEach((rate, index) => { const price = safeParseFloat(rate.oracleExchangeRateVal.exchangeRate); const timestamp = rate.oracleExchangeRateVal.lastUpdateTimestamp; const lastUpdate = formatTimestamp(timestamp); const isStale = isPriceStale(timestamp); console.log(`\n ${index + 1}. ${rate.denom}:`); console.log(` 💲 Price: $${price.toFixed(6)}${isStale ? ' ⚠️ (STALE)' : ''}`); console.log(` ⏰ Last Update: ${lastUpdate}`); }); // 2. Get TWAP data console.log('\n2️⃣ Fetching 1-hour TWAP data...'); const lookbackSeconds = 3600; // 1 hour try { const twaps = await oracle.getOracleTwaps(lookbackSeconds); if (twaps && twaps.length > 0) { console.log(`📈 Found ${twaps.length} TWAP values:`); twaps.forEach((twap, index) => { const twapPrice = safeParseFloat(twap.twap); console.log(`\n ${index + 1}. ${twap.denom}:`); console.log(` 📊 1hr TWAP: $${twapPrice.toFixed(6)}`); console.log(` ⏱️ Lookback: ${twap.lookbackSeconds} seconds`); }); } else { console.log('📭 No TWAP data available for the requested period'); } } catch (twapError) { console.error('❌ Failed to fetch TWAP data:', twapError.message); } // 3. Focus on SEI price analysis console.log('\n3️⃣ SEI Price Analysis...'); const seiRate = exchangeRates.find((r) => r.denom === 'usei'); if (seiRate) { const seiPrice = safeParseFloat(seiRate.oracleExchangeRateVal.exchangeRate); const timestamp = seiRate.oracleExchangeRateVal.lastUpdateTimestamp; console.log(`\n 💎 SEI (usei) Details:`); console.log(` 💲 Current Price: $${seiPrice.toFixed(6)}`); console.log(` ⏰ Last Update: ${formatTimestamp(timestamp)}`); console.log(` 🔄 Price Age: ${Math.floor(Date.now() / 1000) - Number(timestamp)} seconds`); // Market cap calculation (approximate) const circulatingSupply = 3_90000000; // Approximate SEI supply const marketCap = seiPrice * circulatingSupply; console.log(` 📊 Est. Market Cap: $${(marketCap / 1000000).toFixed(2)}M`); } else { console.log(' ❌ SEI price not found in oracle data'); } // 4. DeFi use case - Advanced collateral calculation console.log('\n4️⃣ Advanced DeFi Example - Multi-asset portfolio...'); const portfolio = [ { asset: 'usei', amount: 1000 }, { asset: 'uusdc', amount: 500 }, { asset: 'uatom', amount: 50 } ]; let totalPortfolioValue = 0; const portfolioBreakdown = []; console.log(`\n 💼 Portfolio Analysis:`); portfolio.forEach(({ asset, amount }) => { const assetRate = exchangeRates.find((r) => r.denom === asset); if (assetRate) { const price = safeParseFloat(assetRate.oracleExchangeRateVal.exchangeRate); const value = price * amount; totalPortfolioValue += value; portfolioBreakdown.push({ asset, amount, price, value, percentage: 0 // Will calculate after total }); console.log(` 🪙 ${asset}: ${amount} tokens × $${price.toFixed(6)} = $${value.toFixed(2)}`); } }); // Calculate percentages portfolioBreakdown.forEach((item) => { item.percentage = (item.value / totalPortfolioValue) * 100; }); console.log(`\n 📊 Portfolio Summary:`); console.log(` 💰 Total Value: $${totalPortfolioValue.toFixed(2)}`); portfolioBreakdown.forEach(({ asset, value, percentage }) => { console.log(` 📈 ${asset}: $${value.toFixed(2)} (${percentage.toFixed(1)}%)`); }); // Lending calculations const maxLTV = 0.75; // 75% max loan-to-value const maxBorrow = totalPortfolioValue * maxLTV; console.log(` 🏦 Max Borrowing Power (75% LTV): $${maxBorrow.toFixed(2)}`); // 5. Gas cost analysis console.log('\n5️⃣ Gas cost analysis on mainnet...'); try { const feeData = await provider.getFeeData(); const exchangeRateGas = await oracle.getExchangeRates.estimateGas(); const twapGas = await oracle.getOracleTwaps.estimateGas(3600); const exchangeRateCost = exchangeRateGas * (feeData.gasPrice || 0n); const twapCost = twapGas * (feeData.gasPrice || 0n); console.log(`\n ⛽ Mainnet Gas Estimates:`); console.log(` 📊 getExchangeRates(): ${exchangeRateGas.toString()} gas`); console.log(` 📈 getOracleTwaps(): ${twapGas.toString()} gas`); console.log(` 💰 Exchange Rate Cost: ~${ethers.formatEther(exchangeRateCost)} SEI`); console.log(` 💰 TWAP Cost: ~${ethers.formatEther(twapCost)} SEI`); // Current SEI price for USD conversion if (seiRate) { const seiPrice = safeParseFloat(seiRate.oracleExchangeRateVal.exchangeRate); const exchangeRateUSD = parseFloat(ethers.formatEther(exchangeRateCost)) * seiPrice; const twapUSD = parseFloat(ethers.formatEther(twapCost)) * seiPrice; console.log(` 💵 Exchange Rate Cost: ~$${exchangeRateUSD.toFixed(4)} USD`); console.log(` 💵 TWAP Cost: ~$${twapUSD.toFixed(4)} USD`); } } catch (gasError) { console.log(' ⚠️ Could not estimate gas costs:', gasError.message); } } catch (error) { console.error('\n❌ Demo failed:', error.message); // Enhanced error diagnostics for mainnet if (error.message.includes('1329')) { console.log("💡 Network issue: Make sure you're connecting to Sei Mainnet"); console.log(' - RPC URL: https://evm-rpc.sei-apis.com'); console.log(' - Chain ID: 1329'); } else if (error.code === 'INSUFFICIENT_FUNDS') { console.log('💡 Buy SEI tokens from:'); console.log(' - Binance: https://www.binance.com/en/trade/SEI_USDT'); console.log(' - Coinbase: https://www.coinbase.com/price/sei'); console.log(' - KuCoin: https://www.kucoin.com/trade/SEI-USDT'); } else if (error.code === 'NETWORK_ERROR') { console.log('💡 Network troubleshooting:'); console.log(' - Check internet connection'); console.log(' - Verify RPC endpoint is accessible'); console.log(' - Try alternative RPC if available'); } process.exit(1); } } // Graceful shutdown process.on('SIGINT', () => { console.log('\n🛑 Demo interrupted'); process.exit(0); }); // Run the demo if (require.main === module) { main().catch(console.error); } module.exports = { main };

Running the Example

  1. Create a new directory and initialize npm:
mkdir sei-oracle-mainnet cd sei-oracle-mainnet npm init -y
  1. Install dependencies:
npm install ethers @sei-js/precompiles@2.1.2 dotenv
  1. Create a .env file:
PRIVATE_KEY=your_private_key_here_without_0x_prefix
  1. Create the demo file: Copy the complete integration example above into oracle-demo.js

  2. Run the script:

node oracle-demo.js

Expected Output on Mainnet

🔗 Connecting to Sei Mainnet... ✅ Connected to Sei Mainnet (Chain ID: 1329) 👛 Wallet address: 0x742d35Cc6634C0532925a3b844Bc6789e065f3B 💰 Wallet balance: 5.2 SEI ================================================== 🔮 Oracle Precompile Demo - Sei Mainnet ================================================== 1️⃣ Fetching current exchange rates... 📊 Found 12 price feeds on Sei Mainnet: 1. usei: 💲 Price: $0.421500 ⏰ Last Update: 2024-01-15T15:45:32.000Z 2. uusdc: 💲 Price: $1.000100 ⏰ Last Update: 2024-01-15T15:45:32.000Z 3. uatom: 💲 Price: $9.875000 ⏰ Last Update: 2024-01-15T15:45:32.000Z 2️⃣ Fetching 1-hour TWAP data... 📈 Found 12 TWAP values: 1. usei: 📊 1hr TWAP: $0.419200 ⏱️ Lookback: 3600 seconds 3️⃣ SEI Price Analysis... 💎 SEI (usei) Details: 💲 Current Price: $0.421500 ⏰ Last Update: 2024-01-15T15:45:32.000Z 🔄 Price Age: 45 seconds 📊 Est. Market Cap: $164.4M 4️⃣ Advanced DeFi Example - Multi-asset portfolio... 💼 Portfolio Analysis: 🪙 usei: 1000 tokens × $0.421500 = $421.50 🪙 uusdc: 500 tokens × $1.000100 = $500.05 🪙 uatom: 50 tokens × $9.875000 = $493.75 📊 Portfolio Summary: 💰 Total Value: $1415.30 📈 usei: $421.50 (29.8%) 📈 uusdc: $500.05 (35.3%) 📈 uatom: $493.75 (34.9%) 🏦 Max Borrowing Power (75% LTV): $1061.48 5️⃣ Gas cost analysis on mainnet... ⛽ Mainnet Gas Estimates: 📊 getExchangeRates(): 52341 gas 📈 getOracleTwaps(): 58967 gas 💰 Exchange Rate Cost: ~0.002617 SEI 💰 TWAP Cost: ~0.002948 SEI 💵 Exchange Rate Cost: ~$0.0011 USD 💵 TWAP Cost: ~$0.0012 USD ================================================== ✅ Oracle demo completed successfully on Sei Mainnet! ==================================================

Production Best Practices

Mainnet Production Considerations:

  • Real Money at Risk: Always test thoroughly on testnet first
  • Gas Optimization: Oracle calls cost real SEI - optimize frequency
  • Price Validation: Implement multiple layers of price validation: Always validate price freshness before usage
  • Fallback Mechanisms: Have backup price sources for critical applications
  • Monitoring: Set up alerts for oracle failures or stale data
  • Rate Limiting: Respect RPC rate limits to avoid being blocked

Error Code Reference

Error

Cause

Solution

no oracle data

Oracle module not active

Check network configuration

denom not found

Asset not in oracle

Verify supported denoms

stale price data

Old timestamp

Check lastUpdateTimestamp

invalid lookback

Lookback too long

Use shorter TWAP period

Last updated on