Skip to Content
EVMPrecompilesExample Usage

Example Usage

Sei precompiles are special smart contracts deployed at fixed addresses that expose native Sei functionality to EVM applications. They can be used like any standard smart contract, enabling powerful cross-chain capabilities.

Available Precompiles:

  • Staking (0x1005) - Delegation and staking operations
  • Governance (0x1006) - Proposal submission and voting
  • Oracle (0x1008) - Price feed data access
  • JSON (0x1003) - JSON data parsing
  • P256 (0x1011) - Verifying P-256 elliptic curve signatures
  • Distribution (0x1007) - Staking rewards and validator commissions

Quick Setup

Install the required dependencies:

npm install ethers @sei-js/evm

Set up your provider and signer:

import { ethers } from 'ethers'; // Browser environment with MetaMask const provider = new ethers.BrowserProvider(window.ethereum); await provider.send('eth_requestAccounts', []); const signer = await provider.getSigner(); // Or Node.js environment const provider = new ethers.JsonRpcProvider('https://evm-rpc-testnet.sei-apis.com'); const signer = new ethers.Wallet('YOUR_PRIVATE_KEY', provider);

Precompile Examples

Staking Precompile

Delegate tokens and manage staking operations:

import { STAKING_PRECOMPILE_ABI, STAKING_PRECOMPILE_ADDRESS } from '@sei-js/evm'; const staking = new ethers.Contract(STAKING_PRECOMPILE_ADDRESS, STAKING_PRECOMPILE_ABI, signer); // Delegate 1 SEI const validatorAddress = 'seivaloper1xyz...'; const amountToDelegate = ethers.parseUnits('1', 18); const tx = await staking.delegate(validatorAddress, { value: amountToDelegate }); await tx.wait(); // Query delegation const delegation = await staking.delegation(await signer.getAddress(), validatorAddress); console.log('Delegated amount:', delegation.balance.amount.toString());

Governance Precompile

Submit proposals and vote on governance:

import { GOVERNANCE_PRECOMPILE_ABI, GOVERNANCE_PRECOMPILE_ADDRESS } from '@sei-js/evm'; const governance = new ethers.Contract(GOVERNANCE_PRECOMPILE_ADDRESS, GOVERNANCE_PRECOMPILE_ABI, signer); // Vote on a proposal const proposalId = 1; const voteOption = 1; // 1=Yes, 2=Abstain, 3=No, 4=NoWithVeto const tx = await governance.vote(proposalId, voteOption); await tx.wait(); console.log('Vote cast successfully');

Oracle Precompile

Access real-time price feed data:

import { ORACLE_PRECOMPILE_ABI, ORACLE_PRECOMPILE_ADDRESS } from '@sei-js/evm'; const oracle = new ethers.Contract(ORACLE_PRECOMPILE_ADDRESS, ORACLE_PRECOMPILE_ABI, signer); // Get exchange rates const rates = await oracle.getExchangeRates(); rates.forEach((rate) => { console.log(`${rate.denom}: $${rate.oracleExchangeRateVal.exchangeRate}`); }); // Get 1-hour TWAP const twaps = await oracle.getOracleTwaps(3600); console.log('TWAP data:', twaps);

JSON Precompile

Parse and query JSON data on-chain:

import { JSON_PRECOMPILE_ABI, JSON_PRECOMPILE_ADDRESS } from '@sei-js/evm'; const jsonPrecompile = new ethers.Contract(JSON_PRECOMPILE_ADDRESS, JSON_PRECOMPILE_ABI, signer); // Parse JSON data const data = { price: 100, symbol: 'SEI' }; const inputData = ethers.toUtf8Bytes(JSON.stringify(data)); // Extract string value const symbolBytes = await jsonPrecompile.extractAsBytes(inputData, 'symbol'); const symbol = ethers.toUtf8String(symbolBytes); // Extract numeric value const price = await jsonPrecompile.extractAsUint256(inputData, 'price'); console.log(`${symbol}: ${price}`);

Common Patterns

Error Handling

Always wrap precompile calls in try-catch blocks:

try { const tx = await staking.delegate(validatorAddress, { value: amount }); const receipt = await tx.wait(); console.log('Success:', receipt.hash); } catch (error) { if (error.code === 'INSUFFICIENT_FUNDS') { console.error('Not enough SEI for delegation'); } else { console.error('Transaction failed:', error.message); } }

Gas Optimization

Set appropriate gas limits for different operations:

// Simple operations (queries) const delegation = await staking.delegation(address, validator, { gasLimit: 100000 }); // Complex operations (transactions) const tx = await governance.submitProposal(proposalJSON, { value: depositAmount, gasLimit: 500000 });

Batch Operations

Execute multiple precompile calls efficiently:

// Batch read operations const [rates, twaps, delegation] = await Promise.all([oracle.getExchangeRates(), oracle.getOracleTwaps(3600), staking.delegation(address, validator)]); // Sequential write operations with error handling const operations = [() => staking.delegate(validator1, { value: amount1 }), () => staking.delegate(validator2, { value: amount2 }), () => governance.vote(proposalId, voteOption)]; for (const operation of operations) { try { const tx = await operation(); await tx.wait(); } catch (error) { console.error('Operation failed:', error); } }

Complete Working Example

Here’s a minimal example that demonstrates using multiple precompiles:

// multi-precompile-demo.js const { ethers } = require('ethers'); const { STAKING_PRECOMPILE_ABI, STAKING_PRECOMPILE_ADDRESS, ORACLE_PRECOMPILE_ABI, ORACLE_PRECOMPILE_ADDRESS } = require('@sei-js/evm'); async function main() { // Setup const provider = new ethers.JsonRpcProvider('https://evm-rpc.sei-apis.com'); const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider); // Initialize precompiles const staking = new ethers.Contract(STAKING_PRECOMPILE_ADDRESS, STAKING_PRECOMPILE_ABI, wallet); const oracle = new ethers.Contract(ORACLE_PRECOMPILE_ADDRESS, ORACLE_PRECOMPILE_ABI, wallet); // Get current SEI price const rates = await oracle.getExchangeRates(); const seiRate = rates.find((r) => r.denom === 'usei'); console.log('SEI Price:', seiRate?.oracleExchangeRateVal.exchangeRate); // Check delegation const delegation = await staking.delegation(wallet.address, 'seivaloper1...'); console.log('Current delegation:', delegation.balance.amount.toString()); } main().catch(console.error);

Run with:

PRIVATE_KEY=your_key node multi-precompile-demo.js

Best Practices

⚠️

Important Guidelines:

  • Always validate inputs before calling precompiles
  • Use appropriate decimal conversions
  • Handle errors gracefully with specific error messages
  • Set reasonable gas limits to avoid failed transactions
  • Never expose private keys in code

Next Steps

For detailed documentation on each precompile:

Need Help? Join the Sei Discord for community support or check the GitHub repository for more examples.
Last updated on