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
) - VerifyingP-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:
- Staking Precompile Usage →
- Governance Precompile Usage →
- Oracle Precompile Usage →
- Distribution Precompile Usage →
- P256 Precompile Usage →
- JSON Precompile Usage →