> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sei.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Precompile Example Usage

> Learn how to interact with Sei's precompiles through viem and ethers, covering all available precompiles with quick examples and common patterns for seamless integration between EVM and Sei-native functionality.

Sei precompiles are special smart contracts deployed at fixed addresses that expose native Sei functionality to EVM applications. They can be called like any standard smart contract using viem, ethers, or wagmi.

<Info>
  **Available Precompiles:**

  | Precompile   | Address  | Description                                        |
  | ------------ | -------- | -------------------------------------------------- |
  | Bank         | `0x1001` | Query native denom balances (usei, factory tokens) |
  | JSON         | `0x1003` | Parse JSON data within contracts                   |
  | Staking      | `0x1005` | Delegation and staking operations                  |
  | Governance   | `0x1006` | Proposal voting                                    |
  | Distribution | `0x1007` | Claim staking rewards                              |
  | P256         | `0x1011` | Verify P-256 elliptic curve signatures             |
</Info>

## Setup

```bash theme={"dark"}
npm install viem ethers @sei-js/precompiles
```

<CodeGroup>
  ```ts viem theme={"dark"}
  import { createPublicClient, createWalletClient, http, custom } from 'viem';
  import { sei } from 'viem/chains';

  // Read-only
  const client = createPublicClient({ chain: sei, transport: http() });

  // Browser wallet (write)
  const walletClient = createWalletClient({ chain: sei, transport: custom(window.ethereum) });
  const [account] = await walletClient.getAddresses();
  ```

  ```ts ethers theme={"dark"}
  import { ethers } from 'ethers';

  // Browser environment
  const provider = new ethers.BrowserProvider(window.ethereum);
  const signer = await provider.getSigner();

  // Node.js / scripts
  // const provider = new ethers.JsonRpcProvider('https://evm-rpc.sei-apis.com');
  // const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
  ```
</CodeGroup>

## Bank Precompile

`eth_getBalance` only returns the EVM-side SEI balance. The Bank precompile lets you query any native denom — including factory tokens — from any address:

<CodeGroup>
  ```ts viem theme={"dark"}
  import { BANK_PRECOMPILE_ABI, BANK_PRECOMPILE_ADDRESS } from '@sei-js/precompiles';

  // Query a specific denom balance
  const balance = await client.readContract({
    address: BANK_PRECOMPILE_ADDRESS,
    abi: BANK_PRECOMPILE_ABI,
    functionName: 'balance',
    args: ['0xYourAddress', 'usei'],
  });

  // Query all native balances for an address
  const allBalances = await client.readContract({
    address: BANK_PRECOMPILE_ADDRESS,
    abi: BANK_PRECOMPILE_ABI,
    functionName: 'all_balances',
    args: ['0xYourAddress'],
  });
  // Returns: [{ denom: 'usei', amount: '1000000' }, ...]
  ```

  ```ts ethers theme={"dark"}
  import { BANK_PRECOMPILE_ABI, BANK_PRECOMPILE_ADDRESS } from '@sei-js/precompiles';

  const bank = new ethers.Contract(BANK_PRECOMPILE_ADDRESS, BANK_PRECOMPILE_ABI, provider);

  const balance = await bank.balance('0xYourAddress', 'usei');
  const allBalances = await bank.all_balances('0xYourAddress');
  ```
</CodeGroup>

## Staking Precompile

Delegate, undelegate, and query staking state:

<CodeGroup>
  ```ts viem theme={"dark"}
  import { parseEther } from 'viem';
  import { STAKING_PRECOMPILE_ABI, STAKING_PRECOMPILE_ADDRESS } from '@sei-js/precompiles';

  // Delegate SEI to a validator
  const delegateHash = await walletClient.writeContract({
    address: STAKING_PRECOMPILE_ADDRESS,
    abi: STAKING_PRECOMPILE_ABI,
    functionName: 'delegate',
    args: ['seivaloper1...'],
    value: parseEther('10'),
  });

  // Query delegation
  const delegation = await client.readContract({
    address: STAKING_PRECOMPILE_ADDRESS,
    abi: STAKING_PRECOMPILE_ABI,
    functionName: 'delegation',
    args: [account, 'seivaloper1...'],
  });

  // Undelegate 5 SEI — amount is in 6-decimal usei (1 SEI = 1_000_000 usei), not wei
  const undelegateHash = await walletClient.writeContract({
    address: STAKING_PRECOMPILE_ADDRESS,
    abi: STAKING_PRECOMPILE_ABI,
    functionName: 'undelegate',
    args: ['seivaloper1...', 5_000_000n],
  });
  ```

  ```ts ethers theme={"dark"}
  import { STAKING_PRECOMPILE_ABI, STAKING_PRECOMPILE_ADDRESS } from '@sei-js/precompiles';

  const staking = new ethers.Contract(STAKING_PRECOMPILE_ADDRESS, STAKING_PRECOMPILE_ABI, signer);
  const readStaking = new ethers.Contract(STAKING_PRECOMPILE_ADDRESS, STAKING_PRECOMPILE_ABI, provider);

  // Delegate 10 SEI
  const tx = await staking.delegate('seivaloper1...', { value: ethers.parseEther('10') });
  await tx.wait();

  // Query delegation
  const delegation = await readStaking.delegation(await signer.getAddress(), 'seivaloper1...');
  console.log('Delegated:', delegation.balance.amount.toString());

  // Undelegate 5 SEI — amount is in 6-decimal usei (1 SEI = 1_000_000 usei), not wei
  const undelegateTx = await staking.undelegate('seivaloper1...', ethers.parseUnits('5', 6));
  await undelegateTx.wait();
  ```
</CodeGroup>

## Governance Precompile

Vote on an active governance proposal:

<CodeGroup>
  ```ts viem theme={"dark"}
  import { GOVERNANCE_PRECOMPILE_ABI, GOVERNANCE_PRECOMPILE_ADDRESS } from '@sei-js/precompiles';

  // Vote options: 1 = Yes, 2 = Abstain, 3 = No, 4 = NoWithVeto
  const hash = await walletClient.writeContract({
    address: GOVERNANCE_PRECOMPILE_ADDRESS,
    abi: GOVERNANCE_PRECOMPILE_ABI,
    functionName: 'vote',
    args: [99n, 1],
  });
  ```

  ```ts ethers theme={"dark"}
  import { GOVERNANCE_PRECOMPILE_ABI, GOVERNANCE_PRECOMPILE_ADDRESS } from '@sei-js/precompiles';

  const governance = new ethers.Contract(GOVERNANCE_PRECOMPILE_ADDRESS, GOVERNANCE_PRECOMPILE_ABI, signer);

  // 1 = Yes, 2 = Abstain, 3 = No, 4 = NoWithVeto
  const tx = await governance.vote(99n, 1);
  await tx.wait();
  ```
</CodeGroup>

## Distribution Precompile

Claim staking rewards from a validator:

<CodeGroup>
  ```ts viem theme={"dark"}
  import { DISTRIBUTION_PRECOMPILE_ABI, DISTRIBUTION_PRECOMPILE_ADDRESS } from '@sei-js/precompiles';

  const hash = await walletClient.writeContract({
    address: DISTRIBUTION_PRECOMPILE_ADDRESS,
    abi: DISTRIBUTION_PRECOMPILE_ABI,
    functionName: 'withdrawDelegationRewards',
    args: ['seivaloper1...'],
  });
  ```

  ```ts ethers theme={"dark"}
  import { DISTRIBUTION_PRECOMPILE_ABI, DISTRIBUTION_PRECOMPILE_ADDRESS } from '@sei-js/precompiles';

  const distribution = new ethers.Contract(
    DISTRIBUTION_PRECOMPILE_ADDRESS,
    DISTRIBUTION_PRECOMPILE_ABI,
    signer,
  );

  const tx = await distribution.withdrawDelegationRewards('seivaloper1...');
  await tx.wait();
  ```
</CodeGroup>

## JSON Precompile

Parse JSON data within EVM contracts or dApps — useful for processing oracle responses, NFT metadata, and structured payloads:

<CodeGroup>
  ```ts viem theme={"dark"}
  import { toHex, toBytes } from 'viem';
  import { JSON_PRECOMPILE_ABI, JSON_PRECOMPILE_ADDRESS } from '@sei-js/precompiles';

  const data = { price: 100, symbol: 'SEI' };
  const inputBytes = toBytes(JSON.stringify(data));

  // Extract a string value
  const symbolBytes = await client.readContract({
    address: JSON_PRECOMPILE_ADDRESS,
    abi: JSON_PRECOMPILE_ABI,
    functionName: 'extractAsBytes',
    args: [inputBytes, 'symbol'],
  });

  // Extract a numeric value
  const price = await client.readContract({
    address: JSON_PRECOMPILE_ADDRESS,
    abi: JSON_PRECOMPILE_ABI,
    functionName: 'extractAsUint256',
    args: [inputBytes, 'price'],
  });
  ```

  ```ts ethers theme={"dark"}
  import { JSON_PRECOMPILE_ABI, JSON_PRECOMPILE_ADDRESS } from '@sei-js/precompiles';

  const jsonPrecompile = new ethers.Contract(JSON_PRECOMPILE_ADDRESS, JSON_PRECOMPILE_ABI, provider);

  const data = { price: 100, symbol: 'SEI' };
  const inputData = ethers.toUtf8Bytes(JSON.stringify(data));

  // Extract a string value
  const symbolBytes = await jsonPrecompile.extractAsBytes(inputData, 'symbol');
  const symbol = ethers.toUtf8String(symbolBytes);

  // Extract a numeric value
  const price = await jsonPrecompile.extractAsUint256(inputData, 'price');

  console.log(`${symbol}: ${price}`);
  ```
</CodeGroup>

## Common Patterns

### Error Handling

Wrap precompile calls in try/catch and check for specific error codes:

```ts theme={"dark"}
try {
  const tx = await staking.delegate('seivaloper1...', { value: ethers.parseEther('10') });
  const receipt = await tx.wait();
  console.log('Success:', receipt.hash);
} catch (err: any) {
  if (err.code === 'INSUFFICIENT_FUNDS') {
    console.error('Not enough SEI');
  } else if (err.code === 4001 || err.code === 'ACTION_REJECTED') {
    console.log('User rejected');
  } else {
    console.error('Transaction failed:', err.message);
  }
}
```

### Batch Read Operations

Fetch multiple precompile values in parallel:

```ts theme={"dark"}
const [delegation1, delegation2, rewards] = await Promise.all([
  readStaking.delegation(address, validator1),
  readStaking.delegation(address, validator2),
  distribution.delegationTotalRewards(address),
]);
```

### Gas Limits

Precompile calls that write state need enough gas. Use `estimateGas` rather than hard-coding:

```ts viem theme={"dark"}
const gas = await client.estimateGas({
  account,
  address: STAKING_PRECOMPILE_ADDRESS,
  abi: STAKING_PRECOMPILE_ABI,
  functionName: 'delegate',
  args: ['seivaloper1...'],
  value: parseEther('10'),
});
```

## Full Working Example

A Node.js script that delegates SEI and then casts a governance vote:

```ts theme={"dark"}
import { ethers } from 'ethers';
import {
  STAKING_PRECOMPILE_ABI, STAKING_PRECOMPILE_ADDRESS,
  GOVERNANCE_PRECOMPILE_ABI, GOVERNANCE_PRECOMPILE_ADDRESS,
} from '@sei-js/precompiles';

async function main() {
  const provider = new ethers.JsonRpcProvider('https://evm-rpc.sei-apis.com');
  const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);

  const staking = new ethers.Contract(STAKING_PRECOMPILE_ADDRESS, STAKING_PRECOMPILE_ABI, wallet);
  const governance = new ethers.Contract(GOVERNANCE_PRECOMPILE_ADDRESS, GOVERNANCE_PRECOMPILE_ABI, wallet);

  // Check current delegation
  const readStaking = staking.connect(provider) as typeof staking;
  const delegation = await readStaking.delegation(wallet.address, 'seivaloper1...');
  console.log('Current delegation:', delegation.balance.amount.toString());

  // Delegate 1 SEI
  const delegateTx = await staking.delegate('seivaloper1...', { value: ethers.parseEther('1') });
  await delegateTx.wait();
  console.log('Delegated 1 SEI');

  // Vote Yes on proposal 99
  const voteTx = await governance.vote(99n, 1);
  await voteTx.wait();
  console.log('Vote cast');
}

main().catch(console.error);
```

Run with:

```bash theme={"dark"}
PRIVATE_KEY=your_key npx tsx script.ts
```

## Next Steps

For full ABI reference and all available functions on each precompile:

* [Staking Precompile →](/evm/precompiles/staking)
* [Governance Precompile →](/evm/precompiles/governance)
* [Distribution Precompile →](/evm/precompiles/distribution)
* [JSON Precompile →](/evm/precompiles/json)
* [P256 Precompile →](/evm/precompiles/p256-precompile)
