> ## Documentation Index
> Fetch the complete documentation index at: https://seilabs-docs-remove-retired-sei-rpcs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Sei EVM JSON-RPC API Reference

> Comprehensive reference documentation for Sei's EVM JSON-RPC API endpoints, including standard Ethereum methods and Sei-specific extensions for developers.

export const RPCMethodsViewer = () => {
  const NETWORKS = {
    mainnet: {
      label: 'Pacific-1 · Mainnet',
      chainId: '1329',
      http: 'https://evm-rpc.sei-apis.com',
      ws: 'wss://evm-ws.sei-apis.com'
    },
    testnet: {
      label: 'Atlantic-2 · Testnet',
      chainId: '1328',
      http: 'https://evm-rpc-testnet.sei-apis.com',
      ws: 'wss://evm-ws-testnet.sei-apis.com'
    }
  };
  const NAMESPACE_META = {
    eth: {
      label: 'eth',
      color: '#b05c6c',
      blurb: 'Standard Ethereum methods — accounts, balances, blocks, transactions, logs, calls, and filters.'
    },
    debug: {
      label: 'debug',
      color: '#966f22',
      blurb: 'Transaction and block tracing.'
    },
    txpool: {
      label: 'txpool',
      color: '#3b82f6',
      blurb: 'Transaction-pool inspection.'
    },
    net: {
      label: 'net',
      color: '#0d9488',
      blurb: 'Network metadata.'
    },
    web3: {
      label: 'web3',
      color: '#7c3aed',
      blurb: 'Client metadata.'
    },
    sei: {
      label: 'sei',
      color: '#600014',
      blurb: 'Remaining legacy Sei extensions for address resolution, cross-VM lookup, and synthetic receipts.',
      deprecated: true
    },
    admin: {
      label: 'admin',
      color: '#6b7280',
      blurb: 'Node administration — not exposed on Sei.',
      unavailable: true
    },
    miner: {
      label: 'miner',
      color: '#6b7280',
      blurb: 'Mining control — not applicable (no proof-of-work).',
      unavailable: true
    },
    clique: {
      label: 'clique',
      color: '#6b7280',
      blurb: 'Clique proof-of-authority — not applicable (CometBFT consensus).',
      unavailable: true
    },
    engine: {
      label: 'engine',
      color: '#6b7280',
      blurb: 'Consensus Engine API — not applicable (CometBFT consensus).',
      unavailable: true
    },
    les: {
      label: 'les',
      color: '#6b7280',
      blurb: 'Light Ethereum Subprotocol — not exposed on Sei.',
      unavailable: true
    },
    personal: {
      label: 'personal',
      color: '#6b7280',
      blurb: 'Hosted-key account management — not exposed on Sei.',
      unavailable: true
    }
  };
  const NAMESPACE_ORDER = ['eth', 'debug', 'txpool', 'net', 'web3', 'sei', 'admin', 'miner', 'clique', 'engine', 'les', 'personal'];
  const STATUS_META = {
    supported: {
      label: 'Supported',
      dark: '#22c55e',
      light: '#16a34a',
      tip: 'Implemented with standard Ethereum behavior.'
    },
    limited: {
      label: 'Limited',
      dark: '#f59e0b',
      light: '#b45309',
      tip: 'Works, but is deprecated, returns a static value, or has a Sei-specific caveat.'
    },
    unsupported: {
      label: 'Unavailable',
      dark: '#9ca3af',
      light: '#6b7280',
      tip: 'Not registered on Sei, explicitly errors, or not applicable to Sei’s architecture.'
    }
  };
  const LANGUAGES = [{
    id: 'curl',
    name: 'cURL'
  }, {
    id: 'cast',
    name: 'cast'
  }, {
    id: 'javascript',
    name: 'JavaScript'
  }, {
    id: 'typescript',
    name: 'TypeScript'
  }, {
    id: 'python',
    name: 'Python'
  }, {
    id: 'go',
    name: 'Go'
  }, {
    id: 'rust',
    name: 'Rust'
  }, {
    id: 'java',
    name: 'Java'
  }, {
    id: 'kotlin',
    name: 'Kotlin'
  }, {
    id: 'swift',
    name: 'Swift'
  }, {
    id: 'csharp',
    name: 'C#'
  }];
  const SEI_RPC_METHODS = [{
    "namespace": "eth",
    "name": "eth_blockNumber",
    "status": "supported",
    "description": "Returns the number of the most recent committed EVM block as a hex uint64.",
    "seiNote": "Block height comes from CometBFT latest height; the latest committed block is already final on Sei (instant finality, so latest == safe == finalized)."
  }, {
    "namespace": "eth",
    "name": "eth_chainId",
    "status": "supported",
    "description": "Returns the EVM chain ID as a hex big int.",
    "seiNote": "Sourced from the x/evm keeper. Mainnet (pacific-1) = 1329 (0x531); testnet (atlantic-2) = 1328 (0x530)."
  }, {
    "namespace": "eth",
    "name": "eth_coinbase",
    "status": "limited",
    "description": "Returns the block reward beneficiary (coinbase) address.",
    "seiNote": "Sei has no miner; this returns the Cosmos fee-collector module address (GetFeeCollectorAddress), not a validator/miner address. The COINBASE opcode returns the same value."
  }, {
    "namespace": "eth",
    "name": "eth_accounts",
    "status": "limited",
    "description": "Returns the list of addresses for which the node holds hosted keys.",
    "seiNote": "Sourced from the node's local test keyring only; production/public RPC nodes hold no hosted keys, so this returns an empty list. Sign client-side and use eth_sendRawTransaction."
  }, {
    "namespace": "eth",
    "name": "eth_gasPrice",
    "status": "limited",
    "description": "Returns a suggested gas price in wei (hex).",
    "seiNote": "Sei-specific congestion heuristic, not a raw mempool oracle. InfoAPI.GasPrice/GasPriceHelper (info.go): when uncongested it returns baseFee * 110/100 (base fee +10%); when congested it returns medianRewardPrevBlock + baseFee (50th-percentile priority-fee reward from the previous block added to base fee). The base fee comes from the x/evm keeper (GetNextBaseFeePerGas), which is itself floored at the governance-set minimum base fee; the RPC handler applies no additional explicit lower-bound clamp. The mainnet minimum gas price (~50 gwei) is enforced for transaction acceptance at the mempool/ante-handler level, not inside eth_gasPrice."
  }, {
    "namespace": "eth",
    "name": "eth_maxPriorityFeePerGas",
    "status": "limited",
    "description": "Returns a suggested priority fee (tip) per gas in wei (hex).",
    "seiNote": "Sei-specific: returns a hardcoded 1 gwei (defaultPriorityFeePerGas) when the chain is uncongested; only when congested does it derive the tip from the previous block's 50th-percentile reward. Sei docs advise using a single gasPrice and omitting EIP-1559 fee fields."
  }, {
    "namespace": "eth",
    "name": "eth_feeHistory",
    "status": "supported",
    "description": "Returns base fees, gas-used ratios, and reward percentile data over a range of blocks.",
    "seiNote": "Base fees and rewards reflect Sei's x/evm fee market (GetNextBaseFee), not an Ethereum EIP-1559 mempool, and Sei does not burn the base fee. Watermark-aware: pruned/historical blocks may not be available as far back as on Ethereum archive nodes.",
    "params": [{
      "name": "blockCount",
      "type": "QUANTITY",
      "description": "Number of blocks in the requested range.",
      "example": "0x5"
    }, {
      "name": "newestBlock",
      "type": "BLOCKNUMBER",
      "description": "Highest block of the range (number or tag).",
      "example": "latest"
    }, {
      "name": "rewardPercentiles",
      "type": "array of float",
      "description": "Monotonically increasing percentiles to sample for priority-fee rewards.",
      "example": "[25,50,75]"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_blobBaseFee",
    "status": "unsupported",
    "description": "EIP-4844 blob base fee. Registered but always returns an unsupported error.",
    "seiNote": "Always returns JSON-RPC error -32000 with message 'blobs not supported on this chain'. Sei does not implement EIP-4844 blob transactions."
  }, {
    "namespace": "eth",
    "name": "eth_syncing",
    "status": "unsupported",
    "description": "Sync status. Registered but always returns an unsupported error instead of false/a sync object.",
    "seiNote": "InfoAPI.Syncing returns a JSON-RPC error with the exact message 'eth_syncing is not supported on Sei EVM RPC' (via ErrEVMNotSupported, code -32000, not -32601). Sei does not expose Ethereum sync semantics here; query CometBFT status endpoints instead."
  }, {
    "namespace": "eth",
    "name": "eth_getBalance",
    "status": "supported",
    "description": "Returns the wei balance of an account at a given block.",
    "seiNote": "Balance reflects the account's SEI bank balance (18-decimal wei representation) and can change from both EVM and non-EVM (Cosmos bank send / wasm) transactions. Height is resolved via the watermark manager with a state-version guard.",
    "params": [{
      "name": "address",
      "type": "DATA, 20 bytes",
      "description": "Account address.",
      "example": "0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55"
    }, {
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Block number, tag (latest/earliest/pending/safe/finalized), or hash.",
      "example": "latest"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getCode",
    "status": "supported",
    "description": "Returns the contract bytecode at an address for a given block.",
    "params": [{
      "name": "address",
      "type": "DATA, 20 bytes",
      "description": "Contract address.",
      "example": "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7"
    }, {
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Block number, tag, or hash.",
      "example": "latest"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getStorageAt",
    "status": "supported",
    "description": "Returns the value stored at a storage slot of an address at a given block.",
    "seiNote": "Reads the EVM keeper's slot value directly rather than from an MPT trie. The slot key must decode to at most 32 bytes.",
    "params": [{
      "name": "address",
      "type": "DATA, 20 bytes",
      "description": "Contract address.",
      "example": "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7"
    }, {
      "name": "key",
      "type": "DATA, 32 bytes",
      "description": "Storage slot key (hex, up to 32 bytes).",
      "example": "0x0"
    }, {
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Block number, tag, or hash.",
      "example": "latest"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getProof",
    "status": "limited",
    "description": "Returns a Merkle proof for an account and the requested storage slots.",
    "seiNote": "Sei stores state in an IAVL tree, not an Ethereum Merkle-Patricia trie. The result is a Sei-specific ProofResult{address, hexValues, storageProof} where storageProof entries are CometBFT/IAVL crypto.ProofOps, NOT eth-style MPT proof nodes. There is no accountProof, balance, codeHash, nonce, or storageHash field (Sei has no per-account state root); standard eth_getProof verifiers will not work.",
    "params": [{
      "name": "address",
      "type": "DATA, 20 bytes",
      "description": "Account address.",
      "example": "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7"
    }, {
      "name": "storageKeys",
      "type": "array of DATA, 32 bytes",
      "description": "Storage slot keys to prove (bounded by MaxStorageKeysPerProof).",
      "example": "[\"0x0\"]"
    }, {
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Block number, tag, or hash.",
      "example": "latest"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getNonce",
    "status": "limited",
    "description": "Sei-specific helper that returns the current EVM nonce for an address (latest state only).",
    "seiNote": "Non-standard Sei extension exposed as eth_getNonce, implemented as StateAPI.GetNonce in state.go (NOT on TransactionAPI). Unlike eth_getTransactionCount it takes no block tag (latest-only via ctxProvider(LatestCtxHeight)) and returns a bare uint64 with no block-tag argument. Prefer eth_getTransactionCount for standard nonce queries.",
    "params": [{
      "name": "address",
      "type": "DATA, 20 bytes",
      "description": "Account address.",
      "example": "0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_call",
    "status": "supported",
    "description": "Executes a read-only message call against state without creating a transaction; supports state and block overrides.",
    "seiNote": "Gas is capped by RPCGasCap and execution time by RPCEVMTimeout; a fail-fast limiter may reject with 'eth_call rejected due to rate limit: server busy'. Canonical EVM<->Sei address resolution uses eth_call to the addr precompile at 0x0000000000000000000000000000000000001004.",
    "params": [{
      "name": "args",
      "type": "object",
      "description": "Call object (to, from, data/input, gas, gasPrice/maxFeePerGas, value).",
      "example": "{\"to\":\"0x0000000000000000000000000000000000001004\",\"data\":\"0x0c3c20ed000000000000000000000000Da52B9E673d1f48FcD9916b3F606A136a8eA5e55\"}"
    }, {
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Block number, tag, or hash. Defaults to latest.",
      "example": "latest"
    }, {
      "name": "overrides",
      "type": "object",
      "description": "Optional per-account state overrides (balance, code, nonce, state).",
      "example": "{}"
    }, {
      "name": "blockOverrides",
      "type": "object",
      "description": "Optional block-context overrides (number, time, coinbase).",
      "example": "{}"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_estimateGas",
    "status": "supported",
    "description": "Estimates the gas needed to execute a transaction.",
    "seiNote": "Bounded by RPCGasCap and protected by a fail-fast limiter. Block gas limit on Sei is 12.5M; parallel execution can cause estimates to vary slightly, so size gasLimit with a modest buffer.",
    "params": [{
      "name": "args",
      "type": "object",
      "description": "Transaction call object.",
      "example": "{\"to\":\"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\",\"data\":\"0x18160ddd\"}"
    }, {
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Optional block number, tag, or hash; defaults to latest.",
      "example": "latest"
    }, {
      "name": "overrides",
      "type": "object",
      "description": "Optional state overrides.",
      "example": "{}"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_estimateGasAfterCalls",
    "status": "limited",
    "description": "Estimates gas for a transaction after first applying a sequence of preceding calls against the same simulated state.",
    "seiNote": "Non-standard Sei/geth extension (not part of the standard Ethereum JSON-RPC spec). Same gas-cap and fail-fast-limiter behavior as eth_estimateGas.",
    "params": [{
      "name": "args",
      "type": "object",
      "description": "The final call to estimate gas for.",
      "example": "{\"to\":\"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\",\"data\":\"0x\"}"
    }, {
      "name": "calls",
      "type": "array of object",
      "description": "Ordered list of preceding calls applied before the estimate.",
      "example": "[]"
    }, {
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Optional block number, tag, or hash; defaults to latest.",
      "example": "latest"
    }, {
      "name": "overrides",
      "type": "object",
      "description": "Optional state overrides.",
      "example": "{}"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_createAccessList",
    "status": "supported",
    "description": "Generates an EIP-2930 access list (and gas used) for a transaction.",
    "seiNote": "Defaults to the pending block tag (matching geth). A VM error during simulation is surfaced in the result's 'error' field rather than failing the RPC.",
    "params": [{
      "name": "args",
      "type": "object",
      "description": "Transaction call object.",
      "example": "{\"to\":\"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\",\"data\":\"0x\"}"
    }, {
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Optional block number, tag, or hash; defaults to pending.",
      "example": "pending"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_sendRawTransaction",
    "status": "supported",
    "description": "Submits a signed, RLP-encoded raw EVM transaction to the network and returns its hash.",
    "seiNote": "Decodes to an ethtypes.Transaction, wraps it in a Cosmos MsgEVMTransaction, and broadcasts via CometBFT (async BroadcastTx by default; slow mode uses BroadcastTxCommit). Non-zero CheckTx codes surface as ABCI errors, not geth mempool errors. Legacy (non-1559) txs must set gasPrice at or above the governance minimum (currently 50 gwei on mainnet); blob (EIP-4844) txs are not enabled. Supports per-sender EvmProxy forwarding.",
    "params": [{
      "name": "data",
      "type": "DATA",
      "description": "Signed, RLP-encoded transaction bytes (0x-prefixed).",
      "example": "0x02f8b101808459682f00..."
    }]
  }, {
    "namespace": "eth",
    "name": "eth_sendTransaction",
    "status": "limited",
    "description": "Signs (with a node-hosted key) and submits a transaction in one call.",
    "seiNote": "Requires the 'from' address's private key in the node's local test keyring; production/public RPC nodes hold no hosted keys, so this returns 'from address does not have hosted key'. Always signs as LegacyTxType. Sign client-side and use eth_sendRawTransaction instead.",
    "params": [{
      "name": "args",
      "type": "object",
      "description": "Transaction object (from, to, value, data, gas, nonce, etc.).",
      "example": "{\"from\":\"0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55\",\"to\":\"0x7507454444fa193d39f1392076bc784b77a7a8ff\",\"value\":\"0x1\"}"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_signTransaction",
    "status": "limited",
    "description": "Signs a transaction with a node-hosted key and returns the signed payload without broadcasting.",
    "seiNote": "Requires a node-hosted key for the from address; not usable on public RPC nodes that hold no keys. Returns both the raw RLP bytes and the decoded tx.",
    "params": [{
      "name": "args",
      "type": "object",
      "description": "SendTxArgs transaction object to sign (from, to, gas, gasPrice, value, nonce, data).",
      "example": "{\"from\":\"0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55\",\"to\":\"0x7507454444fa193d39f1392076bc784b77a7a8ff\",\"value\":\"0x1\",\"nonce\":\"0x0\",\"gas\":\"0x5208\",\"gasPrice\":\"0x3b9aca00\"}"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_sign",
    "status": "limited",
    "description": "Signs an EIP-191 personal message with a node-hosted key for the given address.",
    "seiNote": "Only works for addresses in the node's local test keyring; production/public RPC nodes hold no hosted keys, so this returns 'address does not have hosted key'. Applies the EIP-191 personal-message TextHash before signing.",
    "params": [{
      "name": "address",
      "type": "DATA, 20 bytes",
      "description": "Address whose hosted key signs the data.",
      "example": "0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55"
    }, {
      "name": "data",
      "type": "DATA",
      "description": "Message bytes to sign.",
      "example": "0xdeadbeef"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getBlockByNumber",
    "status": "supported",
    "description": "Returns block information by number or tag, with full transactions when fullTx is true.",
    "seiNote": "Under the eth namespace only EVM transactions are indexed (synthetic/bank-transfer txs excluded). Block number 0 returns a synthetic genesis block (for The Graph compatibility); future/non-existent numeric blocks return null. Uncle/PoW header fields (sha3Uncles, nonce, mixHash, difficulty) are placeholders and the uncles array is always empty (CometBFT consensus). safe/finalized/latest are equivalent due to instant finality.",
    "params": [{
      "name": "number",
      "type": "BLOCKNUMBER",
      "description": "Block number (hex) or tag (latest/safe/finalized/pending/earliest).",
      "example": "latest"
    }, {
      "name": "fullTx",
      "type": "boolean",
      "description": "If true include full transaction objects, else only hashes.",
      "example": "true"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getBlockByHash",
    "status": "supported",
    "description": "Returns block information by block hash, with full transactions when fullTx is true.",
    "seiNote": "Block hashes are CometBFT block hashes (computed from the Tendermint header), so they differ from Ethereum block hashes and are not interchangeable across chains. Under the eth namespace synthetic txs and bank transfers are excluded. The genesis hash returns a synthetic genesis block; unknown/zero hash returns null. Uncles array is always empty.",
    "params": [{
      "name": "blockHash",
      "type": "DATA, 32 bytes",
      "description": "Block hash.",
      "example": "0x5620c15afd9a1d0ab19d7560043df6e038d731c6205974dca7a55900071e3864"
    }, {
      "name": "fullTx",
      "type": "boolean",
      "description": "If true include full transaction objects, else only hashes.",
      "example": "false"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getBlockTransactionCountByNumber",
    "status": "supported",
    "description": "Returns the number of EVM transactions in a block by number, as a hex quantity.",
    "seiNote": "Counts EVM transactions only (via getEvmTxCount); synthetic/bank-transfer txs are excluded. Genesis returns 0x0; non-existent/future blocks return null.",
    "params": [{
      "name": "number",
      "type": "BLOCKNUMBER",
      "description": "Block number or tag.",
      "example": "latest"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getBlockTransactionCountByHash",
    "status": "supported",
    "description": "Returns the number of EVM transactions in a block by hash, as a hex quantity.",
    "seiNote": "Counts EVM transactions only; synthetic/bank-transfer txs are excluded. Genesis hash returns 0x0; unknown hash returns null.",
    "params": [{
      "name": "blockHash",
      "type": "DATA, 32 bytes",
      "description": "Block hash.",
      "example": "0x5620c15afd9a1d0ab19d7560043df6e038d731c6205974dca7a55900071e3864"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getBlockReceipts",
    "status": "supported",
    "description": "Returns all EVM transaction receipts for a given block.",
    "seiNote": "Under the eth namespace synthetic/shell receipts are excluded (includeShellReceipts=false). Genesis returns an empty array; zero hash returns null. transactionIndex is recomputed sequentially over the compacted receipt list.",
    "params": [{
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Block number, tag, or hash.",
      "example": "latest"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getTransactionByHash",
    "status": "supported",
    "description": "Returns the EVM transaction matching the given hash, or null if not found.",
    "seiNote": "Sees EVM transactions only; if the hash resolves to a non-EVM Cosmos tx it errors. Pending lookups read from the CometBFT mempool, not a geth txpool.",
    "params": [{
      "name": "hash",
      "type": "DATA, 32 bytes",
      "description": "Transaction hash.",
      "example": "0x828c91592453fe7c5bf743204495a35bf02b67b579b8f59ee7eea8af031d7c14"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getTransactionReceipt",
    "status": "supported",
    "description": "Returns the receipt of a transaction by hash, or null if not found.",
    "seiNote": "Receipt is reconstructed from keeper.GetReceipt + CometBFT block data rather than from a native MPT receipt trie; status/logs are standard Ethereum format.",
    "params": [{
      "name": "hash",
      "type": "DATA, 32 bytes",
      "description": "Transaction hash.",
      "example": "0x828c91592453fe7c5bf743204495a35bf02b67b579b8f59ee7eea8af031d7c14"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getTransactionByBlockNumberAndIndex",
    "status": "supported",
    "description": "Returns the EVM transaction at the given index within the block at the specified number.",
    "seiNote": "Index maps over EVM transactions only; an out-of-range index yields a null result rather than an error.",
    "params": [{
      "name": "blockNr",
      "type": "BLOCKNUMBER",
      "description": "Block number or tag.",
      "example": "latest"
    }, {
      "name": "index",
      "type": "QUANTITY",
      "description": "Transaction index within the block.",
      "example": "0x0"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getTransactionByBlockHashAndIndex",
    "status": "supported",
    "description": "Returns the EVM transaction at the given index within the block identified by hash.",
    "seiNote": "Index maps over EVM transactions only; same null-on-overflow semantics as the block-number variant.",
    "params": [{
      "name": "blockHash",
      "type": "DATA, 32 bytes",
      "description": "Block hash.",
      "example": "0x5620c15afd9a1d0ab19d7560043df6e038d731c6205974dca7a55900071e3864"
    }, {
      "name": "index",
      "type": "QUANTITY",
      "description": "Transaction index within the block.",
      "example": "0x0"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getTransactionCount",
    "status": "supported",
    "description": "Returns the number of transactions sent from an address (nonce) at a given block.",
    "seiNote": "For the 'pending' tag Sei returns EvmNextPendingNonce from the CometBFT mempool (or redirects to an EvmProxy if the sender is sharded there). safe/finalized/latest are equivalent due to instant finality.",
    "params": [{
      "name": "address",
      "type": "DATA, 20 bytes",
      "description": "Account address.",
      "example": "0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55"
    }, {
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Block number, tag, or hash; 'pending' returns the next pending nonce.",
      "example": "latest"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getVMError",
    "status": "limited",
    "description": "Sei extension that returns the EVM VM error string recorded in a transaction's receipt by hash.",
    "seiNote": "Non-standard Sei extension registered under the eth namespace. Returns the receipt's VmError field and propagates a not-found error (unlike eth_getTransactionErrorByHash, which returns an empty string on not-found).",
    "params": [{
      "name": "hash",
      "type": "DATA, 32 bytes",
      "description": "Transaction hash.",
      "example": "0x828c91592453fe7c5bf743204495a35bf02b67b579b8f59ee7eea8af031d7c14"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getTransactionErrorByHash",
    "status": "limited",
    "description": "Sei extension that returns the recorded VM error string for a transaction by hash (empty string if it succeeded or is not found).",
    "seiNote": "Non-standard Sei extension registered under the eth namespace. Unlike eth_getVMError, a not-found lookup returns an empty string and no error.",
    "params": [{
      "name": "hash",
      "type": "DATA, 32 bytes",
      "description": "Transaction hash.",
      "example": "0x828c91592453fe7c5bf743204495a35bf02b67b579b8f59ee7eea8af031d7c14"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_newFilter",
    "status": "supported",
    "description": "Creates a log filter for the given criteria and returns a filter ID for later polling.",
    "seiNote": "Subject to the same range/size caps as eth_getLogs: open-ended ranges return up to 10,000 logs (DefaultMaxLogLimit); close-ended ranges are limited to 2,000 blocks (DefaultMaxBlockRange), with large-query rate limiting.",
    "params": [{
      "name": "crit",
      "type": "object",
      "description": "Filter criteria: fromBlock, toBlock (or blockHash), address(es), and topics.",
      "example": "{\"fromBlock\":\"latest\",\"address\":\"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\",\"topics\":[]}"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_newBlockFilter",
    "status": "supported",
    "description": "Creates a filter that tracks newly arrived block hashes and returns its ID."
  }, {
    "namespace": "eth",
    "name": "eth_newPendingTransactionFilter",
    "status": "unsupported",
    "description": "Pending-transaction filter. Registered but always returns an unsupported error.",
    "seiNote": "Always returns JSON-RPC -32000. Sei has no geth-style public pending mempool to filter; the corresponding newPendingTransactions subscription type is likewise unavailable."
  }, {
    "namespace": "eth",
    "name": "eth_getFilterChanges",
    "status": "supported",
    "description": "Polls a filter and returns new logs (log filters) or block hashes (block filters) since the last poll.",
    "params": [{
      "name": "filterID",
      "type": "QUANTITY/ID",
      "description": "Filter ID from a New*Filter call.",
      "example": "0x1"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getFilterLogs",
    "status": "supported",
    "description": "Returns all logs matching a previously created log filter, including historical logs.",
    "seiNote": "Bounded by the same caps as eth_getLogs (2,000-block range, 10,000-log limit) with large-query rate limiting.",
    "params": [{
      "name": "filterID",
      "type": "QUANTITY/ID",
      "description": "Filter ID from a NewFilter call.",
      "example": "0x1"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getLogs",
    "status": "supported",
    "description": "Returns logs matching the given filter criteria.",
    "seiNote": "Returns EVM logs only. Hard limits: max 2,000 blocks per close-ended query and up to 10,000 logs per response; exceeding the range errors with 'block range too large'. Large queries are globally rate-limited.",
    "params": [{
      "name": "crit",
      "type": "object",
      "description": "Filter criteria: fromBlock, toBlock (or blockHash), address(es), topics.",
      "example": "{\"fromBlock\":\"0x0\",\"toBlock\":\"latest\",\"address\":\"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\",\"topics\":[]}"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_uninstallFilter",
    "status": "supported",
    "description": "Removes a previously installed filter by ID; returns true if it existed and was removed.",
    "seiNote": "Returns false if the filter did not exist rather than erroring. Filters also expire automatically when not polled.",
    "params": [{
      "name": "filterID",
      "type": "QUANTITY/ID",
      "description": "Filter ID to remove.",
      "example": "0x1"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_subscribe",
    "status": "limited",
    "description": "Opens a WebSocket-only push subscription for newHeads or logs notifications.",
    "seiNote": "WebSocket-only (SubscriptionAPI is not registered on the HTTP server; returns rpc.ErrNotificationsUnsupported over HTTP). Only 'newHeads' and 'logs' are implemented in source; there is no 'newPendingTransactions' subscription despite some client docs implying otherwise. newHeads subscriptions are capped by MaxSubscriptionsNewHead.",
    "params": [{
      "name": "subscriptionType",
      "type": "string",
      "description": "Subscription name: 'newHeads' or 'logs'.",
      "example": "newHeads"
    }, {
      "name": "filter",
      "type": "object",
      "description": "Optional filter criteria (address/topics) for the 'logs' subscription.",
      "example": "{\"address\":\"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\",\"topics\":[]}"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_unsubscribe",
    "status": "supported",
    "description": "Cancels an existing WebSocket subscription by ID; returns true on success.",
    "seiNote": "WebSocket only; has no effect over HTTP (notifications unsupported there).",
    "params": [{
      "name": "subscriptionID",
      "type": "string",
      "description": "The subscription ID returned by a prior eth_subscribe call.",
      "example": "0x9cef478923ff08bf67fde6c64013158d"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_mining",
    "status": "unsupported",
    "description": "Whether the node is mining. Not registered on Sei.",
    "seiNote": "Sei uses CometBFT proof-of-stake consensus with no PoW mining; the method is not registered and returns -32601 method not found."
  }, {
    "namespace": "eth",
    "name": "eth_hashrate",
    "status": "unsupported",
    "description": "Node mining hashrate. Not registered on Sei.",
    "seiNote": "No PoW mining on Sei (CometBFT consensus); not registered, returns -32601 method not found."
  }, {
    "namespace": "eth",
    "name": "eth_getWork",
    "status": "unsupported",
    "description": "PoW work package (current header hash, seed, target). Not registered on Sei.",
    "seiNote": "The proof-of-work concept does not exist under Sei's CometBFT consensus; not registered."
  }, {
    "namespace": "eth",
    "name": "eth_submitWork",
    "status": "unsupported",
    "description": "Submit a PoW solution. Not registered on Sei.",
    "seiNote": "PoW submission is meaningless on Sei (CometBFT PoS); not registered.",
    "params": [{
      "name": "nonce",
      "type": "DATA, 8 bytes",
      "description": "Found PoW nonce.",
      "example": "0x0000000000000001"
    }, {
      "name": "powHash",
      "type": "DATA, 32 bytes",
      "description": "Header pow-hash.",
      "example": "0x0000000000000000000000000000000000000000000000000000000000000000"
    }, {
      "name": "mixDigest",
      "type": "DATA, 32 bytes",
      "description": "Mix digest.",
      "example": "0x0000000000000000000000000000000000000000000000000000000000000000"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_submitHashrate",
    "status": "unsupported",
    "description": "Submit a node's mining hashrate. Not registered on Sei.",
    "seiNote": "No PoW mining on Sei; not registered.",
    "params": [{
      "name": "hashrate",
      "type": "QUANTITY",
      "description": "Hashrate value (hex).",
      "example": "0x500000"
    }, {
      "name": "id",
      "type": "DATA, 32 bytes",
      "description": "Random hex ID identifying the client.",
      "example": "0x59daa26581d0acd1fce254fb7e85952f4c09d0915afd33d3886cd914bc7d283c"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_protocolVersion",
    "status": "unsupported",
    "description": "Ethereum (devp2p) protocol version. Not registered on Sei.",
    "seiNote": "Sei does not expose the Ethereum devp2p protocol version; not registered, returns -32601 method not found."
  }, {
    "namespace": "eth",
    "name": "eth_getUncleCountByBlockNumber",
    "status": "unsupported",
    "description": "Uncle count by block number. Not registered; Sei has no uncles.",
    "seiNote": "Sei uses CometBFT (single canonical chain, no uncles/ommers); not registered, returns -32601.",
    "params": [{
      "name": "number",
      "type": "BLOCKNUMBER",
      "description": "Block number or tag.",
      "example": "latest"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getUncleCountByBlockHash",
    "status": "unsupported",
    "description": "Uncle count by block hash. Not registered; Sei has no uncles.",
    "seiNote": "No uncle blocks under CometBFT consensus; not registered, returns -32601.",
    "params": [{
      "name": "blockHash",
      "type": "DATA, 32 bytes",
      "description": "Block hash.",
      "example": "0x5620c15afd9a1d0ab19d7560043df6e038d731c6205974dca7a55900071e3864"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getUncleByBlockNumberAndIndex",
    "status": "unsupported",
    "description": "Uncle block by number and index. Not registered; Sei has no uncles.",
    "seiNote": "No uncle blocks under CometBFT consensus; not registered, returns -32601.",
    "params": [{
      "name": "number",
      "type": "BLOCKNUMBER",
      "description": "Block number or tag.",
      "example": "latest"
    }, {
      "name": "index",
      "type": "QUANTITY",
      "description": "Uncle index.",
      "example": "0x0"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_getUncleByBlockHashAndIndex",
    "status": "unsupported",
    "description": "Uncle block by hash and index. Not registered; Sei has no uncles.",
    "seiNote": "No uncle blocks under CometBFT consensus; not registered, returns -32601.",
    "params": [{
      "name": "blockHash",
      "type": "DATA, 32 bytes",
      "description": "Block hash.",
      "example": "0x5620c15afd9a1d0ab19d7560043df6e038d731c6205974dca7a55900071e3864"
    }, {
      "name": "index",
      "type": "QUANTITY",
      "description": "Uncle index.",
      "example": "0x0"
    }]
  }, {
    "namespace": "eth",
    "name": "eth_pendingTransactions",
    "status": "unsupported",
    "description": "List pending transactions in the node's transaction pool. Not registered on Sei.",
    "seiNote": "Sei exposes no geth-style mempool through this method; pending state is surfaced only via the 'pending' tag on eth_getTransactionCount and via txpool_content. Not registered, returns -32601."
  }, {
    "namespace": "net",
    "name": "net_version",
    "status": "supported",
    "description": "Returns the network/chain ID as a decimal string.",
    "seiNote": "Returns the EVM chain ID in decimal (alias of eth_chainId): '1329' on pacific-1 mainnet, '1328' on atlantic-2 testnet."
  }, {
    "namespace": "net",
    "name": "net_listening",
    "status": "unsupported",
    "description": "Whether the node is listening for connections. Not registered on Sei.",
    "seiNote": "Not registered on Sei's NetAPI; returns -32601 method not found (P2P is handled by CometBFT, not this RPC)."
  }, {
    "namespace": "net",
    "name": "net_peerCount",
    "status": "unsupported",
    "description": "Number of connected peers. Not registered on Sei.",
    "seiNote": "Not registered on Sei's NetAPI; returns -32601. Query CometBFT net_info for peer data instead."
  }, {
    "namespace": "web3",
    "name": "web3_clientVersion",
    "status": "supported",
    "description": "Returns the client version string.",
    "seiNote": "Reports a synthetic 'Geth/<os>-<arch>/<goVersion>' string (Sei's EVM is backed by go-ethereum); it does NOT embed the actual sei-chain/seid version, so it is not a reliable Sei version indicator."
  }, {
    "namespace": "web3",
    "name": "web3_sha3",
    "status": "unsupported",
    "description": "Keccak-256 hash of the input. Not implemented in Sei's Web3API.",
    "seiNote": "Unlike go-ethereum, Sei's Web3API does not implement web3_sha3; it is not registered and returns -32601 method not found.",
    "params": [{
      "name": "data",
      "type": "DATA",
      "description": "Bytes to hash.",
      "example": "0x68656c6c6f20776f726c64"
    }]
  }, {
    "namespace": "txpool",
    "name": "txpool_content",
    "status": "limited",
    "description": "Returns the transactions currently in the pool, grouped by sender address and nonce into pending and queued buckets.",
    "seiNote": "Sei-specific simplification: every unconfirmed EVM tx from the CometBFT mempool is reported under 'pending' and 'queued' is always empty (no geth-style pending/queued nonce-gap distinction). The result set is truncated to the node's MaxTxPoolTxs config, so it may not reflect the entire mempool."
  }, {
    "namespace": "txpool",
    "name": "txpool_contentFrom",
    "status": "unsupported",
    "description": "Pending/queued transactions for a single account. Not implemented on Sei.",
    "seiNote": "Not registered; returns -32601 method not found. The only txpool method available on Sei is txpool_content.",
    "params": [{
      "name": "address",
      "type": "DATA, 20 bytes",
      "description": "The account address to filter by.",
      "example": "0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55"
    }]
  }, {
    "namespace": "txpool",
    "name": "txpool_status",
    "status": "unsupported",
    "description": "Counts of pending and queued transactions. Not implemented on Sei.",
    "seiNote": "Not registered; returns -32601 method not found."
  }, {
    "namespace": "txpool",
    "name": "txpool_inspect",
    "status": "unsupported",
    "description": "Human-readable summary of pending/queued transactions. Not implemented on Sei.",
    "seiNote": "Not registered; returns -32601 method not found."
  }, {
    "namespace": "debug",
    "name": "debug_traceTransaction",
    "status": "supported",
    "description": "Replays a transaction by hash and returns an execution trace using the configured tracer.",
    "seiNote": "HTTP-only (the debug namespace is not registered on the WebSocket server). Supports geth tracers (callTracer, prestateTracer, flatCallTracer, struct/opcode logger); callTracer/prestateTracer/flatCallTracer results are pre-baked/cached via TraceBaker. Requires trace-enabled/archive state for the target height.",
    "params": [{
      "name": "hash",
      "type": "DATA, 32 bytes",
      "description": "Transaction hash to trace.",
      "example": "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"
    }, {
      "name": "config",
      "type": "object",
      "description": "Optional tracer config (tracer name, tracerConfig, timeout, reexec, disableStorage/Stack/Memory).",
      "example": "{\"tracer\":\"callTracer\"}"
    }]
  }, {
    "namespace": "debug",
    "name": "debug_traceBlockByNumber",
    "status": "supported",
    "description": "Traces all transactions in a block by number and returns per-transaction execution traces.",
    "seiNote": "HTTP-only. safe/finalized/latest are equivalent due to instant finality.",
    "params": [{
      "name": "number",
      "type": "BLOCKNUMBER",
      "description": "Block number or tag.",
      "example": "latest"
    }, {
      "name": "config",
      "type": "object",
      "description": "Optional tracer config.",
      "example": "{\"tracer\":\"callTracer\"}"
    }]
  }, {
    "namespace": "debug",
    "name": "debug_traceBlockByHash",
    "status": "supported",
    "description": "Traces all transactions in a block by hash and returns per-transaction execution traces.",
    "seiNote": "HTTP-only.",
    "params": [{
      "name": "hash",
      "type": "DATA, 32 bytes",
      "description": "Block hash.",
      "example": "0x5620c15afd9a1d0ab19d7560043df6e038d731c6205974dca7a55900071e3864"
    }, {
      "name": "config",
      "type": "object",
      "description": "Optional tracer config.",
      "example": "{\"tracer\":\"callTracer\"}"
    }]
  }, {
    "namespace": "debug",
    "name": "debug_traceCall",
    "status": "supported",
    "description": "Executes and traces a call against a block's state without creating a transaction.",
    "seiNote": "HTTP-only. Arbitrary geth tracer names pass through. Tracing on the pending block is not supported.",
    "params": [{
      "name": "args",
      "type": "object",
      "description": "Transaction call object.",
      "example": "{\"to\":\"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\",\"data\":\"0x70a08231\"}"
    }, {
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Block number, tag, or hash.",
      "example": "latest"
    }, {
      "name": "config",
      "type": "object",
      "description": "Optional trace-call config (tracer name, state overrides, block overrides).",
      "example": "{\"tracer\":\"callTracer\"}"
    }]
  }, {
    "namespace": "debug",
    "name": "debug_traceStateAccess",
    "status": "limited",
    "description": "Sei extension that replays a transaction and returns its app/tendermint/receipt state-access traces.",
    "seiNote": "Sei-specific extension (not part of upstream go-ethereum's debug namespace). HTTP-only and subject to historical-debug-trace availability guards.",
    "params": [{
      "name": "hash",
      "type": "DATA, 32 bytes",
      "description": "Transaction hash whose state accesses are returned.",
      "example": "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"
    }]
  }, {
    "namespace": "debug",
    "name": "debug_traceTransactionProfile",
    "status": "limited",
    "description": "Sei extension that traces a transaction and returns the trace plus a phase-by-phase timing profile of the trace execution.",
    "seiNote": "Sei-specific extension (not part of upstream go-ethereum's debug namespace). Returns {trace, profile} where profile carries totalNanos, historicalDbLookupNanos, otherNanos, and per-phase timings. HTTP-only and subject to the max_trace_lookback_blocks historical guard.",
    "params": [{
      "name": "hash",
      "type": "DATA, 32 bytes",
      "description": "Transaction hash to trace and profile.",
      "example": "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"
    }, {
      "name": "config",
      "type": "object",
      "description": "Optional tracer config.",
      "example": "{\"tracer\":\"callTracer\"}"
    }]
  }, {
    "namespace": "debug",
    "name": "debug_getRawHeader",
    "status": "unsupported",
    "description": "RLP-encoded block header. Registered but always returns an unsupported error.",
    "seiNote": "Always returns JSON-RPC -32000. Sei block headers are CometBFT headers, not RLP-encoded Ethereum headers.",
    "params": [{
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Block number, tag, or hash.",
      "example": "latest"
    }]
  }, {
    "namespace": "debug",
    "name": "debug_getRawBlock",
    "status": "unsupported",
    "description": "RLP-encoded full block. Registered but always returns an unsupported error.",
    "seiNote": "Always returns JSON-RPC -32000; no canonical RLP-encoded Ethereum block exists on Sei.",
    "params": [{
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Block number, tag, or hash.",
      "example": "latest"
    }]
  }, {
    "namespace": "debug",
    "name": "debug_getRawReceipts",
    "status": "unsupported",
    "description": "RLP-encoded receipts for a block. Registered but always returns an unsupported error.",
    "seiNote": "Always returns JSON-RPC -32000.",
    "params": [{
      "name": "blockNrOrHash",
      "type": "BLOCKNUMBER or DATA",
      "description": "Block number, tag, or hash.",
      "example": "latest"
    }]
  }, {
    "namespace": "debug",
    "name": "debug_getRawTransaction",
    "status": "unsupported",
    "description": "RLP-encoded signed transaction by hash. Registered but always returns an unsupported error.",
    "seiNote": "Always returns JSON-RPC -32000.",
    "params": [{
      "name": "hash",
      "type": "DATA, 32 bytes",
      "description": "Transaction hash.",
      "example": "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"
    }]
  }, {
    "namespace": "debug",
    "name": "debug_storageRangeAt",
    "status": "unsupported",
    "description": "Range of storage entries for a contract at a block/tx. Not implemented on Sei.",
    "seiNote": "Not registered; returns -32601. Sei uses IAVL state, not an Ethereum MPT, so geth's MPT-based storage-range walk is not provided.",
    "params": [{
      "name": "blockHash",
      "type": "DATA, 32 bytes",
      "description": "Block hash.",
      "example": "0x5620c15afd9a1d0ab19d7560043df6e038d731c6205974dca7a55900071e3864"
    }, {
      "name": "txIndex",
      "type": "QUANTITY",
      "description": "Transaction index.",
      "example": "0x0"
    }, {
      "name": "address",
      "type": "DATA, 20 bytes",
      "description": "Contract address.",
      "example": "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7"
    }, {
      "name": "startKey",
      "type": "DATA",
      "description": "Start storage key.",
      "example": "0x00"
    }, {
      "name": "maxResult",
      "type": "QUANTITY",
      "description": "Maximum number of entries.",
      "example": "0x64"
    }]
  }, {
    "namespace": "debug",
    "name": "debug_traceBlock",
    "status": "unsupported",
    "description": "Trace a block supplied as raw RLP bytes. Not implemented on Sei.",
    "seiNote": "Not registered; returns -32601. Sei does not accept RLP-encoded Ethereum blocks; use debug_traceBlockByNumber/ByHash instead.",
    "params": [{
      "name": "blockRlp",
      "type": "DATA",
      "description": "RLP-encoded block bytes.",
      "example": "0xf90211..."
    }]
  }, {
    "namespace": "debug",
    "name": "debug_intermediateRoots",
    "status": "unsupported",
    "description": "Intermediate state roots while executing a block. Not implemented on Sei.",
    "seiNote": "Not registered; returns -32601. Sei uses IAVL state, not an Ethereum MPT, so per-transaction MPT intermediate roots are not produced.",
    "params": [{
      "name": "blockHash",
      "type": "DATA, 32 bytes",
      "description": "Block hash.",
      "example": "0x5620c15afd9a1d0ab19d7560043df6e038d731c6205974dca7a55900071e3864"
    }, {
      "name": "config",
      "type": "object",
      "description": "Optional trace config.",
      "example": "{}"
    }]
  }, {
    "namespace": "debug",
    "name": "debug_setHead",
    "status": "unsupported",
    "description": "Rewind the chain head to a given block. Not implemented on Sei.",
    "seiNote": "Not registered; returns -32601. The chain head is controlled by CometBFT consensus, not the EVM RPC layer.",
    "params": [{
      "name": "number",
      "type": "QUANTITY",
      "description": "Block number to set as head.",
      "example": "0x1a2b3c"
    }]
  }, {
    "namespace": "sei",
    "name": "sei_getSeiAddress",
    "status": "limited",
    "description": "Returns the native Sei bech32 (sei1...) address associated with a given EVM (0x) address.",
    "seiNote": "Deprecated legacy sei_* method, but ENABLED by default in the enabled_legacy_sei_apis allowlist on seid init. New integrations should call the addr precompile at 0x0000000000000000000000000000000000001004 (getSeiAddr) via eth_call. Errors if the address is not yet associated. HTTP-only.",
    "params": [{
      "name": "ethAddress",
      "type": "DATA, 20 bytes",
      "description": "The EVM address to resolve.",
      "example": "0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55"
    }]
  }, {
    "namespace": "sei",
    "name": "sei_getEVMAddress",
    "status": "limited",
    "description": "Returns the EVM (0x) address associated with a given native Sei bech32 (sei1...) address.",
    "seiNote": "Deprecated legacy sei_* method, ENABLED by default in enabled_legacy_sei_apis. Prefer the addr precompile at 0x0000000000000000000000000000000000001004 (getEvmAddr) via eth_call. Errors if the bech32 is malformed or the address is not yet associated. HTTP-only.",
    "params": [{
      "name": "seiAddress",
      "type": "string",
      "description": "The Sei bech32 address to resolve.",
      "example": "sei13ytysxs88z0fp9cssagg77ekpecrrlrwce9pwl"
    }]
  }, {
    "namespace": "sei",
    "name": "sei_getCosmosTx",
    "status": "limited",
    "description": "Returns the underlying CometBFT/Cosmos transaction hash corresponding to a given EVM transaction hash.",
    "seiNote": "Deprecated legacy sei_* method, but ENABLED by default in enabled_legacy_sei_apis (it has no precompile equivalent yet). Returns the wrapping Cosmos transaction hash as uppercase hexadecimal without a 0x prefix. HTTP-only.",
    "params": [{
      "name": "ethHash",
      "type": "DATA, 32 bytes",
      "description": "The EVM transaction hash to map to its underlying Cosmos tx hash.",
      "example": "0x828c91592453fe7c5bf743204495a35bf02b67b579b8f59ee7eea8af031d7c14"
    }]
  }, {
    "namespace": "sei",
    "name": "sei_getTransactionReceipt",
    "status": "limited",
    "description": "Returns a transaction receipt by hash, including synthetic receipts for Cosmos transactions.",
    "seiNote": "Deprecated legacy sei_* method, DISABLED by default. It can retrieve logs for a synthetic transaction when its hash is already known. HTTP-only.",
    "params": [{
      "name": "hash",
      "type": "DATA, 32 bytes",
      "description": "Transaction hash.",
      "example": "0x828c91592453fe7c5bf743204495a35bf02b67b579b8f59ee7eea8af031d7c14"
    }]
  }, {
    "namespace": "admin",
    "name": "admin_*",
    "status": "unsupported",
    "description": "Geth node administration namespace (admin_nodeInfo, admin_peers, admin_addPeer, admin_datadir, etc.). Not run by Sei.",
    "seiNote": "Sei does not run go-ethereum's admin namespace; node administration is via the CometBFT/Cosmos stack. All admin_* methods return -32601 method not found."
  }, {
    "namespace": "miner",
    "name": "miner_*",
    "status": "unsupported",
    "description": "Geth miner-control namespace (miner_start, miner_stop, miner_setEtherbase, miner_setGasPrice, etc.). Not run by Sei.",
    "seiNote": "Sei has no PoW/PoA miner (CometBFT PoS consensus); the namespace is not served. All miner_* methods return -32601."
  }, {
    "namespace": "clique",
    "name": "clique_*",
    "status": "unsupported",
    "description": "Clique proof-of-authority consensus namespace (clique_getSnapshot, clique_propose, etc.). Not run by Sei.",
    "seiNote": "Sei uses CometBFT, not the Clique PoA engine; the namespace is not served. All clique_* methods return -32601."
  }, {
    "namespace": "engine",
    "name": "engine_*",
    "status": "unsupported",
    "description": "Ethereum Engine API namespace (engine_newPayloadV*, engine_forkchoiceUpdatedV*, engine_getPayloadV*) for consensus/execution-layer payload exchange. Not run by Sei.",
    "seiNote": "Sei is not a post-merge Ethereum execution client; there is no CL/EL split or payload engine (consensus is CometBFT). All engine_* methods return -32601."
  }, {
    "namespace": "les",
    "name": "les_*",
    "status": "unsupported",
    "description": "Light Ethereum Subprotocol (LES) light-server namespace. Not run by Sei.",
    "seiNote": "Sei does not implement LES light-server endpoints; the namespace is not served. All les_* methods return -32601."
  }, {
    "namespace": "personal",
    "name": "personal_*",
    "status": "unsupported",
    "description": "Geth account-management namespace (personal_newAccount, personal_unlockAccount, personal_sendTransaction, personal_sign, etc.). Not run by Sei.",
    "seiNote": "Sei does not expose the deprecated personal namespace; hosted RPC nodes hold no user keys. Key management/signing is client-side and eth_sendRawTransaction is the supported path. All personal_* methods return -32601."
  }];
  const parseValue = raw => {
    if (typeof raw !== 'string') return raw;
    const t = raw.trim();
    if (t === '') return '';
    const looksJson = t[0] === '{' || t[0] === '[' || t === 'true' || t === 'false' || t === 'null';
    if (looksJson) {
      try {
        return JSON.parse(t);
      } catch (e) {
        return raw;
      }
    }
    return raw;
  };
  const isEmptyValue = v => {
    if (v === '' || v === undefined || v === null) return true;
    if (Array.isArray(v)) return v.length === 0;
    if (typeof v === 'object') return Object.keys(v).length === 0;
    return false;
  };
  const buildParams = (method, values) => {
    const defs = method.params || [];
    const raw = defs.map(p => {
      const v = values ? values[p.name] : undefined;
      return v !== undefined ? v : p.example || '';
    });
    const isBlank = v => typeof v === 'string' && v.trim() === '';
    let end = raw.length;
    while (end > 0 && isEmptyValue(parseValue(raw[end - 1]))) end--;
    const params = raw.slice(0, end).map((v, i) => isBlank(v) ? parseValue(defs[i].example || '') : parseValue(v));
    const sub = typeof params[0] === 'string' ? params[0].trim().toLowerCase() : params[0];
    if (method.name === 'eth_subscribe' && sub !== 'logs') params.length = 1;
    return params;
  };
  const deriveWsEndpoint = httpUrl => {
    if (!httpUrl) return 'wss://<your-ws-endpoint>';
    try {
      const u = new URL(httpUrl);
      u.protocol = u.protocol === 'http:' ? 'ws:' : 'wss:';
      return u.toString().replace(/\/$/, '');
    } catch (e) {
      return 'wss://<your-ws-endpoint>';
    }
  };
  const isWsOnly = name => name === 'eth_subscribe' || name === 'eth_unsubscribe';
  const isMutation = name => name === 'eth_sendRawTransaction' || name === 'eth_sendTransaction' || name === 'eth_signTransaction' || name === 'eth_sign' || name.startsWith('personal_');
  const [theme, setTheme] = useState('dark');
  const [isMobile, setIsMobile] = useState(false);
  const [mobileView, setMobileView] = useState('list');
  const rootRef = useRef(null);
  const runIdRef = useRef(0);
  const probeIdRef = useRef(0);
  const [network, setNetwork] = useState('mainnet');
  const [customEndpoint, setCustomEndpoint] = useState('');
  const endpoint = network === 'custom' ? customEndpoint : NETWORKS[network].http;
  const wsEndpoint = network === 'custom' ? deriveWsEndpoint(customEndpoint) : NETWORKS[network].ws;
  const [connection, setConnection] = useState('idle');
  const [consoleActive, setConsoleActive] = useState(false);
  const [searchTerm, setSearchTerm] = useState('');
  const [selectedNamespace, setSelectedNamespace] = useState('all');
  const [showAll, setShowAll] = useState(false);
  const isHiddenByDefault = m => m.status === 'unsupported' || !!(NAMESPACE_META[m.namespace] && NAMESPACE_META[m.namespace].deprecated);
  const [selectedMethod, setSelectedMethod] = useState(null);
  const [selectedLanguage, setSelectedLanguage] = useState('curl');
  const [paramValues, setParamValues] = useState({});
  const [debouncedParams, setDebouncedParams] = useState({});
  const [requestResult, setRequestResult] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  const [copied, setCopied] = useState('');
  const isDark = theme === 'dark';
  useEffect(() => {
    const detect = () => setTheme(document.documentElement.classList.contains('dark') ? 'dark' : 'light');
    detect();
    const observer = new MutationObserver(detect);
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class']
    });
    return () => observer.disconnect();
  }, []);
  useEffect(() => {
    const stackBelow = w => setIsMobile(w < 768);
    const el = rootRef.current;
    if (el && typeof ResizeObserver !== 'undefined') {
      const ro = new ResizeObserver(entries => stackBelow(entries[0].contentRect.width));
      ro.observe(el);
      return () => ro.disconnect();
    }
    const check = () => stackBelow(window.innerWidth);
    check();
    window.addEventListener('resize', check);
    return () => window.removeEventListener('resize', check);
  }, []);
  useEffect(() => {
    const t = setTimeout(() => setDebouncedParams(paramValues), 250);
    return () => clearTimeout(t);
  }, [paramValues]);
  const validateEndpoint = useCallback(async () => {
    if (!endpoint) {
      setConnection('idle');
      return;
    }
    const probeId = ++probeIdRef.current;
    try {
      const res = await fetch(endpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          jsonrpc: '2.0',
          id: 1,
          method: 'web3_clientVersion',
          params: []
        })
      });
      if (probeId === probeIdRef.current) setConnection(res.ok ? 'ok' : 'fail');
    } catch (e) {
      if (probeId === probeIdRef.current) setConnection('fail');
    }
  }, [endpoint]);
  useEffect(() => {
    if (consoleActive) validateEndpoint();
  }, [validateEndpoint, consoleActive]);
  useEffect(() => {
    runIdRef.current++;
    setRequestResult(null);
    setIsLoading(false);
  }, [endpoint]);
  const allMethods = useMemo(() => SEI_RPC_METHODS.map(m => ({
    ...m,
    meta: NAMESPACE_META[m.namespace] || ({
      label: m.namespace,
      color: '#6b7280'
    })
  })), []);
  const filteredMethods = useMemo(() => {
    let list = allMethods;
    if (selectedNamespace !== 'all') list = list.filter(m => m.namespace === selectedNamespace);
    if (!showAll) list = list.filter(m => !isHiddenByDefault(m));
    if (searchTerm) {
      const q = searchTerm.toLowerCase();
      list = list.filter(m => m.name.toLowerCase().includes(q) || (m.description || '').toLowerCase().includes(q));
    }
    const rank = s => s === 'supported' ? 0 : s === 'limited' ? 1 : 2;
    return [...list].sort((a, b) => {
      const ns = NAMESPACE_ORDER.indexOf(a.namespace) - NAMESPACE_ORDER.indexOf(b.namespace);
      if (ns !== 0) return ns;
      return rank(a.status) - rank(b.status);
    });
  }, [allMethods, selectedNamespace, showAll, searchTerm]);
  const visibleNamespaces = useMemo(() => {
    const present = new Set();
    allMethods.forEach(m => {
      if (showAll || !isHiddenByDefault(m)) present.add(m.namespace);
    });
    return NAMESPACE_ORDER.filter(ns => present.has(ns));
  }, [allMethods, showAll]);
  const counts = useMemo(() => allMethods.reduce((a, m) => (a[m.status] = (a[m.status] || 0) + 1, a), {}), [allMethods]);
  const selectMethod = m => {
    setConsoleActive(true);
    setSelectedMethod(m);
    setParamValues({});
    setDebouncedParams({});
    runIdRef.current++;
    setRequestResult(null);
    setIsLoading(false);
    setSelectedLanguage('curl');
    if (isMobile) setMobileView('detail');
  };
  const copy = (text, key) => {
    navigator.clipboard.writeText(text);
    setCopied(key);
    setTimeout(() => setCopied(''), 1500);
  };
  const execute = async () => {
    if (!selectedMethod) return;
    const runId = ++runIdRef.current;
    setIsLoading(true);
    setRequestResult(null);
    const params = buildParams(selectedMethod, paramValues);
    try {
      const res = await fetch(endpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          jsonrpc: '2.0',
          id: 1,
          method: selectedMethod.name,
          params
        })
      });
      const json = await res.json();
      if (runId === runIdRef.current) setRequestResult(json);
    } catch (e) {
      if (runId === runIdRef.current) setRequestResult({
        error: {
          code: -1,
          message: e.message + ' (the endpoint may not allow browser requests / CORS)'
        }
      });
    } finally {
      if (runId === runIdRef.current) setIsLoading(false);
    }
  };
  const generateCode = useCallback((method, language) => {
    if (!method) return '';
    const params = buildParams(method, debouncedParams);
    const paramsJson = JSON.stringify(params);
    const bodyJson = JSON.stringify({
      jsonrpc: '2.0',
      id: 1,
      method: method.name,
      params
    });
    const url = endpoint || 'https://evm-rpc.sei-apis.com';
    const ws = wsEndpoint;
    const BT = String.fromCharCode(96);
    const csBody = bodyJson.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
    if (isWsOnly(method.name)) {
      if (language === 'javascript') {
        return [`// ${method.name} runs over WebSocket only.`, `const socket = new WebSocket('${ws}');`, 'socket.onopen = () => socket.send(JSON.stringify({', `  jsonrpc: '2.0', id: 1, method: '${method.name}', params: ${paramsJson},`, '}));', 'socket.onmessage = (e) => console.log(JSON.parse(e.data));', '', '// ethers v6', "import { WebSocketProvider } from 'ethers';", `const provider = new WebSocketProvider('${ws}');`, `console.log(await provider.send('${method.name}', ${paramsJson}));`].join('\n');
      }
      if (language === 'typescript') {
        return [`// ${method.name} runs over WebSocket only.`, `const socket = new WebSocket('${ws}');`, 'socket.onopen = () => socket.send(JSON.stringify({', `  jsonrpc: '2.0', id: 1, method: '${method.name}', params: ${paramsJson},`, '}));', 'socket.onmessage = (e: MessageEvent) => console.log(JSON.parse(e.data));'].join('\n');
      }
      if (language === 'python') {
        return ['# pip install websocket-client', 'from websocket import create_connection', `socket = create_connection("${ws}")`, `socket.send(r"""${bodyJson}""")`, 'print(socket.recv())', 'socket.close()'].join('\n');
      }
      if (language === 'go') {
        return ['// go get github.com/gorilla/websocket', 'package main', '', 'import (', '\t"fmt"', '\t"github.com/gorilla/websocket"', ')', '', 'func main() {', `\tc, _, err := websocket.DefaultDialer.Dial("${ws}", nil)`, '\tif err != nil {', '\t\tpanic(err)', '\t}', '\tdefer c.Close()', '\tc.WriteMessage(websocket.TextMessage, []byte(' + BT + bodyJson + BT + '))', '\t_, msg, _ := c.ReadMessage()', '\tfmt.Println(string(msg))', '}'].join('\n');
      }
      if (language === 'rust') {
        return ['// tokio-tungstenite = "0.23"  futures-util = "0.3"  tokio = { version = "1", features = ["full"] }', 'use futures_util::{SinkExt, StreamExt};', 'use tokio_tungstenite::{connect_async, tungstenite::Message};', '', '#[tokio::main]', 'async fn main() -> Result<(), Box<dyn std::error::Error>> {', `    let (mut socket, _) = connect_async("${ws}").await?;`, '    socket.send(Message::Text(r#"' + bodyJson + '"#.to_string())).await?;', '    if let Some(msg) = socket.next().await {', '        println!("{}", msg?);', '    }', '    Ok(())', '}'].join('\n');
      }
      if (language === 'csharp') {
        return ['using System;', 'using System.Net.WebSockets;', 'using System.Text;', 'using System.Threading;', '', 'using var socket = new ClientWebSocket();', `await socket.ConnectAsync(new Uri("${ws}"), CancellationToken.None);`, `var body = Encoding.UTF8.GetBytes("${csBody}");`, 'await socket.SendAsync(body, WebSocketMessageType.Text, true, CancellationToken.None);', 'var buffer = new byte[8192];', 'var res = await socket.ReceiveAsync(buffer, CancellationToken.None);', 'Console.WriteLine(Encoding.UTF8.GetString(buffer, 0, res.Count));'].join('\n');
      }
      if (language === 'cast') {
        return [`# ${method.name} is WebSocket-only. cast has no native WebSocket support.`, '# Use wscat (npm i -g wscat):', `wscat -c ${ws}`, `> ${bodyJson}`].join('\n');
      }
      if (language === 'java') {
        return ['import java.net.URI;', 'import java.net.http.*;', 'import java.util.concurrent.CompletableFuture;', 'import java.util.concurrent.CompletionStage;', '', 'var done = new CompletableFuture<Void>();', 'HttpClient.newHttpClient().newWebSocketBuilder()', `    .buildAsync(URI.create("${ws}"), new WebSocket.Listener() {`, '        public void onOpen(WebSocket ws) {', `            ws.sendText("${csBody}", true); ws.request(1);`, '        }', '        public CompletionStage<?> onText(WebSocket ws, CharSequence data, boolean last) {', '            System.out.println(data); done.complete(null); return null;', '        }', '    }).join();', 'done.join();'].join('\n');
      }
      if (language === 'kotlin') {
        return ['import java.net.URI', 'import java.net.http.*', 'import java.util.concurrent.CompletableFuture', 'import java.util.concurrent.CompletionStage', '', 'val done = CompletableFuture<Void>()', 'HttpClient.newHttpClient().newWebSocketBuilder()', `    .buildAsync(URI.create("${ws}"), object : WebSocket.Listener {`, '        override fun onOpen(ws: WebSocket) {', `            ws.sendText("${csBody}", true); ws.request(1)`, '        }', '        override fun onText(ws: WebSocket, data: CharSequence, last: Boolean): CompletionStage<*>? {', '            println(data); done.complete(null); ws.request(1); return null', '        }', '    }).join()', 'done.join()'].join('\n');
      }
      if (language === 'swift') {
        return ['import Foundation', '', `let task = URLSession.shared.webSocketTask(with: URL(string: "${ws}")!)`, 'task.resume()', `try await task.send(.string(#"${bodyJson}"#))`, 'let msg = try await task.receive()', 'if case .string(let text) = msg { print(text) }', 'task.cancel(with: .normalClosure, reason: nil)'].join('\n');
      }
      return [`# ${method.name} is WebSocket-only. Use wscat (npm i -g wscat):`, `wscat -c ${ws}`, `> ${bodyJson}`].join('\n');
    }
    if (language === 'javascript') {
      return ['// fetch', `const res = await fetch('${url}', {`, "  method: 'POST',", "  headers: { 'Content-Type': 'application/json' },", '  body: JSON.stringify({', "    jsonrpc: '2.0', id: 1,", `    method: '${method.name}',`, `    params: ${paramsJson},`, '  }),', '});', 'console.log((await res.json()).result);', '', '// ethers v6', "import { JsonRpcProvider } from 'ethers';", `const provider = new JsonRpcProvider('${url}');`, `console.log(await provider.send('${method.name}', ${paramsJson}));`, '', '// viem', "import { createPublicClient, http } from 'viem';", `const client = createPublicClient({ transport: http('${url}') });`, `console.log(await client.request({ method: '${method.name}', params: ${paramsJson} }));`].join('\n');
    }
    if (language === 'typescript') {
      return ['type RpcResponse<T> = {', '  jsonrpc: string; id: number;', '  result?: T; error?: { code: number; message: string };', '};', '', `const res = await fetch('${url}', {`, "  method: 'POST',", "  headers: { 'Content-Type': 'application/json' },", '  body: JSON.stringify({', "    jsonrpc: '2.0', id: 1,", `    method: '${method.name}',`, `    params: ${paramsJson},`, '  }),', '});', 'const data: RpcResponse<unknown> = await res.json();', 'console.log(data.result);', '', '// ethers v6', "import { JsonRpcProvider } from 'ethers';", `const provider = new JsonRpcProvider('${url}');`, `console.log(await provider.send('${method.name}', ${paramsJson}));`].join('\n');
    }
    if (language === 'python') {
      return ['import requests, json', '', `url = "${url}"`, `params = json.loads(r"""${paramsJson}""")`, 'res = requests.post(url, json={', '    "jsonrpc": "2.0", "id": 1,', `    "method": "${method.name}", "params": params,`, '})', 'print(res.json().get("result"))', '', '# web3.py', 'from web3 import Web3', 'w3 = Web3(Web3.HTTPProvider(url))', `print(w3.provider.make_request("${method.name}", params))`].join('\n');
    }
    if (language === 'go') {
      return ['package main', '', 'import (', '\t"bytes"', '\t"fmt"', '\t"io"', '\t"net/http"', ')', '', 'func main() {', '\tbody := []byte(' + BT + bodyJson + BT + ')', `\tresp, err := http.Post("${url}", "application/json", bytes.NewBuffer(body))`, '\tif err != nil {', '\t\tpanic(err)', '\t}', '\tdefer resp.Body.Close()', '\tout, _ := io.ReadAll(resp.Body)', '\tfmt.Println(string(out))', '}'].join('\n');
    }
    if (language === 'rust') {
      return ['// reqwest = { version = "0.12", features = ["json"] }', '// serde_json = "1"   tokio = { version = "1", features = ["full"] }', 'use serde_json::Value;', '', '#[tokio::main]', 'async fn main() -> Result<(), Box<dyn std::error::Error>> {', '    let body: Value = serde_json::from_str(r#"' + bodyJson + '"#)?;', `    let res = reqwest::Client::new().post("${url}")`, '        .json(&body).send().await?', '        .json::<Value>().await?;', '    println!("{:#?}", res["result"]);', '    Ok(())', '}'].join('\n');
    }
    if (language === 'csharp') {
      return ['using System;', 'using System.Net.Http;', 'using System.Text;', '', 'using var http = new HttpClient();', `var json = "${csBody}";`, 'var content = new StringContent(json, Encoding.UTF8, "application/json");', `var res = await http.PostAsync("${url}", content);`, 'Console.WriteLine(await res.Content.ReadAsStringAsync());'].join('\n');
    }
    if (language === 'cast') {
      const castArgs = params.map(p => `'${JSON.stringify(p)}'`).join(' ');
      return `cast rpc --rpc-url ${url} ${method.name}${params.length ? ' ' + castArgs : ''}`;
    }
    if (language === 'java') {
      return ['import java.net.URI;', 'import java.net.http.*;', '', `var json = "${csBody}";`, `var req = HttpRequest.newBuilder(URI.create("${url}"))`, '    .header("Content-Type", "application/json")', '    .POST(HttpRequest.BodyPublishers.ofString(json))', '    .build();', 'var res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());', 'System.out.println(res.body());'].join('\n');
    }
    if (language === 'kotlin') {
      return ['import java.net.URI', 'import java.net.http.HttpClient', 'import java.net.http.HttpRequest', 'import java.net.http.HttpResponse', '', `val json = "${csBody}"`, `val req = HttpRequest.newBuilder(URI.create("${url}"))`, '    .header("Content-Type", "application/json")', '    .POST(HttpRequest.BodyPublishers.ofString(json))', '    .build()', 'val res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString())', 'println(res.body())'].join('\n');
    }
    if (language === 'swift') {
      return ['import Foundation', '', `let url = URL(string: "${url}")!`, 'var request = URLRequest(url: url)', 'request.httpMethod = "POST"', 'request.setValue("application/json", forHTTPHeaderField: "Content-Type")', `request.httpBody = Data(#"${bodyJson}"#.utf8)`, '', 'let (data, _) = try await URLSession.shared.data(for: request)', 'print(String(decoding: data, as: UTF8.self))'].join('\n');
    }
    const curlBody = bodyJson.replace(/'/g, "'\\''");
    return `curl -s -X POST ${url} \\\n  -H "Content-Type: application/json" \\\n  -d '${curlBody}'`;
  }, [endpoint, wsEndpoint, debouncedParams]);
  const codeExample = useMemo(() => generateCode(selectedMethod, selectedLanguage), [selectedMethod, selectedLanguage, generateCode]);
  const c = {
    bg: isDark ? '#000000' : '#f5f5f7',
    panel: isDark ? '#0a0a0a' : '#ffffff',
    panel2: isDark ? '#121212' : '#f5f5f7',
    border: isDark ? '#1f1f1f' : '#ececee',
    text: isDark ? '#ffffff' : '#131313',
    sub: isDark ? '#9ca3af' : '#666666',
    faint: isDark ? '#6b7280' : '#999999',
    input: isDark ? '#161616' : '#ffffff',
    code: isDark ? '#0d0d0d' : '#1a1a1a',
    maroon: '#600014'
  };
  const mono = 'var(--sei-font-mono, ui-monospace, "SF Mono", Menlo, monospace)';
  const bd = '1px solid ' + c.border;
  const fieldStyle = {
    width: '100%',
    fontSize: 12,
    fontFamily: mono,
    padding: '7px 10px',
    background: c.input,
    color: c.text,
    border: bd,
    borderRadius: 4,
    outline: 'none',
    boxSizing: 'border-box'
  };
  const statusColor = s => isDark ? STATUS_META[s].dark : STATUS_META[s].light;
  const StatusDot = ({status}) => <span title={STATUS_META[status].label} style={{
    display: 'inline-block',
    width: 7,
    height: 7,
    borderRadius: 9,
    background: statusColor(status),
    flexShrink: 0
  }} />;
  const Badge = ({status}) => <span style={{
    fontSize: 11,
    fontWeight: 600,
    padding: '2px 8px',
    borderRadius: 3,
    color: statusColor(status),
    background: statusColor(status) + '22',
    border: `1px solid ${statusColor(status)}55`
  }}>
      {STATUS_META[status].label}
    </span>;
  const CopyBtn = ({text, k}) => <button onClick={() => copy(text, k)} style={{
    fontSize: 11,
    color: c.sub,
    background: 'transparent',
    border: bd,
    borderRadius: 3,
    padding: '3px 8px',
    cursor: 'pointer'
  }}>
      {copied === k ? 'Copied' : 'Copy'}
    </button>;
  const CodeBlock = ({text, maxHeight}) => <pre style={{
    margin: 0,
    padding: 14,
    borderRadius: 4,
    background: c.code,
    border: bd,
    overflowX: 'auto',
    maxHeight
  }}>
      <code style={{
    fontFamily: mono,
    fontSize: 12,
    color: '#d4d4d4',
    whiteSpace: 'pre',
    lineHeight: 1.6
  }}>{text}</code>
    </pre>;
  const m = selectedMethod;
  const mMeta = m ? NAMESPACE_META[m.namespace] || ({}) : {};
  return <div ref={rootRef} className="not-prose rpc-explorer-root" style={{
    fontFamily: 'var(--sei-font-body, inherit)',
    color: c.text,
    background: c.bg,
    border: bd,
    borderRadius: 6,
    overflow: 'hidden',
    display: 'flex',
    flexDirection: 'column',
    height: '96vh',
    minHeight: 768
  }}>
      <div style={{
    borderBottom: bd,
    background: c.panel,
    padding: '14px 18px',
    display: 'flex',
    flexDirection: 'column',
    gap: 12,
    flexShrink: 0
  }}>
        <div>
          <div style={{
    fontSize: 16,
    fontWeight: 700,
    letterSpacing: '-0.01em'
  }}>Sei EVM JSON-RPC Explorer</div>
          <div style={{
    fontSize: 12,
    color: c.sub,
    marginTop: 2
  }}>
            {allMethods.length} methods · {counts.supported} supported · {counts.limited} limited · {counts.unsupported} unavailable
          </div>
        </div>
        <div style={{
    display: 'flex',
    gap: 8,
    alignItems: 'center',
    flexWrap: 'wrap'
  }}>
          {}
          <div style={{
    display: 'flex',
    border: bd,
    borderRadius: 4,
    overflow: 'hidden'
  }}>
            {['mainnet', 'testnet', 'custom'].map(n => <button key={n} onClick={() => {
    setNetwork(n);
    setConnection('idle');
  }} style={{
    fontSize: 12,
    padding: '6px 12px',
    cursor: 'pointer',
    border: 'none',
    textTransform: 'capitalize',
    background: network === n ? c.maroon : 'transparent',
    color: network === n ? '#fff' : c.sub,
    fontWeight: network === n ? 600 : 400
  }}>
                {n}
              </button>)}
          </div>
          {network === 'custom' ? <input value={customEndpoint} onChange={e => {
    setCustomEndpoint(e.target.value);
    setConnection('idle');
  }} onBlur={validateEndpoint} placeholder="https://your-rpc" style={{
    fontSize: 12,
    fontFamily: mono,
    padding: '6px 10px',
    width: 220,
    background: c.input,
    color: c.text,
    border: bd,
    borderRadius: 4,
    outline: 'none'
  }} /> : <code style={{
    fontSize: 12,
    fontFamily: mono,
    color: c.sub,
    padding: '5px 10px',
    background: c.panel2,
    borderRadius: 4,
    border: bd,
    maxWidth: '100%',
    overflowWrap: 'anywhere'
  }}>{endpoint}</code>}
          <span title={connection === 'ok' ? 'Reachable' : connection === 'fail' ? 'Unreachable from this browser' : 'Not checked'} style={{
    display: 'inline-flex',
    alignItems: 'center',
    gap: 5,
    fontSize: 11,
    color: connection === 'ok' ? '#22c55e' : connection === 'fail' ? '#ef4444' : c.faint
  }}>
            <span style={{
    width: 8,
    height: 8,
    borderRadius: 9,
    background: connection === 'ok' ? '#22c55e' : connection === 'fail' ? '#ef4444' : c.faint
  }} />
            {connection === 'ok' ? 'Live' : connection === 'fail' ? 'Offline' : '—'}
          </span>
        </div>
      </div>

      {}
      <div style={{
    flex: 1,
    display: 'flex',
    overflow: 'hidden'
  }}>
        {}
        <div style={{
    width: isMobile ? '100%' : 320,
    flexShrink: 0,
    display: isMobile && mobileView !== 'list' ? 'none' : 'flex',
    flexDirection: 'column',
    borderRight: isMobile ? 'none' : bd,
    background: c.panel,
    overflow: 'hidden'
  }}>
          <div style={{
    padding: 14,
    borderBottom: bd
  }}>
            <input value={searchTerm} onChange={e => setSearchTerm(e.target.value)} placeholder="Search methods…" style={{
    width: '100%',
    fontSize: 13,
    padding: '8px 12px',
    background: c.input,
    color: c.text,
    border: bd,
    borderRadius: 4,
    outline: 'none',
    boxSizing: 'border-box'
  }} />
            <div style={{
    display: 'flex',
    flexWrap: 'wrap',
    gap: 5,
    marginTop: 10
  }}>
              <button onClick={() => setSelectedNamespace('all')} style={{
    fontSize: 11,
    padding: '3px 9px',
    borderRadius: 3,
    cursor: 'pointer',
    fontWeight: 600,
    border: `1px solid ${selectedNamespace === 'all' ? c.maroon : c.border}`,
    background: selectedNamespace === 'all' ? c.maroon : 'transparent',
    color: selectedNamespace === 'all' ? '#fff' : c.sub
  }}>
                All
              </button>
              {visibleNamespaces.map(ns => {
    const active = selectedNamespace === ns;
    const col = NAMESPACE_META[ns].color;
    return <button key={ns} onClick={() => setSelectedNamespace(ns)} style={{
      fontSize: 11,
      padding: '3px 9px',
      borderRadius: 3,
      cursor: 'pointer',
      fontWeight: 600,
      border: `1px solid ${col}`,
      background: active ? col : 'transparent',
      color: active ? '#fff' : isDark ? col : col,
      opacity: active ? 1 : 0.85
    }}>
                    {NAMESPACE_META[ns].label}
                  </button>;
  })}
            </div>
            <label style={{
    display: 'flex',
    alignItems: 'center',
    gap: 7,
    marginTop: 11,
    fontSize: 12,
    color: c.sub,
    cursor: 'pointer'
  }}>
              <input type="checkbox" checked={showAll} onChange={e => {
    const next = e.target.checked;
    setShowAll(next);
    if (!next) {
      if (selectedNamespace !== 'all') {
        const meta = NAMESPACE_META[selectedNamespace];
        if (meta && (meta.deprecated || meta.unavailable)) setSelectedNamespace('all');
      }
      if (selectedMethod && isHiddenByDefault(selectedMethod)) {
        runIdRef.current++;
        setSelectedMethod(null);
        setRequestResult(null);
        setIsLoading(false);
      }
    }
  }} style={{
    accentColor: c.maroon
  }} />
              Show deprecated & unavailable methods
            </label>
          </div>
          <div style={{
    flex: 1,
    overflowY: 'auto'
  }}>
            {filteredMethods.length === 0 && <div style={{
    padding: 24,
    fontSize: 13,
    color: c.faint,
    textAlign: 'center'
  }}>No methods match.</div>}
            {filteredMethods.map(mm => {
    const active = m && m.name === mm.name;
    return <button key={mm.name} onClick={() => selectMethod(mm)} style={{
      width: '100%',
      textAlign: 'left',
      padding: '9px 13px 9px 12px',
      cursor: 'pointer',
      border: 'none',
      borderLeft: `3px solid ${mm.meta.color}`,
      borderBottom: bd,
      background: active ? isDark ? '#161616' : '#f0eef0' : 'transparent',
      display: 'block',
      opacity: mm.status === 'unsupported' ? 0.6 : 1
    }}>
                  <div style={{
      display: 'flex',
      alignItems: 'center',
      gap: 7
    }}>
                    <StatusDot status={mm.status} />
                    <code style={{
      fontFamily: mono,
      fontSize: 12.5,
      color: active ? c.text : isDark ? '#e5e5e5' : '#1a1a1a',
      fontWeight: active ? 600 : 500,
      whiteSpace: 'nowrap',
      overflow: 'hidden',
      textOverflow: 'ellipsis'
    }}>{mm.name}</code>
                  </div>
                  <div style={{
      fontSize: 11.5,
      color: c.faint,
      marginTop: 3,
      lineHeight: 1.35,
      display: '-webkit-box',
      WebkitLineClamp: 2,
      WebkitBoxOrient: 'vertical',
      overflow: 'hidden'
    }}>{mm.description}</div>
                </button>;
  })}
          </div>
        </div>

        {}
        <div style={{
    flex: 1,
    display: isMobile && mobileView !== 'detail' ? 'none' : 'flex',
    flexDirection: 'column',
    overflowY: 'auto',
    background: c.bg
  }}>
          {!m ? <div style={{
    flex: 1,
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    color: c.faint,
    fontSize: 14,
    padding: 24,
    textAlign: 'center'
  }}>
              Select a method to see its reference, parameters, and runnable examples.
            </div> : <div style={{
    padding: isMobile ? 16 : 24,
    maxWidth: 860
  }}>
              {isMobile && <button onClick={() => setMobileView('list')} style={{
    fontSize: 12,
    color: c.sub,
    background: 'transparent',
    border: 'none',
    cursor: 'pointer',
    padding: 0,
    marginBottom: 12
  }}>← Methods</button>}
              <div style={{
    display: 'flex',
    alignItems: 'center',
    gap: 10,
    flexWrap: 'wrap'
  }}>
                <code style={{
    fontFamily: mono,
    fontSize: 19,
    fontWeight: 700,
    color: c.text
  }}>{m.name}</code>
                <Badge status={m.status} />
                <span style={{
    fontSize: 11,
    padding: '2px 8px',
    borderRadius: 3,
    color: '#fff',
    background: mMeta.color
  }}>{mMeta.label}</span>
              </div>
              <p style={{
    fontSize: 14,
    color: c.sub,
    marginTop: 10,
    lineHeight: 1.55
  }}>{m.description}</p>

              {mMeta.deprecated && <div style={{
    marginTop: 14,
    padding: '10px 14px',
    borderRadius: 4,
    background: '#f59e0b18',
    border: '1px solid #f59e0b55',
    fontSize: 12.5,
    color: isDark ? '#fbbf24' : '#92400e',
    lineHeight: 1.5
  }}>
                  <strong>Deprecated.</strong> The <code style={{
    fontFamily: mono
  }}>{m.namespace}_*</code> surface is scheduled for removal and is gated by <code style={{
    fontFamily: mono
  }}>enabled_legacy_sei_apis</code> in <code style={{
    fontFamily: mono
  }}>app.toml</code>. Prefer standard <code style={{
    fontFamily: mono
  }}>eth_*</code>/<code style={{
    fontFamily: mono
  }}>debug_*</code> methods for new integrations.
                </div>}
              {mMeta.unavailable && <div style={{
    marginTop: 14,
    padding: '10px 14px',
    borderRadius: 4,
    background: isDark ? '#ffffff0a' : '#0000000a',
    border: bd,
    fontSize: 12.5,
    color: c.sub,
    lineHeight: 1.5
  }}>
                  The entire <code style={{
    fontFamily: mono
  }}>{m.namespace}_*</code> namespace is not exposed on Sei. {mMeta.blurb}
                </div>}
              {m.seiNote && <div style={{
    marginTop: 14,
    padding: '12px 14px',
    borderRadius: 4,
    background: c.maroon + (isDark ? '22' : '12'),
    border: `1px solid ${c.maroon}${isDark ? '66' : '44'}`,
    fontSize: 12.5,
    color: isDark ? '#e9b8c0' : '#600014',
    lineHeight: 1.55
  }}>
                  <div style={{
    fontWeight: 700,
    marginBottom: 4,
    fontSize: 11,
    letterSpacing: '0.04em',
    textTransform: 'uppercase'
  }}>Sei-specific behavior</div>
                  {m.seiNote}
                </div>}

              {}
              {m.params && m.params.length > 0 && <div style={{
    marginTop: 22
  }}>
                  <div style={{
    fontSize: 13,
    fontWeight: 700,
    marginBottom: 10
  }}>Parameters</div>
                  <div style={{
    display: 'flex',
    flexDirection: 'column',
    gap: 8
  }}>
                    {m.params.map(p => <div key={p.name} style={{
    padding: '10px 13px',
    borderRadius: 4,
    background: c.panel2,
    border: bd
  }}>
                        <div style={{
    display: 'flex',
    alignItems: 'center',
    gap: 8,
    flexWrap: 'wrap'
  }}>
                          <code style={{
    fontFamily: mono,
    fontSize: 12.5,
    color: isDark ? '#e9b8c0' : c.maroon,
    fontWeight: 600
  }}>{p.name}</code>
                          <span style={{
    fontSize: 10.5,
    padding: '1px 7px',
    borderRadius: 3,
    color: c.sub,
    background: isDark ? '#ffffff10' : '#00000008',
    border: bd,
    fontFamily: mono
  }}>{p.type}</span>
                        </div>
                        <div style={{
    fontSize: 12.5,
    color: c.sub,
    marginTop: 5,
    lineHeight: 1.5
  }}>{p.description}</div>
                      </div>)}
                  </div>
                </div>}

              {}
              {m.status !== 'unsupported' && <div style={{
    marginTop: 22
  }}>
                  <div style={{
    fontSize: 13,
    fontWeight: 700,
    marginBottom: 10,
    display: 'flex',
    alignItems: 'center',
    gap: 8
  }}>
                    Try it
                    <span style={{
    fontSize: 11,
    fontWeight: 400,
    color: c.faint
  }}>· {network === 'custom' ? endpoint || 'set a custom endpoint' : NETWORKS[network].label}</span>
                  </div>

                  {isWsOnly(m.name) && <div style={{
    padding: '10px 14px',
    borderRadius: 4,
    background: c.panel2,
    border: bd,
    fontSize: 12.5,
    color: c.sub,
    lineHeight: 1.5,
    marginBottom: 10
  }}>
                      This is a WebSocket subscription method. Connect to <code style={{
    fontFamily: mono
  }}>{wsEndpoint}</code> and send the payload below — edit the parameters to customize the subscription.
                      {network === 'custom' && ' This URL is derived from your HTTP endpoint as a best guess; Sei serves WebSocket on a separate host (evm-ws…) from HTTP (evm-rpc…), so replace it with your node’s actual WebSocket endpoint if they differ.'}
                    </div>}
                  {m.params && m.params.length > 0 && <div style={{
    display: 'flex',
    flexDirection: 'column',
    gap: 8,
    marginBottom: 10
  }}>
                      {m.params.map(p => {
    const ex = p.example || '';
    const big = ex.trim().startsWith('{') || ex.trim().startsWith('[') || (p.type || '').toLowerCase().includes('object');
    const fieldId = `rpc-param-${p.name}`;
    const field = {
      id: fieldId,
      value: paramValues[p.name] !== undefined ? paramValues[p.name] : '',
      onChange: e => setParamValues(prev => ({
        ...prev,
        [p.name]: e.target.value
      })),
      placeholder: ex
    };
    return <div key={p.name}>
                            <label htmlFor={fieldId} style={{
      fontSize: 11,
      color: c.faint,
      fontFamily: mono,
      display: 'block',
      marginBottom: 3
    }}>{p.name}</label>
                            {big ? <textarea rows={2} {...field} style={{
      ...fieldStyle,
      resize: 'vertical'
    }} /> : <input {...field} style={fieldStyle} />}
                          </div>;
  })}
                    </div>}
                  {isMutation(m.name) && <div style={{
    fontSize: 11.5,
    color: c.faint,
    marginBottom: 8,
    lineHeight: 1.45
  }}>
                      This is a state-changing / signing method. Public RPC nodes hold no keys, so it generally errors unless you supply a signed payload.
                    </div>}

                  {}
                  <div style={{
    marginTop: 12
  }}>
                    <div style={{
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 8,
    flexWrap: 'wrap',
    gap: 8
  }}>
                      <div style={{
    fontSize: 12,
    fontWeight: 700,
    color: c.sub
  }}>Request</div>
                      <div style={{
    display: 'flex',
    gap: 8,
    alignItems: 'center'
  }}>
                        <div style={{
    display: 'flex',
    gap: 3,
    flexWrap: 'wrap'
  }}>
                          {LANGUAGES.map(l => <button key={l.id} onClick={() => setSelectedLanguage(l.id)} style={{
    fontSize: 11,
    padding: '3px 9px',
    borderRadius: 3,
    cursor: 'pointer',
    border: 'none',
    background: selectedLanguage === l.id ? c.maroon : isDark ? '#161616' : '#ececee',
    color: selectedLanguage === l.id ? '#fff' : c.sub
  }}>
                              {l.name}
                            </button>)}
                        </div>
                        <CopyBtn text={codeExample} k="code" />
                      </div>
                    </div>
                    <CodeBlock text={codeExample} />
                  </div>

                  {}
                  {!isWsOnly(m.name) && <div style={{
    marginTop: 14
  }}>
                      <button onClick={execute} disabled={isLoading || !endpoint} style={{
    fontSize: 13,
    fontWeight: 600,
    padding: '8px 18px',
    borderRadius: 4,
    cursor: isLoading || !endpoint ? 'not-allowed' : 'pointer',
    border: 'none',
    background: c.maroon,
    color: '#fff',
    opacity: isLoading || !endpoint ? 0.55 : 1
  }}>
                        {isLoading ? 'Running…' : 'Run request'}
                      </button>
                      {requestResult && <div style={{
    marginTop: 12
  }}>
                          <div style={{
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 6
  }}>
                            <span style={{
    fontSize: 11,
    color: requestResult.error ? '#ef4444' : '#22c55e',
    fontWeight: 600
  }}>{requestResult.error ? 'Error' : 'Result'}</span>
                            <CopyBtn text={JSON.stringify(requestResult, null, 2)} k="resp" />
                          </div>
                          <CodeBlock text={JSON.stringify(requestResult, null, 2)} maxHeight={280} />
                        </div>}
                    </div>}
                </div>}
            </div>}
        </div>
      </div>
    </div>;
};

Sei fully supports the standard Ethereum JSON-RPC API, so existing EVM tooling (ethers.js, viem, Hardhat, Foundry, etc.) works out of the box. Use the explorer below to browse every method Sei exposes, inspect parameters, run requests against a live endpoint, and copy ready-to-use snippets in a range of popular languages. The authoritative prose for the request format, the remaining deprecated `sei_*` extensions, and address resolution follows underneath.

<RPCMethodsViewer />

<Note>
  By default the explorer lists only the available, current methods. Each is labelled with one of three statuses:

  * **Supported** — registered with a full implementation and standard Ethereum behavior.
  * **Limited** — callable, but returns a static value or has a Sei-specific caveat (shown in the method's **Sei-specific behavior** note). Examples: `eth_coinbase` returns the fee-collector address and `eth_getProof` returns an IAVL proof.
  * **Unavailable** — not registered, explicitly errors, or not applicable to Sei's architecture. This includes blob methods (`eth_blobBaseFee`), proof-of-work and uncle methods, and the `admin`/`miner`/`clique`/`engine`/`les`/`personal` namespaces.

  The remaining deprecated `sei_*` extensions and the unavailable methods are hidden by default. Enable **Show deprecated & unavailable methods** to browse them. The deprecated extensions are also documented under [Sei custom endpoints](#sei-custom-endpoints).
</Note>

## Overview

Sei supports the [Ethereum JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/) with some Sei-specific extensions to support cross-VM operations, synthetic transactions, and other advanced features. Because Sei has [instant finality](/evm/differences-with-ethereum#finality), the `safe`, `finalized`, and `latest` block tags all resolve to the same (latest committed) block.

All endpoints follow the standard JSON-RPC format:

<Accordion title="JSON-RPC Request/Response Format">
  **Request Format**

  * HTTP method: always "`POST`"
  * Header: `accept: application/json`
  * Header: `content-type: application/json`
  * Body (JSON):
    * `id`: an arbitrary string identifier
    * `jsonrpc`: always "2.0"
    * `method`: endpoint name (e.g. "eth\_sendRawTransaction")
    * `params`: an array that differs from endpoint to endpoint

  **Response Format**

  * Body (JSON):
    * `id`: the same identifier in request
    * `jsonrpc`: always "2.0"
    * `result`: an object that differs from endpoint to endpoint
    * `error` (if applicable): error details
</Accordion>

### Network endpoints

| Network              | Chain ID         | HTTP endpoint                          | WebSocket endpoint                  |
| -------------------- | ---------------- | -------------------------------------- | ----------------------------------- |
| Pacific-1 (mainnet)  | `1329` (`0x531`) | `https://evm-rpc.sei-apis.com`         | `wss://evm-ws.sei-apis.com`         |
| Atlantic-2 (testnet) | `1328` (`0x530`) | `https://evm-rpc-testnet.sei-apis.com` | `wss://evm-ws-testnet.sei-apis.com` |

For additional public and commercial endpoints, see [RPC providers](/learn/rpc-providers) and [Chains & endpoints](/learn/dev-chains).

### Tendermint `/status` endpoint

Alongside the EVM JSON-RPC surface, Sei nodes expose the underlying Tendermint/CometBFT RPC, including the `/status` endpoint. Its `SyncInfo` object reports a `last_committed_block_height` field: the height of the last block finalized by consensus.

```bash theme={"dark"}
curl -s $SEI_TENDERMINT_RPC/status | jq '.result.sync_info.last_committed_block_height'
```

The field is JSON-serialized as a string (`last_committed_block_height`), matching the other height fields in `SyncInfo`.

| Field                         | JSON   | Description                                      |
| :---------------------------- | :----- | :----------------------------------------------- |
| `last_committed_block_height` | string | Height of the last block finalized by consensus. |

**Consensus-engine behavior:**

* **Under CometBFT** — commit and app-apply happen in a single step, so `last_committed_block_height` is guaranteed to equal `latest_block_height`.
* **Under Autobahn** — the value is derived from the latest `CommitQC`. Because consensus finalizes a block before the app executes it, the invariant is `last_committed_block_height >= latest_block_height`; the two can briefly differ while the app catches up.

**`validator_info` shape.** The `/status` response's `validator_info` object always includes both a `pub_key` and an `address` field. On nodes that are not validators, `pub_key` is a zero (empty) public key with `address` derived from it and `voting_power` is `0`, rather than the fields being omitted — a stable response shape so clients like CosmJS can parse `/status` without special-casing non-validator nodes. On validator nodes, `pub_key` and `voting_power` carry the real values.

<Note>
  Under Autobahn (`AutobahnConfigFile` set) the CometBFT block store is not populated, so `/status` derives `latest_block_height` and `latest_app_hash` from the app layer (`ABCIInfo`) instead of the block store. Several other `SyncInfo` fields (block hash/time, earliest-block metadata, `catching_up`, and peer-height fields) remain unpopulated in this mode.
</Note>

### Tendermint block and validator endpoints under Autobahn

Under Autobahn (`AutobahnConfigFile` set) the CometBFT `BlockStore` and `StateStore` are not populated. Rather than returning empty or failing responses, the `/block` and `/block_by_hash` Tendermint RPC endpoints route through the GigaRouter's in-memory state (the finalized global blocks retained by the Autobahn data layer), while `/block_results` and `/validators` synthesize their responses (an empty result set and the genesis committee, respectively). This keeps downstream consumers — including evmrpc, block explorers, and monitoring tooling — working without individually branching on the consensus engine.

For `/block` and `/block_by_hash`, responses are served only for heights still inside Autobahn's retained window (heights pruned per `RetainHeight` are no longer available); `/block_results` and `/validators` do not read the retained block data and respond for any height up to the current ABCI head. Requests are validated against the current ABCI head, so heights above it return the same `ErrHeightExceedsChainHead`-class errors as the CometBFT path, and pruned heights on `/block` return `ErrHeightNotAvailable`.

| Endpoint         | Autobahn behavior                                                                                                                                                                                                                                                                                                                                                       |
| :--------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/block`         | Returns the fully-populated translated block at the requested height: `BlockID.Hash` (the Autobahn header hash), the header (`ChainID`, `Height`, `Time`), and `Data.Txs`. Other header fields (`AppHash`, `ProposerAddress`, `LastCommit`, …) stay at zero values.                                                                                                     |
| `/block_by_hash` | Resolves the block by its Autobahn header hash via an in-memory hash index. An unknown or wrong-size hash returns `{Block: nil}` with no error, matching CometBFT semantics for a missing block.                                                                                                                                                                        |
| `/block_results` | Returns a valid-but-empty `ResultBlockResults` at the requested height. `ConsensusParamUpdates.Block.MaxGas` is populated from the producer config; `TxsResults` (per-tx `ExecTxResult` details) is intentionally empty because `FinalizeBlock` responses are not persisted under Autobahn.                                                                             |
| `/validators`    | Returns the genesis committee for any height up to the current ABCI head — the committee is fixed at genesis under Autobahn (no validator-updates path), and the endpoint does not read the retained block data, so pruned heights still answer. `block_height` matches the requested height, and pagination (`page`/`per_page`) behaves the same as the CometBFT path. |

<Note>
  Because `FinalizeBlock` responses are not stored on disk under Autobahn, `/block_results` cannot surface per-transaction execution results (`TxsResults` is empty). For per-transaction EVM data, use the EVM JSON-RPC methods (`eth_getTransactionReceipt`, `eth_getBlockReceipts`) instead.
</Note>

### Filter and subscription limits

<Info>
  Log filters (`eth_getLogs`, `eth_getFilterLogs`) are subject to the following limits by default:

  * **Open-ended block range:** up to 10,000 logs in one response
  * **Close-ended block range:** up to 2,000 blocks to query over

  Real-time subscriptions (`eth_subscribe` for `newHeads` and `logs`) are available over WebSocket only. See [WebSocket connections](/evm/evm-parity/websocket) for transport details.
</Info>

## Standard Ethereum endpoints

Every method below is also browsable interactively in the explorer above; this section is the static, copy-friendly reference. Methods are grouped by purpose and labelled with their Sei support status. Block parameters accept a hex number or one of the tags `latest`, `earliest`, `pending`, `safe`, or `finalized`. On Sei, `safe`, `finalized`, and `latest` all resolve to the latest committed block due to [instant finality](/evm/differences-with-ethereum#finality). The remaining deprecated `sei_*` extensions are documented separately under [Sei custom endpoints](#sei-custom-endpoints).

<Accordion title="Send transactions">
  #### `eth_sendRawTransaction`

  **Supported.** Submits a signed, RLP-encoded raw EVM transaction to the network and returns its hash.

  **Sei-specific behavior:** Decodes to an ethtypes.Transaction, wraps it in a Cosmos MsgEVMTransaction, and broadcasts via CometBFT (CheckTx-level BroadcastTx, i.e. `broadcast_tx_sync`, by default; slow mode uses BroadcastTxCommit). Non-zero CheckTx codes surface as ABCI errors, not geth mempool errors. Legacy (non-1559) txs must set gasPrice at or above the governance minimum (currently 50 gwei on mainnet); blob (EIP-4844) txs are not enabled. Supports per-sender EvmProxy forwarding.

  **Under Autobahn (`AutobahnConfigFile` set):** transaction broadcast routes through Autobahn's producer-backed mempool instead of CometBFT's `TxMempool`. This mempool admits EVM transactions strictly in sequential per-sender nonce order: a transaction whose nonce does not match the sender's next expected nonce is rejected with a bad-nonce error, so senders must submit nonces contiguously. The default CheckTx-synchronous broadcast (`broadcast_tx_sync`, the same path named above) blocks while the mempool is full and only returns once capacity is available — meaning a default `eth_sendRawTransaction` under Autobahn can stall for as long as the mempool stays full — whereas the async path (`broadcast_tx_async`) may silently drop the transaction instead. The `unsafe_flush_mempool` Tendermint RPC endpoint is not supported under Autobahn and returns `unsafe_flush_mempool is not supported with autobahn mempool`.

  **Parameters:**

  | #  | Name   | Type | Description                                          |
  | :- | :----- | :--- | :--------------------------------------------------- |
  | 1  | `data` | DATA | Signed, RLP-encoded transaction bytes (0x-prefixed). |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_sendRawTransaction",
    "params": [
      "0x02f8b101808459682f00..."
    ]
  }
  ```

  #### `eth_sendTransaction`

  **Limited.** Signs (with a node-hosted key) and submits a transaction in one call.

  **Sei-specific behavior:** Requires the 'from' address's private key in the node's local test keyring; production/public RPC nodes hold no hosted keys, so this returns 'from address does not have hosted key'. Always signs as LegacyTxType. Sign client-side and use eth\_sendRawTransaction instead.

  **Parameters:**

  | #  | Name   | Type   | Description                                                   |
  | :- | :----- | :----- | :------------------------------------------------------------ |
  | 1  | `args` | object | Transaction object (from, to, value, data, gas, nonce, etc.). |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_sendTransaction",
    "params": [
      {
        "from": "0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55",
        "to": "0x7507454444fa193d39f1392076bc784b77a7a8ff",
        "value": "0x1"
      }
    ]
  }
  ```

  #### `eth_signTransaction`

  **Limited.** Signs a transaction with a node-hosted key and returns the signed payload without broadcasting.

  **Sei-specific behavior:** Requires a node-hosted key for the from address; not usable on public RPC nodes that hold no keys. Returns both the raw RLP bytes and the decoded tx.

  **Parameters:**

  | #  | Name   | Type   | Description                                                                          |
  | :- | :----- | :----- | :----------------------------------------------------------------------------------- |
  | 1  | `args` | object | SendTxArgs transaction object to sign (from, to, gas, gasPrice, value, nonce, data). |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_signTransaction",
    "params": [
      {
        "from": "0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55",
        "to": "0x7507454444fa193d39f1392076bc784b77a7a8ff",
        "value": "0x1",
        "nonce": "0x0",
        "gas": "0x5208",
        "gasPrice": "0x3b9aca00"
      }
    ]
  }
  ```

  #### `eth_sign`

  **Limited.** Signs an EIP-191 personal message with a node-hosted key for the given address.

  **Sei-specific behavior:** Only works for addresses in the node's local test keyring; production/public RPC nodes hold no hosted keys, so this returns 'address does not have hosted key'. Applies the EIP-191 personal-message TextHash before signing.

  **Parameters:**

  | #  | Name      | Type           | Description                              |
  | :- | :-------- | :------------- | :--------------------------------------- |
  | 1  | `address` | DATA, 20 bytes | Address whose hosted key signs the data. |
  | 2  | `data`    | DATA           | Message bytes to sign.                   |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_sign",
    "params": [
      "0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55",
      "0xdeadbeef"
    ]
  }
  ```
</Accordion>

<Accordion title="Transaction lookup">
  #### `eth_getTransactionByHash`

  **Supported.** Returns the EVM transaction matching the given hash, or null if not found.

  **Sei-specific behavior:** Sees EVM transactions only; if the hash resolves to a non-EVM Cosmos tx it errors. Pending lookups resolve the transaction directly from the CometBFT mempool via an EVM-hash index (rather than a geth txpool), so a pending EVM tx is found by its hash without scanning through unconfirmed-transaction pages.

  **Parameters:**

  | #  | Name   | Type           | Description       |
  | :- | :----- | :------------- | :---------------- |
  | 1  | `hash` | DATA, 32 bytes | Transaction hash. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getTransactionByHash",
    "params": [
      "0x828c91592453fe7c5bf743204495a35bf02b67b579b8f59ee7eea8af031d7c14"
    ]
  }
  ```

  #### `eth_getTransactionReceipt`

  **Supported.** Returns the receipt of a transaction by hash, or null if not found.

  **Sei-specific behavior:** Receipt is reconstructed from keeper.GetReceipt + CometBFT block data rather than from a native MPT receipt trie; status/logs are standard Ethereum format. Under the Giga executor, an EVM transaction that bumps the sender's nonce but then fails during state transition now returns a `status=0` failed-tx receipt, rather than returning null indefinitely and hanging clients that poll for it. The known natural case is an EIP-7623 floor-data-gas shortfall (post-Pectra), which fails inside go-ethereum's `Execute()` before any opcode runs. The receipt is a synthetic one written at EndBlock, with `gasUsed` and `effectiveGasPrice` of 0. The `VmError` reason is not part of the `eth_getTransactionReceipt` response; retrieve it with the non-standard `eth_getVMError` method. If a receipt exists but its block height is above the safe-latest watermark (for example when Tendermint status momentarily lags the receipt store), the method returns JSON null rather than an error — the Ethereum JSON-RPC 'not yet mined' signal — so clients simply poll again, matching `eth_getBlockByNumber` behavior.

  **Parameters:**

  | #  | Name   | Type           | Description       |
  | :- | :----- | :------------- | :---------------- |
  | 1  | `hash` | DATA, 32 bytes | Transaction hash. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getTransactionReceipt",
    "params": [
      "0x828c91592453fe7c5bf743204495a35bf02b67b579b8f59ee7eea8af031d7c14"
    ]
  }
  ```

  #### `eth_getTransactionByBlockNumberAndIndex`

  **Supported.** Returns the EVM transaction at the given index within the block at the specified number.

  **Sei-specific behavior:** Index maps over EVM transactions only; an out-of-range index yields a null result rather than an error.

  **Parameters:**

  | #  | Name      | Type        | Description                         |
  | :- | :-------- | :---------- | :---------------------------------- |
  | 1  | `blockNr` | BLOCKNUMBER | Block number or tag.                |
  | 2  | `index`   | QUANTITY    | Transaction index within the block. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getTransactionByBlockNumberAndIndex",
    "params": [
      "latest",
      "0x0"
    ]
  }
  ```

  #### `eth_getTransactionByBlockHashAndIndex`

  **Supported.** Returns the EVM transaction at the given index within the block identified by hash.

  **Sei-specific behavior:** Index maps over EVM transactions only; same null-on-overflow semantics as the block-number variant.

  **Parameters:**

  | #  | Name        | Type           | Description                         |
  | :- | :---------- | :------------- | :---------------------------------- |
  | 1  | `blockHash` | DATA, 32 bytes | Block hash.                         |
  | 2  | `index`     | QUANTITY       | Transaction index within the block. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getTransactionByBlockHashAndIndex",
    "params": [
      "0x5620c15afd9a1d0ab19d7560043df6e038d731c6205974dca7a55900071e3864",
      "0x0"
    ]
  }
  ```

  #### `eth_getTransactionCount`

  **Supported.** Returns the number of transactions sent from an address (nonce) at a given block.

  **Sei-specific behavior:** For the 'pending' tag Sei returns EvmNextPendingNonce from the CometBFT mempool (or redirects to an EvmProxy if the sender is sharded there). safe/finalized/latest are equivalent due to instant finality.

  **Parameters:**

  | #  | Name            | Type                | Description                                                           |
  | :- | :-------------- | :------------------ | :-------------------------------------------------------------------- |
  | 1  | `address`       | DATA, 20 bytes      | Account address.                                                      |
  | 2  | `blockNrOrHash` | BLOCKNUMBER or DATA | Block number, tag, or hash; 'pending' returns the next pending nonce. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getTransactionCount",
    "params": [
      "0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55",
      "latest"
    ]
  }
  ```

  #### `eth_getNonce`

  **Limited.** Sei-specific helper that returns the current EVM nonce for an address (latest state only).

  **Sei-specific behavior:** Non-standard Sei extension exposed as eth\_getNonce, implemented as StateAPI.GetNonce in state.go (NOT on TransactionAPI). Unlike eth\_getTransactionCount it takes no block tag (latest-only via ctxProvider(LatestCtxHeight)) and returns a bare uint64 with no block-tag argument. Prefer eth\_getTransactionCount for standard nonce queries.

  **Parameters:**

  | #  | Name      | Type           | Description      |
  | :- | :-------- | :------------- | :--------------- |
  | 1  | `address` | DATA, 20 bytes | Account address. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getNonce",
    "params": [
      "0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55"
    ]
  }
  ```

  #### `eth_getTransactionErrorByHash`

  **Limited.** Sei extension that returns the recorded VM error string for a transaction by hash (empty string if it succeeded or is not found).

  **Sei-specific behavior:** Non-standard Sei extension registered under the eth namespace. Unlike eth\_getVMError, a not-found lookup returns an empty string and no error.

  **Parameters:**

  | #  | Name   | Type           | Description       |
  | :- | :----- | :------------- | :---------------- |
  | 1  | `hash` | DATA, 32 bytes | Transaction hash. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getTransactionErrorByHash",
    "params": [
      "0x828c91592453fe7c5bf743204495a35bf02b67b579b8f59ee7eea8af031d7c14"
    ]
  }
  ```

  #### `eth_getVMError`

  **Limited.** Sei extension that returns the EVM VM error string recorded in a transaction's receipt by hash.

  **Sei-specific behavior:** Non-standard Sei extension registered under the eth namespace. Returns the receipt's VmError field and propagates a not-found error (unlike eth\_getTransactionErrorByHash, which returns an empty string on not-found).

  **Parameters:**

  | #  | Name   | Type           | Description       |
  | :- | :----- | :------------- | :---------------- |
  | 1  | `hash` | DATA, 32 bytes | Transaction hash. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getVMError",
    "params": [
      "0x828c91592453fe7c5bf743204495a35bf02b67b579b8f59ee7eea8af031d7c14"
    ]
  }
  ```
</Accordion>

<Accordion title="Account information">
  #### `eth_getBalance`

  **Supported.** Returns the wei balance of an account at a given block.

  **Sei-specific behavior:** Balance reflects the account's SEI bank balance (18-decimal wei representation) and can change from both EVM and non-EVM (Cosmos bank send / wasm) transactions. Height is resolved via the watermark manager with a state-version guard.

  **Parameters:**

  | #  | Name            | Type                | Description                                                          |
  | :- | :-------------- | :------------------ | :------------------------------------------------------------------- |
  | 1  | `address`       | DATA, 20 bytes      | Account address.                                                     |
  | 2  | `blockNrOrHash` | BLOCKNUMBER or DATA | Block number, tag (latest/earliest/pending/safe/finalized), or hash. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getBalance",
    "params": [
      "0xDa52B9E673d1f48FcD9916b3F606A136a8eA5e55",
      "latest"
    ]
  }
  ```

  #### `eth_getCode`

  **Supported.** Returns the contract bytecode at an address for a given block.

  **Parameters:**

  | #  | Name            | Type                | Description                 |
  | :- | :-------------- | :------------------ | :-------------------------- |
  | 1  | `address`       | DATA, 20 bytes      | Contract address.           |
  | 2  | `blockNrOrHash` | BLOCKNUMBER or DATA | Block number, tag, or hash. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getCode",
    "params": [
      "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7",
      "latest"
    ]
  }
  ```

  #### `eth_getStorageAt`

  **Supported.** Returns the value stored at a storage slot of an address at a given block.

  **Sei-specific behavior:** Reads the EVM keeper's slot value directly rather than from an MPT trie. The slot key must decode to at most 32 bytes.

  **Parameters:**

  | #  | Name            | Type                | Description                             |
  | :- | :-------------- | :------------------ | :-------------------------------------- |
  | 1  | `address`       | DATA, 20 bytes      | Contract address.                       |
  | 2  | `key`           | DATA, 32 bytes      | Storage slot key (hex, up to 32 bytes). |
  | 3  | `blockNrOrHash` | BLOCKNUMBER or DATA | Block number, tag, or hash.             |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getStorageAt",
    "params": [
      "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7",
      "0x0",
      "latest"
    ]
  }
  ```

  #### `eth_getProof`

  **Limited.** Returns a Merkle proof for an account and the requested storage slots.

  **Sei-specific behavior:** Sei stores state in an IAVL-style tree, not an Ethereum Merkle-Patricia trie. The handler unwraps the EVM store through any intervening wrappers (cache, tracing, Giga cache, prefix stores) until it reaches an underlying proof-capable queryable store — classic IAVL, a store/v2 memiavl commitment, or any other proof-capable root — so proofs work across these backends rather than only classic IAVL. If no proof-capable queryable store can be reached it returns `cannot find a proof-capable queryable KV store`. The result is a Sei-specific ProofResult\{address, hexValues, storageProof} where storageProof entries are CometBFT/IAVL crypto.ProofOps, NOT eth-style MPT proof nodes. There is no accountProof, balance, codeHash, nonce, or storageHash field (Sei has no per-account state root); standard eth\_getProof verifiers will not work.

  **Parameters:**

  | #  | Name            | Type                    | Description                                                     |
  | :- | :-------------- | :---------------------- | :-------------------------------------------------------------- |
  | 1  | `address`       | DATA, 20 bytes          | Account address.                                                |
  | 2  | `storageKeys`   | array of DATA, 32 bytes | Storage slot keys to prove (bounded by MaxStorageKeysPerProof). |
  | 3  | `blockNrOrHash` | BLOCKNUMBER or DATA     | Block number, tag, or hash.                                     |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getProof",
    "params": [
      "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7",
      [
        "0x0"
      ],
      "latest"
    ]
  }
  ```

  #### `eth_accounts`

  **Limited.** Returns the list of addresses for which the node holds hosted keys.

  **Sei-specific behavior:** Sourced from the node's local test keyring only; production/public RPC nodes hold no hosted keys, so this returns an empty list. Sign client-side and use eth\_sendRawTransaction.

  **Parameters:** none.
</Accordion>

<Accordion title="Block information">
  #### `eth_getBlockByNumber`

  **Supported.** Returns block information by number or tag, with full transactions when fullTx is true.

  **Sei-specific behavior:** Under the eth namespace only EVM transactions are indexed (synthetic/bank-transfer txs excluded). Block number 0 returns a synthetic genesis block (for The Graph compatibility); future/non-existent numeric blocks return null. Uncle/PoW header fields (sha3Uncles, nonce, mixHash, difficulty) are placeholders and the uncles array is always empty (CometBFT consensus). safe/finalized/latest are equivalent due to instant finality.

  **Parameters:**

  | #  | Name     | Type        | Description                                                         |
  | :- | :------- | :---------- | :------------------------------------------------------------------ |
  | 1  | `number` | BLOCKNUMBER | Block number (hex) or tag (latest/safe/finalized/pending/earliest). |
  | 2  | `fullTx` | boolean     | If true include full transaction objects, else only hashes.         |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getBlockByNumber",
    "params": [
      "latest",
      true
    ]
  }
  ```

  #### `eth_getBlockByHash`

  **Supported.** Returns block information by block hash, with full transactions when fullTx is true.

  **Sei-specific behavior:** Block hashes are CometBFT block hashes (computed from the Tendermint header), so they differ from Ethereum block hashes and are not interchangeable across chains. Under the eth namespace synthetic txs and bank transfers are excluded. The genesis block hash (`0xF9D3845DF25B43B1C6926F3CEDA6845C17F5624E12212FD8847D0BA01DA1AB9E`, a synthetic constant identical on every Sei network, returned by the node in this uppercase form; lookups are case-insensitive) is recognized and returns the encoded genesis block directly, keeping hash-based lookups consistent with `eth_getBlockByNumber("0x0")`; other unknown/zero hashes return null. Uncles array is always empty.

  **Parameters:**

  | #  | Name        | Type           | Description                                                 |
  | :- | :---------- | :------------- | :---------------------------------------------------------- |
  | 1  | `blockHash` | DATA, 32 bytes | Block hash.                                                 |
  | 2  | `fullTx`    | boolean        | If true include full transaction objects, else only hashes. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getBlockByHash",
    "params": [
      "0x5620c15afd9a1d0ab19d7560043df6e038d731c6205974dca7a55900071e3864",
      false
    ]
  }
  ```

  #### `eth_getBlockTransactionCountByNumber`

  **Supported.** Returns the number of EVM transactions in a block by number, as a hex quantity.

  **Sei-specific behavior:** Counts the same transactions that appear in `eth_getBlockByNumber`'s transaction list. EVM transactions are counted only when a receipt exists for them, while synthetic (wasm `MsgExecuteContract`) and bank-transfer (`MsgSend`) transactions remain excluded. Genesis returns 0x0; non-existent/future blocks return null. Because the receipt store can be configured with a smaller `KeepRecent` than the block/state stores, this method now verifies that the requested block's receipts have not been pruned before counting: if they have, it returns an error of the form `requested height N receipts have been pruned; earliest available is M` rather than a count. This means the call can fail for older blocks even when the block data itself is still available.

  **Parameters:**

  | #  | Name     | Type        | Description          |
  | :- | :------- | :---------- | :------------------- |
  | 1  | `number` | BLOCKNUMBER | Block number or tag. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getBlockTransactionCountByNumber",
    "params": [
      "latest"
    ]
  }
  ```

  #### `eth_getBlockTransactionCountByHash`

  **Supported.** Returns the number of EVM transactions in a block by hash, as a hex quantity.

  **Sei-specific behavior:** Counts EVM transactions only; synthetic/bank-transfer txs are excluded. Genesis hash returns 0x0; unknown hash returns null. Like `eth_getBlockTransactionCountByNumber`, returns a "receipts have been pruned" error when the requested block's receipts have been pruned from the receipt store.

  **Parameters:**

  | #  | Name        | Type           | Description |
  | :- | :---------- | :------------- | :---------- |
  | 1  | `blockHash` | DATA, 32 bytes | Block hash. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getBlockTransactionCountByHash",
    "params": [
      "0x5620c15afd9a1d0ab19d7560043df6e038d731c6205974dca7a55900071e3864"
    ]
  }
  ```

  #### `eth_getBlockReceipts`

  **Supported.** Returns all EVM transaction receipts for a given block.

  **Sei-specific behavior:** Under the eth namespace synthetic/shell receipts are excluded (includeShellReceipts=false). Genesis returns an empty array. An empty (zero) or non-existent/unknown block hash returns `result: null` rather than an error, matching the Ethereum RPC spec. transactionIndex is recomputed sequentially over the compacted receipt list.

  **Parameters:**

  | #  | Name            | Type                | Description                 |
  | :- | :-------------- | :------------------ | :-------------------------- |
  | 1  | `blockNrOrHash` | BLOCKNUMBER or DATA | Block number, tag, or hash. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getBlockReceipts",
    "params": [
      "latest"
    ]
  }
  ```
</Accordion>

<Accordion title="Blockchain information">
  #### `eth_blockNumber`

  **Supported.** Returns the number of the most recent committed EVM block as a hex uint64.

  **Sei-specific behavior:** Block height comes from CometBFT latest height; the latest committed block is already final on Sei (instant finality, so latest == safe == finalized).

  **Parameters:** none.

  #### `eth_chainId`

  **Supported.** Returns the EVM chain ID as a hex big int.

  **Sei-specific behavior:** Sourced from the x/evm keeper. Mainnet (pacific-1) = 1329 (0x531); testnet (atlantic-2) = 1328 (0x530).

  **Parameters:** none.

  #### `eth_coinbase`

  **Limited.** Returns the block reward beneficiary (coinbase) address.

  **Sei-specific behavior:** Sei has no miner; this returns the Cosmos fee-collector module address (GetFeeCollectorAddress), not a validator/miner address. The COINBASE opcode returns the same value.

  **Parameters:** none.

  #### `eth_gasPrice`

  **Limited.** Returns a suggested gas price in wei (hex).

  **Sei-specific behavior:** Sei-specific congestion heuristic, not a raw mempool oracle. InfoAPI.GasPrice/GasPriceHelper (info.go): when uncongested it returns baseFee \* 110/100 (base fee +10%); when congested it returns medianRewardPrevBlock + baseFee (50th-percentile priority-fee reward from the previous block added to base fee). The base fee comes from the x/evm keeper (GetNextBaseFeePerGas), which is itself floored at the governance-set minimum base fee; the RPC handler applies no additional explicit lower-bound clamp. The mainnet minimum gas price (\~50 gwei) is enforced for transaction acceptance at the mempool/ante-handler level, not inside eth\_gasPrice.

  **Parameters:** none.

  #### `eth_maxPriorityFeePerGas`

  **Limited.** Returns a suggested priority fee (tip) per gas in wei (hex).

  **Sei-specific behavior:** Sei-specific: returns a hardcoded 1 gwei (defaultPriorityFeePerGas) when the chain is uncongested; only when congested does it derive the tip from the previous block's 50th-percentile reward. Sei docs advise using a single gasPrice and omitting EIP-1559 fee fields.

  **Parameters:** none.

  #### `eth_feeHistory`

  **Supported.** Returns base fees, gas-used ratios, and reward percentile data over a range of blocks.

  **Sei-specific behavior:** Base fees and rewards reflect Sei's x/evm fee market (GetNextBaseFee), not an Ethereum EIP-1559 mempool, and Sei does not burn the base fee. Watermark-aware: pruned/historical blocks may not be available as far back as on Ethereum archive nodes. Matching go-ethereum/execution-apis semantics, on ranges where every block has base-fee data, `baseFeePerGas` contains one more element than `gasUsedRatio`: the trailing element is the projected base fee for the child of the newest block in the range, appended only when the newest block's own header base fee was available. Heights with pruned or partial base-fee data are skipped from `baseFeePerGas` while still contributing a `gasUsedRatio` row (0.0 fallback), so the two arrays can diverge from that `+1` relationship on ranges with pruned history. Each block's base fee uses header base fee semantics (the same value reported in the block header — `GetNextBaseFee` at the parent's committed height) with a `DefaultMinFeePerGas` fallback for early blocks.

  **Parameters:**

  | #  | Name                | Type           | Description                                                              |
  | :- | :------------------ | :------------- | :----------------------------------------------------------------------- |
  | 1  | `blockCount`        | QUANTITY       | Number of blocks in the requested range.                                 |
  | 2  | `newestBlock`       | BLOCKNUMBER    | Highest block of the range (number or tag).                              |
  | 3  | `rewardPercentiles` | array of float | Monotonically increasing percentiles to sample for priority-fee rewards. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_feeHistory",
    "params": [
      "0x5",
      "latest",
      [
        25,
        50,
        75
      ]
    ]
  }
  ```

  #### `net_version`

  **Supported.** Returns the network/chain ID as a decimal string.

  **Sei-specific behavior:** Returns the EVM chain ID in decimal (alias of eth\_chainId): '1329' on pacific-1 mainnet, '1328' on atlantic-2 testnet.

  **Parameters:** none.

  #### `web3_clientVersion`

  **Supported.** Returns the client version string.

  **Sei-specific behavior:** Reports a synthetic 'Geth/\<os>-\<arch>/\<goVersion>' string (Sei's EVM is backed by go-ethereum); it does NOT embed the actual sei-chain/seid version, so it is not a reliable Sei version indicator.

  **Parameters:** none.
</Accordion>

<Accordion title="Filters & subscriptions">
  #### `eth_newFilter`

  **Supported.** Creates a log filter for the given criteria and returns a filter ID for later polling.

  **Sei-specific behavior:** Subject to the same range/size caps as eth\_getLogs: open-ended ranges return up to 10,000 logs (DefaultMaxLogLimit); close-ended ranges are limited to 2,000 blocks (DefaultMaxBlockRange), with large-query rate limiting.

  **Parameters:**

  | #  | Name   | Type   | Description                                                                  |
  | :- | :----- | :----- | :--------------------------------------------------------------------------- |
  | 1  | `crit` | object | Filter criteria: fromBlock, toBlock (or blockHash), address(es), and topics. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_newFilter",
    "params": [
      {
        "fromBlock": "latest",
        "address": "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7",
        "topics": []
      }
    ]
  }
  ```

  #### `eth_newBlockFilter`

  **Supported.** Creates a filter that tracks newly arrived block hashes and returns its ID.

  **Parameters:** none.

  #### `eth_getFilterChanges`

  **Supported.** Polls a filter and returns new logs (log filters) or block hashes (block filters) since the last poll.

  **Sei-specific behavior:** For log filters, returns an empty array (`[]`) rather than `null` when no logs match or a bounded filter's block range has been fully consumed, in line with the Ethereum JSON-RPC spec.

  **Parameters:**

  | #  | Name       | Type        | Description                        |
  | :- | :--------- | :---------- | :--------------------------------- |
  | 1  | `filterID` | QUANTITY/ID | Filter ID from a New\*Filter call. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getFilterChanges",
    "params": [
      "0x1"
    ]
  }
  ```

  #### `eth_getFilterLogs`

  **Supported.** Returns all logs matching a previously created log filter, including historical logs.

  **Sei-specific behavior:** Bounded by the same caps as eth\_getLogs (2,000-block range, 10,000-log limit) with large-query rate limiting.

  **Parameters:**

  | #  | Name       | Type        | Description                      |
  | :- | :--------- | :---------- | :------------------------------- |
  | 1  | `filterID` | QUANTITY/ID | Filter ID from a NewFilter call. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getFilterLogs",
    "params": [
      "0x1"
    ]
  }
  ```

  #### `eth_getLogs`

  **Supported.** Returns logs matching the given filter criteria.

  **Sei-specific behavior:** Returns EVM logs only. Hard limits: max 2,000 blocks per close-ended query and up to 10,000 logs per response; exceeding the range errors with 'block range too large'. Large queries are globally rate-limited.

  **Parameters:**

  | #  | Name   | Type   | Description                                                              |
  | :- | :----- | :----- | :----------------------------------------------------------------------- |
  | 1  | `crit` | object | Filter criteria: fromBlock, toBlock (or blockHash), address(es), topics. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getLogs",
    "params": [
      {
        "fromBlock": "0x0",
        "toBlock": "latest",
        "address": "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7",
        "topics": []
      }
    ]
  }
  ```

  #### `eth_uninstallFilter`

  **Supported.** Removes a previously installed filter by ID; returns true if it existed and was removed.

  **Sei-specific behavior:** Returns false if the filter did not exist rather than erroring. Filters also expire automatically when not polled.

  **Parameters:**

  | #  | Name       | Type        | Description          |
  | :- | :--------- | :---------- | :------------------- |
  | 1  | `filterID` | QUANTITY/ID | Filter ID to remove. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_uninstallFilter",
    "params": [
      "0x1"
    ]
  }
  ```

  #### `eth_subscribe`

  **Limited.** Opens a WebSocket-only push subscription for newHeads or logs notifications.

  **Sei-specific behavior:** WebSocket-only (SubscriptionAPI is not registered on the HTTP server; returns rpc.ErrNotificationsUnsupported over HTTP). Only 'newHeads' and 'logs' are implemented in source; there is no 'newPendingTransactions' subscription despite some client docs implying otherwise. newHeads subscriptions are capped by MaxSubscriptionsNewHead.

  **Parameters:**

  | #  | Name               | Type   | Description                                                            |
  | :- | :----------------- | :----- | :--------------------------------------------------------------------- |
  | 1  | `subscriptionType` | string | Subscription name: 'newHeads' or 'logs'.                               |
  | 2  | `filter`           | object | Optional filter criteria (address/topics) for the 'logs' subscription. |

  The `filter` object applies only to `logs` subscriptions. For `newHeads`, pass the subscription name alone: `"params": ["newHeads"]`.

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_subscribe",
    "params": [
      "logs",
      {
        "address": "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7",
        "topics": []
      }
    ]
  }
  ```

  #### `eth_unsubscribe`

  **Supported.** Cancels an existing WebSocket subscription by ID; returns true on success.

  **Sei-specific behavior:** WebSocket only; has no effect over HTTP (notifications unsupported there).

  **Parameters:**

  | #  | Name             | Type   | Description                                                  |
  | :- | :--------------- | :----- | :----------------------------------------------------------- |
  | 1  | `subscriptionID` | string | The subscription ID returned by a prior eth\_subscribe call. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_unsubscribe",
    "params": [
      "0x9cef478923ff08bf67fde6c64013158d"
    ]
  }
  ```
</Accordion>

<Accordion title="Simulation">
  #### `eth_call`

  **Supported.** Executes a read-only message call against state without creating a transaction; supports state and block overrides.

  **Sei-specific behavior:** Gas is capped by RPCGasCap and execution time by RPCEVMTimeout; a fail-fast limiter may reject with 'eth\_call rejected due to rate limit: server busy'. Canonical EVM\<->Sei address resolution uses eth\_call to the addr precompile at 0x0000000000000000000000000000000000001004.

  **Parameters:**

  | #  | Name             | Type                | Description                                                            |
  | :- | :--------------- | :------------------ | :--------------------------------------------------------------------- |
  | 1  | `args`           | object              | Call object (to, from, data/input, gas, gasPrice/maxFeePerGas, value). |
  | 2  | `blockNrOrHash`  | BLOCKNUMBER or DATA | Block number, tag, or hash. Defaults to latest.                        |
  | 3  | `overrides`      | object              | Optional per-account state overrides (balance, code, nonce, state).    |
  | 4  | `blockOverrides` | object              | Optional block-context overrides (number, time, coinbase).             |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_call",
    "params": [
      {
        "to": "0x0000000000000000000000000000000000001004",
        "data": "0x0c3c20ed000000000000000000000000Da52B9E673d1f48FcD9916b3F606A136a8eA5e55"
      },
      "latest"
    ]
  }
  ```

  #### `eth_estimateGas`

  **Supported.** Estimates the gas needed to execute a transaction.

  **Sei-specific behavior:** Bounded by RPCGasCap and protected by a fail-fast limiter. Block gas limit on Sei is 12.5M; parallel execution can cause estimates to vary slightly, so size gasLimit with a modest buffer.

  **Parameters:**

  | #  | Name            | Type                | Description                                              |
  | :- | :-------------- | :------------------ | :------------------------------------------------------- |
  | 1  | `args`          | object              | Transaction call object.                                 |
  | 2  | `blockNrOrHash` | BLOCKNUMBER or DATA | Optional block number, tag, or hash; defaults to latest. |
  | 3  | `overrides`     | object              | Optional state overrides.                                |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_estimateGas",
    "params": [
      {
        "to": "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7",
        "data": "0x18160ddd"
      },
      "latest"
    ]
  }
  ```

  #### `eth_estimateGasAfterCalls`

  **Limited.** Estimates gas for a transaction after first applying a sequence of preceding calls against the same simulated state.

  **Sei-specific behavior:** Non-standard Sei/geth extension (not part of the standard Ethereum JSON-RPC spec). Same gas-cap and fail-fast-limiter behavior as eth\_estimateGas.

  **Parameters:**

  | #  | Name            | Type                | Description                                                  |
  | :- | :-------------- | :------------------ | :----------------------------------------------------------- |
  | 1  | `args`          | object              | The final call to estimate gas for.                          |
  | 2  | `calls`         | array of object     | Ordered list of preceding calls applied before the estimate. |
  | 3  | `blockNrOrHash` | BLOCKNUMBER or DATA | Optional block number, tag, or hash; defaults to latest.     |
  | 4  | `overrides`     | object              | Optional state overrides.                                    |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_estimateGasAfterCalls",
    "params": [
      {
        "to": "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7",
        "data": "0x"
      },
      [],
      "latest"
    ]
  }
  ```

  #### `eth_createAccessList`

  **Supported.** Generates an EIP-2930 access list (and gas used) for a transaction.

  **Sei-specific behavior:** Defaults to the pending block tag (matching geth). A VM error during simulation is surfaced in the result's 'error' field rather than failing the RPC.

  **Parameters:**

  | #  | Name            | Type                | Description                                               |
  | :- | :-------------- | :------------------ | :-------------------------------------------------------- |
  | 1  | `args`          | object              | Transaction call object.                                  |
  | 2  | `blockNrOrHash` | BLOCKNUMBER or DATA | Optional block number, tag, or hash; defaults to pending. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_createAccessList",
    "params": [
      {
        "to": "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7",
        "data": "0x"
      },
      "pending"
    ]
  }
  ```
</Accordion>

<Accordion title="Transaction pool">
  #### `txpool_content`

  **Limited.** Returns the transactions currently in the pool, grouped by sender address and nonce into pending and queued buckets.

  **Sei-specific behavior:** Sei-specific simplification: every unconfirmed EVM tx from the CometBFT mempool is reported under 'pending' and 'queued' is always empty (no geth-style pending/queued nonce-gap distinction). The result set is truncated to the node's MaxTxPoolTxs config, so it may not reflect the entire mempool.

  **Parameters:** none.
</Accordion>

<Accordion title="Debugging & tracing">
  #### `debug_traceTransaction`

  **Supported.** Replays a transaction by hash and returns an execution trace using the configured tracer.

  **Sei-specific behavior:** HTTP-only (the debug namespace is not registered on the WebSocket server). Supports geth tracers (callTracer, prestateTracer, flatCallTracer, struct/opcode logger); callTracer/prestateTracer/flatCallTracer results are pre-baked/cached via TraceBaker. Requires trace-enabled/archive state for the target height. Subject to the max block lookback guard (`max_trace_lookback_blocks`): a request whose target block is older than the configured lookback is rejected with an error of the form `block number X is beyond max lookback of Y`. This guard now applies consistently across all `debug_trace*` endpoints, and such attempts increment the `evmrpc_historical_debug_trace_attempts_total` metric.

  **Parameters:**

  | #  | Name     | Type           | Description                                                                                       |
  | :- | :------- | :------------- | :------------------------------------------------------------------------------------------------ |
  | 1  | `hash`   | DATA, 32 bytes | Transaction hash to trace.                                                                        |
  | 2  | `config` | object         | Optional tracer config (tracer name, tracerConfig, timeout, reexec, disableStorage/Stack/Memory). |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "debug_traceTransaction",
    "params": [
      "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060",
      {
        "tracer": "callTracer"
      }
    ]
  }
  ```

  #### `debug_traceBlockByNumber`

  **Supported.** Traces all transactions in a block by number and returns per-transaction execution traces.

  **Sei-specific behavior:** HTTP-only. safe/finalized/latest are equivalent due to instant finality. Subject to the `max_trace_lookback_blocks` historical guard (see `debug_traceTransaction`).

  **Parameters:**

  | #  | Name     | Type        | Description             |
  | :- | :------- | :---------- | :---------------------- |
  | 1  | `number` | BLOCKNUMBER | Block number or tag.    |
  | 2  | `config` | object      | Optional tracer config. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "debug_traceBlockByNumber",
    "params": [
      "latest",
      {
        "tracer": "callTracer"
      }
    ]
  }
  ```

  #### `debug_traceBlockByHash`

  **Supported.** Traces all transactions in a block by hash and returns per-transaction execution traces.

  **Sei-specific behavior:** HTTP-only. Subject to the `max_trace_lookback_blocks` historical guard (see `debug_traceTransaction`).

  **Parameters:**

  | #  | Name     | Type           | Description             |
  | :- | :------- | :------------- | :---------------------- |
  | 1  | `hash`   | DATA, 32 bytes | Block hash.             |
  | 2  | `config` | object         | Optional tracer config. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "debug_traceBlockByHash",
    "params": [
      "0x5620c15afd9a1d0ab19d7560043df6e038d731c6205974dca7a55900071e3864",
      {
        "tracer": "callTracer"
      }
    ]
  }
  ```

  #### `debug_traceCall`

  **Supported.** Executes and traces a call against a block's state without creating a transaction.

  **Sei-specific behavior:** HTTP-only. Arbitrary geth tracer names pass through. Tracing on the pending block is not supported. Subject to the `max_trace_lookback_blocks` historical guard (see `debug_traceTransaction`).

  **Parameters:**

  | #  | Name            | Type                | Description                                                                 |
  | :- | :-------------- | :------------------ | :-------------------------------------------------------------------------- |
  | 1  | `args`          | object              | Transaction call object.                                                    |
  | 2  | `blockNrOrHash` | BLOCKNUMBER or DATA | Block number, tag, or hash.                                                 |
  | 3  | `config`        | object              | Optional trace-call config (tracer name, state overrides, block overrides). |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "debug_traceCall",
    "params": [
      {
        "to": "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7",
        "data": "0x70a08231"
      },
      "latest",
      {
        "tracer": "callTracer"
      }
    ]
  }
  ```

  #### `debug_traceStateAccess`

  **Limited.** Sei extension that replays a transaction and returns its app/tendermint/receipt state-access traces.

  **Sei-specific behavior:** Sei-specific extension (not part of upstream go-ethereum's debug namespace). HTTP-only and subject to historical-debug-trace availability guards. Subject to the `max_trace_lookback_blocks` historical guard (see `debug_traceTransaction`).

  **Parameters:**

  | #  | Name   | Type           | Description                                         |
  | :- | :----- | :------------- | :-------------------------------------------------- |
  | 1  | `hash` | DATA, 32 bytes | Transaction hash whose state accesses are returned. |

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "debug_traceStateAccess",
    "params": [
      "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"
    ]
  }
  ```

  #### `debug_traceTransactionProfile`

  **Limited.** Sei extension that replays a transaction by hash and returns its execution trace alongside a detailed timing and store-access profile.

  **Sei-specific behavior:** Sei-specific extension (not part of upstream go-ethereum's debug namespace). HTTP-only and subject to historical-debug-trace availability guards. In addition to the standard trace result, it returns a `profile` object breaking down where time was spent — total wall time, historical DB lookup time, and per-phase timings (transaction lookup, block load, historical tx replay, block-context build, tx prepare, execution, and trace-result assembly) — plus a per-module `store` access trace (reads, iterators with the keys they surfaced, and per-operation `stats` roll-ups). Per-tx caps bound the trace size: at most 16 iterators and 64 keys per iterator are retained per module, with overflow flagged via `truncated`. To run this method across a whole block range and generate aggregate reports, use the `seidb trace-profile-report` command. Subject to the `max_trace_lookback_blocks` historical guard (see `debug_traceTransaction`).

  **Parameters:**

  | #  | Name     | Type           | Description                                                                                       |
  | :- | :------- | :------------- | :------------------------------------------------------------------------------------------------ |
  | 1  | `hash`   | DATA, 32 bytes | Transaction hash to trace and profile.                                                            |
  | 2  | `config` | object         | Optional tracer config (tracer name, tracerConfig, timeout, reexec, disableStorage/Stack/Memory). |

  The response `result` contains a `trace` field (the standard tracer output) and a `profile` object shaped as follows:

  * `totalNanos` — total wall-clock nanoseconds for the profiled trace.
  * `historicalDbLookupNanos` — nanoseconds spent in historical store lookups (get/has/iterator/iteratorNext).
  * `otherNanos` — remaining time not attributed to historical lookups or execution.
  * `phases` — per-phase timings: `lookupTransactionNanos`, `loadBlockNanos`, `replayHistoricalTxsNanos`, `buildBlockContextNanos`, `prepareTxNanos`, `executionNanos`, `traceResultNanos`.
  * `store` — per-module store access trace: `modules` (each with `reads`, `has`, `iterators`, and per-op `stats`) and top-level `stats`.

  **Example request:**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "debug_traceTransactionProfile",
    "params": [
      "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060",
      {
        "timeout": "60s"
      }
    ]
  }
  ```

  **Example response (trimmed):**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
      "trace": { "...": "standard tracer output" },
      "profile": {
        "totalNanos": 18422119,
        "historicalDbLookupNanos": 10021554,
        "otherNanos": 8400565,
        "phases": {
          "lookupTransactionNanos": 310221,
          "loadBlockNanos": 902114,
          "replayHistoricalTxsNanos": 6114203,
          "buildBlockContextNanos": 421900,
          "prepareTxNanos": 188212,
          "executionNanos": 9873341,
          "traceResultNanos": 612128
        }
      }
    }
  }
  ```
</Accordion>

## Sei custom endpoints

Sei keeps four legacy custom endpoints for address resolution, cross-VM transaction lookup, and synthetic receipts.

<Warning>
  The `sei2_*` namespace has been removed. Most legacy `sei_*` methods have also been removed, including block, filter, log, signing, association, and transaction lookup methods. The `sei_*` cleanup is tracked in [sei-chain PR #3927](https://github.com/sei-protocol/sei-chain/pull/3927).

  The four remaining `sei_*` methods are deprecated and scheduled for removal. Use standard `eth_*` and `debug_*` methods for new integrations.
</Warning>

<Note>There is no remaining block or filter method for discovering synthetic logs from Cosmos-originated transactions. If you already know a synthetic transaction hash, enable `sei_getTransactionReceipt` to retrieve its receipt and logs.</Note>

Access is controlled by the `enabled_legacy_sei_apis` setting under `[evm]` in `app.toml`. Only methods explicitly listed in this allowlist are available. Disabled methods return a standard JSON-RPC error (code `-32601`, data `"legacy_sei_deprecated"`). Allowed single-object calls pass through unchanged, with an optional `Sei-Legacy-RPC-Deprecation` HTTP response header signaling deprecation.

JSON-RPC batches are handled by the gate rather than passed through wholesale. Only allowed methods are forwarded to the inner handler. The handler then merges responses by matching each response's JSON-RPC `id`. Disallowed methods return the usual `-32601` legacy deprecation error in their slot. A batch element that is not a JSON object returns a JSON-RPC `-32600` `"Invalid Request"` error in its slot.

Per JSON-RPC 2.0, requests that omit the `id` member are notifications and do not produce a response entry, including within a batch. A request with `"id": null` is not a notification and receives a response. If a batch produces no response objects, the gateway returns an empty HTTP body with HTTP 200 rather than an empty JSON array (`[]`).

### Legacy API configuration

The `enabled_legacy_sei_apis` setting controls which remaining `sei_*` methods are accessible on the EVM HTTP endpoint. `seid init` enables the three address and cross-VM lookup helpers by default:

```toml theme={"dark"}
[evm]
enabled_legacy_sei_apis = [
  "sei_getSeiAddress",
  "sei_getEVMAddress",
  "sei_getCosmosTx",

  # Optional: enable synthetic receipt lookup.
  # "sei_getTransactionReceipt",
]
```

Only these four methods are available:

| Method                      | Description                                                                              |
| --------------------------- | ---------------------------------------------------------------------------------------- |
| `sei_getSeiAddress`         | Get the Sei address associated with an EVM address.                                      |
| `sei_getEVMAddress`         | Get the EVM address associated with a Sei address.                                       |
| `sei_getCosmosTx`           | Get the wrapping Cosmos transaction hash as uppercase hexadecimal without a `0x` prefix. |
| `sei_getTransactionReceipt` | Get a receipt, including a synthetic receipt when its transaction hash is known.         |

### Address resolution

For resolving the EVM (`0x…`) ↔ Sei (`sei1…`) address pair, use the **`addr` precompile at `0x0000000000000000000000000000000000001004`** via a standard `eth_call`. The precompile is universally available on every Sei RPC, is not part of the deprecated `sei_*` namespace, and is the canonical resolution path going forward.

```bash theme={"dark"}
# EVM → Sei (getSeiAddr(address), selector 0x0c3c20ed)
curl -X POST $SEIEVM -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "method": "eth_call",
  "params": [{
    "to": "0x0000000000000000000000000000000000001004",
    "data": "0x0c3c20ed000000000000000000000000<evmAddressWithout0x>"
  }, "latest"],
  "id": 1
}'
```

In TypeScript with viem:

```ts theme={"dark"}
import { createPublicClient, http } from 'viem';
import { sei } from 'viem/chains';

const ADDR_PRECOMPILE = '0x0000000000000000000000000000000000001004';
const ADDR_ABI = [
  { name: 'getSeiAddr', type: 'function', stateMutability: 'view',
    inputs: [{ name: 'addr', type: 'address' }],
    outputs: [{ name: 'response', type: 'string' }] },
  { name: 'getEvmAddr', type: 'function', stateMutability: 'view',
    inputs: [{ name: 'addr', type: 'string' }],
    outputs: [{ name: 'response', type: 'address' }] },
] as const;

const client = createPublicClient({ chain: sei, transport: http() });

const seiAddr = await client.readContract({
  address: ADDR_PRECOMPILE, abi: ADDR_ABI, functionName: 'getSeiAddr', args: ['0x…'],
});

const evmAddr = await client.readContract({
  address: ADDR_PRECOMPILE, abi: ADDR_ABI, functionName: 'getEvmAddr', args: ['sei1…'],
});
```

The call reverts when the input address is not yet associated. See [Accounts](/learn/accounts) for the full association lifecycle and how the bidirectional mapping is established.

<Note>The legacy JSON-RPC helpers `sei_getSeiAddress` and `sei_getEVMAddress` historically served this role and are still enabled by default on nodes today, but they belong to the deprecated `sei_*` namespace and may be removed in a future release. New integrations should call the precompile.</Note>

### Cross-VM transaction lookup

`sei_getCosmosTx` resolves the underlying Cosmos transaction hash for a given EVM transaction. It returns the hash as uppercase hexadecimal without a `0x` prefix. The method does not yet have a precompile equivalent and is enabled by default on Sei nodes.

<Accordion title="View Cross-VM Lookup Endpoints">
  #### sei\_getCosmosTx

  Returns the wrapping Cosmos transaction hash for a given EVM transaction hash.

  * **Parameters**:

  | Type             | Description                             |
  | :--------------- | :-------------------------------------- |
  | `DATA, 32 bytes` | The `0x`-prefixed EVM transaction hash. |

  * **Result**:

  | Type     | Description                                                                 |
  | :------- | :-------------------------------------------------------------------------- |
  | `string` | The Cosmos transaction hash as uppercase hexadecimal without a `0x` prefix. |

  **Example Request**

  ```json theme={"dark"}
  {
    "jsonrpc": "2.0",
    "method": "sei_getCosmosTx",
    "params": ["0x828c91592453fe7c5bf743204495a35bf02b67b579b8f59ee7eea8af031d7c14"],
    "id": 1
  }
  ```
</Accordion>

### Legacy deprecation error

When a remaining `sei_*` method is called but not listed in `enabled_legacy_sei_apis`, the node returns:

```json theme={"dark"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32601,
    "message": "sei_getTransactionReceipt is not enabled on this node. The sei_* JSON-RPC surface is deprecated, scheduled for removal, and should not be used for new integrations - prefer standard eth_* (and debug_*) methods and official migration guidance. To allow this legacy method, add it to enabled_legacy_sei_apis under [evm] in app.toml.",
    "data": "legacy_sei_deprecated"
  }
}
```

### Deprecation HTTP header

When an allowlisted `sei_*` method is successfully called, the response includes an optional HTTP header signaling deprecation:

```
Sei-Legacy-RPC-Deprecation: All sei_* JSON-RPC methods are deprecated and scheduled for removal; migrate to eth_* and supported APIs.
```

Clients can use this header to detect legacy API usage and plan migration.
