diff --git a/docs.json b/docs.json
index 2fb505b..63f1057 100644
--- a/docs.json
+++ b/docs.json
@@ -504,6 +504,16 @@
"prompt": "Search the Sei docs..."
},
"redirects": [
+ {
+ "source": "/learn/getting-started",
+ "destination": "/learn",
+ "permanent": true
+ },
+ {
+ "source": "/evm/getting-started",
+ "destination": "/learn",
+ "permanent": true
+ },
{
"source": "/evm/ai-tooling/mcp-server",
"destination": "/ai/mcp-server",
diff --git a/evm/building-a-frontend.mdx b/evm/building-a-frontend.mdx
index ca6b4fd..6886ee4 100644
--- a/evm/building-a-frontend.mdx
+++ b/evm/building-a-frontend.mdx
@@ -102,7 +102,7 @@ touch src/wagmi.ts
## Defining the ERC20 Contract Details
-Make sure to deploy your ERC20 token contract first and replace `TOKEN_CONTRACT_ADDRESS` in the constants file with your actual deployed contract address, and update the RPC URL in the Sei chain configuration. You can find a list of existing ERC20 contracts on Sei Mainnet here: [Sei Assets](https://seiscan.io/tokens)
+Make sure to deploy your ERC20 token contract first — for example with [Hardhat](/evm/evm-hardhat) or [Foundry](/evm/evm-foundry), or generate one with the [contract wizard](/evm/evm-wizard) (see also [deploy & verify](/evm/evm-parity/examples/deploy-verify)) — and replace `TOKEN_CONTRACT_ADDRESS` in the constants file with your actual deployed contract address, and update the RPC URL in the Sei chain configuration. You can find a list of existing ERC20 contracts on Sei Mainnet here: [Sei Assets](https://seiscan.io/tokens)
Let's create a shared constants file for our project:
@@ -218,7 +218,7 @@ export const ERC20_ABI = [
}
];
-// TODO: Replace with your deployed ERC20 token contract address
+// TODO: Deploy an ERC-20 (see /evm/evm-hardhat or /evm/evm-foundry) and paste its address here
export const TOKEN_CONTRACT_ADDRESS = '0xYourTokenContractAddress';
```
diff --git a/evm/evm-parity/examples/ethers-quickstart.mdx b/evm/evm-parity/examples/ethers-quickstart.mdx
index aba4972..c0e34a0 100644
--- a/evm/evm-parity/examples/ethers-quickstart.mdx
+++ b/evm/evm-parity/examples/ethers-quickstart.mdx
@@ -23,16 +23,29 @@ const provider = new ethers.JsonRpcProvider('https://evm-rpc.sei-apis.com');
## Reading Chain Data
+This is the first milestone — it needs no private key.
+
```ts
-const blockNumber = await provider.getBlockNumber();
+const blockNumber = await provider.getBlockNumber(); // number
+console.log('Block number:', blockNumber);
+
+const balance = await provider.getBalance('0xYourAddress'); // bigint, wei
+console.log('Balance (SEI):', ethers.formatEther(balance));
-const block = await provider.getBlock('latest');
+const nonce = await provider.getTransactionCount('0xYourAddress'); // number
+console.log('Nonce:', nonce);
+```
-const balance = await provider.getBalance('0xYourAddress');
+**You're done when you see:**
-const nonce = await provider.getTransactionCount('0xYourAddress');
+```text
+Block number: 148203117
+Balance (SEI): 12.5
+Nonce: 7
```
+The exact numbers are illustrative — your block number and balance will differ. `getBlockNumber()` and `getTransactionCount()` return a `number`, while `getBalance()` returns a `bigint` in wei (format it with `ethers.formatEther()`).
+
## Browser Provider
In a browser context, connect to the user's injected wallet:
@@ -53,6 +66,8 @@ const wallet = new ethers.Wallet('0xYourPrivateKey', provider);
## Sending a Transaction
+Next step — this requires a funded account; get testnet SEI from the [faucet](/learn/faucet).
+
```ts
const tx = await wallet.sendTransaction({
to: '0xRecipient',
@@ -104,6 +119,34 @@ contract.on('Transfer', (from, to, value) => {
contract.off('Transfer');
```
+## Using Python (web3.py)
+
+Sei is fully EVM-compatible, so any standard Ethereum client works — including Python's [web3.py](https://web3py.readthedocs.io).
+
+```bash
+pip install web3
+```
+
+```python
+from web3 import Web3
+
+w3 = Web3(Web3.HTTPProvider("https://evm-rpc.sei-apis.com"))
+
+print("Connected:", w3.is_connected())
+print("Latest block:", w3.eth.block_number)
+print("Chain ID:", w3.eth.chain_id) # 1329
+```
+
+**You're done when you see:**
+
+```text
+Connected: True
+Latest block: 148203117
+Chain ID: 1329
+```
+
+The block number is illustrative; the chain ID is always `1329` on mainnet.
+
## Next Steps
- [ERC-20 interaction](/evm/evm-parity/examples/erc20) — full token read/write examples
diff --git a/evm/evm-parity/examples/viem-quickstart.mdx b/evm/evm-parity/examples/viem-quickstart.mdx
index de3a56a..0a5bba0 100644
--- a/evm/evm-parity/examples/viem-quickstart.mdx
+++ b/evm/evm-parity/examples/viem-quickstart.mdx
@@ -38,16 +38,31 @@ const client = createPublicClient({
## Reading Chain Data
+This is the first milestone — it needs no private key.
+
```ts
-const blockNumber = await client.getBlockNumber();
+import { formatEther } from 'viem';
-const block = await client.getBlock({ blockTag: 'latest' });
+const blockNumber = await client.getBlockNumber(); // bigint
+console.log('Block number:', blockNumber);
-const balance = await client.getBalance({ address: '0xYourAddress' });
+const balance = await client.getBalance({ address: '0xYourAddress' }); // bigint, wei
+console.log('Balance (SEI):', formatEther(balance));
-const nonce = await client.getTransactionCount({ address: '0xYourAddress' });
+const nonce = await client.getTransactionCount({ address: '0xYourAddress' }); // number
+console.log('Nonce:', nonce);
```
+**You're done when you see:**
+
+```text
+Block number: 148203117n
+Balance (SEI): 12.5
+Nonce: 7
+```
+
+The exact numbers are illustrative — your block number and balance will differ. Note the trailing `n`: `getBlockNumber()` and `getBalance()` return `bigint`, while `getTransactionCount()` returns a `number`.
+
## Wallet Client
A wallet client handles signing and broadcasting transactions.
@@ -70,6 +85,8 @@ For browser use, replace `http()` with `custom(window.ethereum)` and call `walle
## Sending a Transaction
+Next step — this requires a funded account; get testnet SEI from the [faucet](/learn/faucet).
+
```ts
import { parseEther } from 'viem';
@@ -137,6 +154,34 @@ const gas = await client.estimateGas({
});
```
+## Using Python (web3.py)
+
+Sei is fully EVM-compatible, so any standard Ethereum client works — including Python's [web3.py](https://web3py.readthedocs.io).
+
+```bash
+pip install web3
+```
+
+```python
+from web3 import Web3
+
+w3 = Web3(Web3.HTTPProvider("https://evm-rpc.sei-apis.com"))
+
+print("Connected:", w3.is_connected())
+print("Latest block:", w3.eth.block_number)
+print("Chain ID:", w3.eth.chain_id) # 1329
+```
+
+**You're done when you see:**
+
+```text
+Connected: True
+Latest block: 148203117
+Chain ID: 1329
+```
+
+The block number is illustrative; the chain ID is always `1329` on mainnet.
+
## Next Steps
- [ERC-20 interaction](/evm/evm-parity/examples/erc20) — full token read/write examples
diff --git a/evm/index.mdx b/evm/index.mdx
index c8dd343..60f4f98 100644
--- a/evm/index.mdx
+++ b/evm/index.mdx
@@ -74,11 +74,26 @@ keywords: ["sei evm", "ethereum virtual machine", "web3 development", "blockchai
## RPC Endpoints
-Choose from official Sei Foundation endpoints or community-maintained alternatives. All endpoints support standard EVM JSON-RPC methods. Public endpoints have rate limits—for production apps, consider using a dedicated RPC provider or running your own node.
+Choose from official Sei Foundation endpoints or community-maintained alternatives. All endpoints support standard EVM JSON-RPC methods. Public endpoints have rate limits — for production apps, use a [dedicated RPC provider](/learn/rpc-providers) or [run your own node](/node).
-
+
+
+ | Endpoint | Provider | Type | Rate limit | Notes |
+ | --- | --- | --- | --- | --- |
+ | `https://evm-rpc.sei-apis.com` | Sei Foundation | public | 10 req/s | Recommended for development |
+ | `https://evm-rpc-sei.stingray.plus` | Staketab | public | — | Community maintained |
+ | `https://sei-evm-rpc.publicnode.com` | PublicNode | public | 5 req/s | Community maintained |
+ | `https://seievm-rpc.polkachu.com` | Polkachu | public | — | Community maintained |
+ | `https://jsonrpc.lavenderfive.com:443/sei` | LavenderFive | public | — | Community maintained |
+
+
+ | Endpoint | Provider | Type | Rate limit | Notes |
+ | --- | --- | --- | --- | --- |
+ | `https://evm-rpc-testnet.sei-apis.com` | Sei Foundation | public | 20 req/s | Recommended for testing |
+ | `https://evm-rpc-testnet-sei.stingray.plus` | Staketab | public | — | Community maintained |
+ | `https://seievm-testnet-rpc.polkachu.com` | Polkachu | public | — | Community maintained |
+ | `https://sei-testnet.drpc.org` | dRPC | public | — | Community maintained |
+
+
+
+For the complete list of JSON-RPC methods, see the [EVM reference](/evm/reference).
diff --git a/evm/transactions.mdx b/evm/transactions.mdx
index c83ceb6..b2584a9 100644
--- a/evm/transactions.mdx
+++ b/evm/transactions.mdx
@@ -155,42 +155,42 @@ EVM transactions in Sei follow the Ethereum transaction format with standard pro
### JavaScript example with web3.js
+
+ Public RPC endpoints such as `https://evm-rpc.sei-apis.com` do not manage or unlock accounts, so `eth_getAccounts` and `eth_sendTransaction` are not available. Sign transactions locally with a private key and broadcast the raw transaction instead.
+
+
```javascript
- // Example using web3.js to send a transaction
- const Web3 = require('web3');
+ // Example using web3.js v4 to sign and broadcast a transaction.
+ // Public RPC endpoints do not manage accounts, so sign locally with a private key.
+ const { Web3 } = require('web3');
const web3 = new Web3('https://evm-rpc.sei-apis.com');
- async function sendTransaction() {
- const accounts = await web3.eth.getAccounts();
- const sender = accounts[0];
+ // Load your account from a private key. Never hard-code keys — read from an env var.
+ const account = web3.eth.accounts.privateKeyToAccount(process.env.PRIVATE_KEY);
- // Get the current nonce for the sender
- const nonce = await web3.eth.getTransactionCount(sender);
+ async function sendTransaction() {
+ // Current nonce for the sender
+ const nonce = await web3.eth.getTransactionCount(account.address);
- // Get the current block to estimate gas fees
+ // Use the latest base fee to set EIP-1559 fees
const block = await web3.eth.getBlock('latest');
- const baseFeePerGas = block.baseFeePerGas;
-
- // Set priority fee (tip)
const maxPriorityFeePerGas = web3.utils.toWei('1', 'gwei');
-
- // Calculate max fee per gas
- const maxFeePerGas = web3.utils
- .toBN(baseFeePerGas)
- .add(web3.utils.toBN(maxPriorityFeePerGas));
+ const maxFeePerGas = (BigInt(block.baseFeePerGas) + BigInt(maxPriorityFeePerGas)).toString();
const tx = {
- from: sender,
+ from: account.address,
to: '0x07a565b7ed7d7a678680a4c162885bedbb695fe0',
value: web3.utils.toWei('0.1', 'ether'),
gas: 21000, // Gas limit for a simple transfer
- maxFeePerGas: maxFeePerGas.toString(),
- maxPriorityFeePerGas: maxPriorityFeePerGas,
- nonce: nonce,
- data: '0x' // Empty data for a simple transfer
+ maxFeePerGas,
+ maxPriorityFeePerGas,
+ nonce,
+ chainId: 1329 // pacific-1 mainnet (use 1328 for atlantic-2 testnet)
};
- const receipt = await web3.eth.sendTransaction(tx);
+ // Sign locally, then broadcast the raw transaction
+ const signed = await web3.eth.accounts.signTransaction(tx, process.env.PRIVATE_KEY);
+ const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
console.log('Transaction receipt:', receipt);
}
diff --git a/learn/dev-chains.mdx b/learn/dev-chains.mdx
index b2163cd..4798e60 100644
--- a/learn/dev-chains.mdx
+++ b/learn/dev-chains.mdx
@@ -20,6 +20,9 @@ applications and activities.
- **Purpose**: Production
- **Chain ID**: `pacific-1`
- **EVM Chain ID**: `1329` or `0x531`
+- **EVM RPC**: `https://evm-rpc.sei-apis.com`
+- **WebSocket**: `wss://evm-ws.sei-apis.com`
+- **Explorer**: `https://seiscan.io`