{"id":87159,"plugin_id":"plugin_asdk_app_6abfbd9a20c481919866ead0f4722d34","kind":"skill","collection_source":"plugin_package","comparison_source":null,"observed_at":"2026-11-09T12:07:50.460Z","digest":"bf61c552522119a3acfdfd73839d34e81a5bb2c8c3ab58b72bacc0185fed1dcc","against":null,"payload":{"description":"Use when reading EVM blockchain data through Dwellir endpoints: Ethereum JSON-RPC methods, connection setup (ethers.js, viem, web3.js, web3.py), debug/trace APIs, WebSocket subscriptions, and batch requests. Use when working with EVM chains, Ethereum, eth_ methods, Solidity contracts, gas estimation, transaction tracing, or EVM L2 rollups through Dwellir. Triggers on mentions of EVM, ethereum, eth_, solidity, ethers, viem, web3, debug_trace, callTracer, gas, ERC-20, smart contract, or EVM chain names (Arbitrum, Base, Polygon, Optimism, etc.).\n","included_files":[],"name":"evm","skill_md_contents":"---\nname: evm\ndescription: >\n  Use when reading EVM blockchain data through Dwellir endpoints: Ethereum JSON-RPC methods,\n  connection setup (ethers.js, viem, web3.js, web3.py), debug/trace APIs,\n  WebSocket subscriptions, and batch requests.\n  Use when working with EVM chains, Ethereum, eth_ methods, Solidity contracts,\n  gas estimation, transaction tracing, or EVM L2 rollups through Dwellir.\n  Triggers on mentions of EVM, ethereum, eth_, solidity, ethers, viem, web3,\n  debug_trace, callTracer, gas, ERC-20, smart contract, or EVM chain names\n  (Arbitrum, Base, Polygon, Optimism, etc.).\n---\n\n# EVM RPC Endpoints Reference\n\nUse Dwellir for blockchain reads, transaction analysis, and read-only application development.\nThis skill does not sign or broadcast transactions, transfer assets, or execute trades.\nAn existing wallet or a rejected MCP method does not authorize an alternate execution route.\n\nDiscover endpoints with `list_endpoints` and choose a key reference with `list_keys`.\nCall a separately exposed read tool, such as `eth_chainId`, `eth_blockNumber`, or `eth_getBalance`.\nUse its input schema for named arguments, including `endpoint_id` and `key_ref`.\nThe direct RPC examples below describe application code; MCP supports a smaller method set.\nRead credentials from environment variables or a secret store. Never print authenticated URLs or raw connection errors.\n\n## Overview\n\n- **Protocol:** JSON-RPC 2.0 over HTTPS and WSS\n- **Authentication:** API key in URL path\n- **Endpoint format:** `https://api-{network}.n.dwellir.com/{API_KEY}`\n- **WebSocket format:** `wss://api-{network}.n.dwellir.com/{API_KEY}`\n\n## Connection Setup\n\nAll examples use the `DWELLIR_RPC_URL` environment variable. Set it to your full endpoint URL including API key.\n\n### ethers.js (v6)\n\n```typescript\nimport { JsonRpcProvider, WebSocketProvider } from 'ethers';\n\n// HTTP\nconst provider = new JsonRpcProvider(process.env.DWELLIR_RPC_URL);\n\n// WebSocket\nconst wsProvider = new WebSocketProvider(process.env.DWELLIR_WSS_URL);\n```\n\n### viem\n\n```typescript\nimport { createPublicClient, http, webSocket } from 'viem';\nimport { mainnet } from 'viem/chains';\n\n// HTTP\nconst client = createPublicClient({\n  chain: mainnet,\n  transport: http(process.env.DWELLIR_RPC_URL),\n});\n\n// WebSocket\nconst wsClient = createPublicClient({\n  chain: mainnet,\n  transport: webSocket(process.env.DWELLIR_WSS_URL),\n});\n```\n\n### web3.js\n\n```javascript\nimport Web3 from 'web3';\nconst web3 = new Web3(process.env.DWELLIR_RPC_URL);\n```\n\n### web3.py\n\n```python\nfrom web3 import Web3\nimport os\n\nw3 = Web3(Web3.HTTPProvider(os.environ[\"DWELLIR_RPC_URL\"]))\nprint(w3.is_connected())\n```\n\n### Python HTTP request\n\n```python\nimport json\nimport os\nfrom urllib.request import Request, urlopen\n\npayload = {\"jsonrpc\": \"2.0\", \"method\": \"eth_blockNumber\", \"params\": [], \"id\": 1}\ntry:\n    request = Request(os.environ[\"DWELLIR_RPC_URL\"], data=json.dumps(payload).encode(),\n                      headers={\"Content-Type\": \"application/json\"})\n    with urlopen(request, timeout=10) as response:\n        decoded = json.load(response)\nexcept Exception:\n    raise SystemExit(\"Dwellir request failed. Check endpoint access and retry.\") from None\nresponses = decoded if isinstance(decoded, list) else [decoded]\nfor item in responses:\n    if \"error\" in item:\n        raise SystemExit(f\"Dwellir RPC request {item.get('id')} failed.\")\n    print(item.get(\"id\"), item.get(\"result\"))\n```\n\nHandle failures with a redacted error message. Raw exceptions can include the authenticated URL.\nThe JSON examples below are request bodies for this HTTP pattern.\n\n## EVM RPC Methods\n\n### Account Methods\n\n| Method | Description | Params |\n|--------|-------------|--------|\n| `eth_getBalance` | Get account balance in wei | `[address, block]` |\n| `eth_getTransactionCount` | Get account nonce | `[address, block]` |\n| `eth_getCode` | Get contract bytecode | `[address, block]` |\n| `eth_getStorageAt` | Get storage value at position | `[address, position, block]` |\n\n### Block Methods\n\n| Method | Description | Params |\n|--------|-------------|--------|\n| `eth_blockNumber` | Latest block number | `[]` |\n| `eth_getBlockByNumber` | Get block by number | `[blockNumber, fullTx]` |\n| `eth_getBlockByHash` | Get block by hash | `[blockHash, fullTx]` |\n| `eth_getBlockReceipts` | Get all receipts for a block | `[blockNumber]` |\n\n### Transaction Methods\n\n| Method | Description | Params |\n|--------|-------------|--------|\n| `eth_getTransactionByHash` | Get transaction by hash | `[txHash]` |\n| `eth_getTransactionReceipt` | Get transaction receipt | `[txHash]` |\n| `eth_getTransactionByBlockNumberAndIndex` | Get tx by block and index | `[blockNumber, index]` |\n\n### Call & Simulation Methods\n\n| Method | Description | Params |\n|--------|-------------|--------|\n| `eth_call` | Execute read-only call | `[txObject, block]` |\n| `eth_estimateGas` | Estimate gas for transaction | `[txObject, block]` |\n| `eth_createAccessList` | Generate access list for tx | `[txObject, block]` |\n\n### Log & Filter Methods\n\n| Method | Description | Params |\n|--------|-------------|--------|\n| `eth_getLogs` | Get matching log entries | `[filterObject]` |\n| `eth_newFilter` | Create log filter | `[filterObject]` |\n| `eth_newBlockFilter` | Create block filter | `[]` |\n| `eth_getFilterChanges` | Poll filter for changes | `[filterId]` |\n| `eth_getFilterLogs` | Get all logs for filter | `[filterId]` |\n| `eth_uninstallFilter` | Remove filter | `[filterId]` |\n\n### Gas & Fee Methods\n\n| Method | Description | Params |\n|--------|-------------|--------|\n| `eth_gasPrice` | Current gas price | `[]` |\n| `eth_maxPriorityFeePerGas` | Suggested priority fee (EIP-1559) | `[]` |\n| `eth_feeHistory` | Historical fee data | `[blockCount, newestBlock, rewardPercentiles]` |\n\n### Network Methods\n\n| Method | Description | Params |\n|--------|-------------|--------|\n| `eth_chainId` | Chain ID | `[]` |\n| `net_version` | Network ID | `[]` |\n| `eth_syncing` | Sync status | `[]` |\n| `web3_clientVersion` | Client version string | `[]` |\n\n### Subscription Methods (WebSocket)\n\n| Method | Description | Params |\n|--------|-------------|--------|\n| `eth_subscribe` | Start subscription | `[type, options]` |\n| `eth_unsubscribe` | Stop subscription | `[subscriptionId]` |\n\nSubscription types: `newHeads`, `logs`, `newPendingTransactions`, `syncing`.\n\n## Debug & Trace Methods\n\nAvailability depends on the endpoint and account entitlements. Check current documentation.\n\n### debug_traceTransaction\n\nTrace a single transaction by hash. Returns detailed execution trace.\n\n```json\n{\n    \"jsonrpc\": \"2.0\",\n    \"method\": \"debug_traceTransaction\",\n    \"params\": [\n      \"0x...\",\n      {\"tracer\": \"callTracer\"}\n    ],\n    \"id\": 1\n  }\n```\n\n### debug_traceCall\n\nTrace a call without submitting a transaction.\n\n```json\n{\n    \"jsonrpc\": \"2.0\",\n    \"method\": \"debug_traceCall\",\n    \"params\": [\n      {\n        \"from\": \"0x...\",\n        \"to\": \"0x...\",\n        \"data\": \"0x...\"\n      },\n      \"latest\",\n      {\"tracer\": \"callTracer\"}\n    ],\n    \"id\": 1\n  }\n```\n\n### debug_traceBlockByNumber\n\nTrace all transactions in a block.\n\n```json\n{\n    \"jsonrpc\": \"2.0\",\n    \"method\": \"debug_traceBlockByNumber\",\n    \"params\": [\"0x...\", {\"tracer\": \"callTracer\"}],\n    \"id\": 1\n  }\n```\n\n### trace_transaction (Parity-style)\n\n```json\n{\n    \"jsonrpc\": \"2.0\",\n    \"method\": \"trace_transaction\",\n    \"params\": [\"0x...\"],\n    \"id\": 1\n  }\n```\n\n### trace_block (Parity-style)\n\n```json\n{\n    \"jsonrpc\": \"2.0\",\n    \"method\": \"trace_block\",\n    \"params\": [\"0x...\"],\n    \"id\": 1\n  }\n```\n\n### Tracer Types\n\n#### callTracer\n\nReturns a tree of calls made during execution.\n\n```json\n{\n  \"tracer\": \"callTracer\",\n  \"tracerConfig\": {\n    \"onlyTopCall\": false\n  }\n}\n```\n\nResponse includes: `type`, `from`, `to`, `value`, `gas`, `gasUsed`, `input`, `output`, `error`, `calls` (nested).\n\n#### prestateTracer\n\nShows account state before execution.\n\n```json\n{\n  \"tracer\": \"prestateTracer\",\n  \"tracerConfig\": {\n    \"diffMode\": true\n  }\n}\n```\n\nWith `diffMode: true`, returns `pre` and `post` state for each account showing balance, code, storage, and nonce changes.\n\n#### 4byteTracer\n\nMaps 4-byte function selectors to call counts.\n\n```json\n{\n  \"tracer\": \"4byteTracer\"\n}\n```\n\nResponse: `{\"0xa9059cbb-64\": 1, \"0x095ea7b3-64\": 2}` — each key is `selector-calldataSize`, value is count.\n\n#### Custom JavaScript Tracer\n\nDefine custom analysis logic:\n\n```json\n{\n  \"tracer\": \"{result: [], fault: function(log) {}, step: function(log) { if(log.op.toString() === 'SSTORE') this.result.push(log.stack.peek(0)); }, result: function() { return this.result; }}\"\n}\n```\n\n## Code Examples\n\n### Get Account Balance\n\n```typescript\nimport { JsonRpcProvider, formatEther } from 'ethers';\n\nconst provider = new JsonRpcProvider(process.env.DWELLIR_RPC_URL);\nconst balance = await provider.getBalance('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045');\nconsole.log(`Balance: ${formatEther(balance)} ETH`);\n```\n\n### Get Logs (ERC-20 Transfers)\n\n```typescript\nimport { JsonRpcProvider } from 'ethers';\n\nconst provider = new JsonRpcProvider(process.env.DWELLIR_RPC_URL);\nconst logs = await provider.getLogs({\n  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC\n  topics: [\n    '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' // Transfer\n  ],\n  fromBlock: 'latest',\n});\nconsole.log(`Found ${logs.length} transfers`);\n```\n\n### Call Contract (Read-Only)\n\n```typescript\nimport { createPublicClient, http, parseAbi } from 'viem';\nimport { mainnet } from 'viem/chains';\n\nconst client = createPublicClient({\n  chain: mainnet,\n  transport: http(process.env.DWELLIR_RPC_URL),\n});\n\nconst totalSupply = await client.readContract({\n  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n  abi: parseAbi(['function totalSupply() view returns (uint256)']),\n  functionName: 'totalSupply',\n});\n```\n\n### Trace a Transaction\n\n```typescript\nconst result = await provider.send('debug_traceTransaction', [\n  '0x...txhash...',\n  { tracer: 'callTracer' }\n]);\nconsole.log('Top-level call:', result.type, result.from, '->', result.to);\nconsole.log('Internal calls:', result.calls?.length ?? 0);\n```\n\n### WebSocket — Subscribe to New Blocks\n\n```typescript\nimport { WebSocketProvider } from 'ethers';\n\nconst provider = new WebSocketProvider(process.env.DWELLIR_WSS_URL);\n\nprovider.on('block', async (blockNumber) => {\n  const block = await provider.getBlock(blockNumber);\n  console.log(`Block ${blockNumber}: ${block.transactions.length} txs`);\n});\n```\n\n### WebSocket — Subscribe to Contract Events\n\n```typescript\nimport { WebSocketProvider, Contract } from 'ethers';\n\nconst provider = new WebSocketProvider(process.env.DWELLIR_WSS_URL);\nconst usdc = new Contract(\n  '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n  ['event Transfer(address indexed from, address indexed to, uint256 value)'],\n  provider\n);\n\nusdc.on('Transfer', (from, to, value) => {\n  console.log(`USDC Transfer: ${from} -> ${to}: ${value}`);\n});\n```\n\n## Batch Requests\n\nSend multiple JSON-RPC calls in a single HTTP request:\n\n```json\n[\n    {\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[],\"id\":1},\n    {\"jsonrpc\":\"2.0\",\"method\":\"eth_gasPrice\",\"params\":[],\"id\":2},\n    {\"jsonrpc\":\"2.0\",\"method\":\"eth_chainId\",\"params\":[],\"id\":3}\n  ]\n```\n\n```typescript\n// ethers.js batch via FetchRequest\nconst [blockNumber, gasPrice, chainId] = await Promise.all([\n  provider.getBlockNumber(),\n  provider.getFeeData(),\n  provider.getNetwork(),\n]);\n```\n\n## WebSocket Subscription Patterns\n\n### newHeads — New Block Headers\n\n```json\n{\"jsonrpc\":\"2.0\",\"method\":\"eth_subscribe\",\"params\":[\"newHeads\"],\"id\":1}\n```\n\n### logs — Contract Events\n\n```json\n{\n  \"jsonrpc\":\"2.0\",\n  \"method\":\"eth_subscribe\",\n  \"params\":[\n    \"logs\",\n    {\n      \"address\": \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n      \"topics\": [\"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\"]\n    }\n  ],\n  \"id\":1\n}\n```\n\n### newPendingTransactions\n\n```json\n{\"jsonrpc\":\"2.0\",\"method\":\"eth_subscribe\",\"params\":[\"newPendingTransactions\"],\"id\":1}\n```\n\n### Unsubscribe\n\n```json\n{\"jsonrpc\":\"2.0\",\"method\":\"eth_unsubscribe\",\"params\":[\"0x...subscriptionId\"],\"id\":1}\n```\n\n## Best Practices\n\n1. **Retry with exponential backoff** — handle 429 (rate limited) and 5xx responses:\n   ```typescript\n   async function rpcWithRetry(fn, maxRetries = 3) {\n     for (let i = 0; i < maxRetries; i++) {\n       try {\n         return await fn();\n       } catch (err) {\n         if (i === maxRetries - 1) throw err;\n         await new Promise(r => setTimeout(r, 1000 * 2 ** i));\n       }\n     }\n   }\n   ```\n\n2. **Cache block data** — blocks are immutable once finalized; cache `getBlock` results.\n\n3. **Use `latest` carefully** — `latest` changes every block. For consistency within a workflow, fetch the block number once and reference it explicitly.\n\n4. **Prefer `eth_getBlockReceipts`** — more efficient than individual `eth_getTransactionReceipt` calls for full-block analysis.\n\n5. **Limit `eth_getLogs` range** — use narrow block ranges (≤2000 blocks). Overly broad queries may time out.\n\n6. **Connection pooling** — reuse HTTP connections and WebSocket clients rather than opening new ones per request.\n\n7. **Archive vs full nodes** — trace/debug methods and historical state queries require archive data, when the endpoint and account support it.\n\n## Troubleshooting\n\n| Error | Cause | Fix |\n|-------|-------|-----|\n| `429 Too Many Requests` | Rate limit exceeded | Add bounded backoff/retry and reduce request volume |\n| `401 Unauthorized` | Invalid API key | Check key is correct UUID in URL path |\n| `method not found` | Method unavailable on this chain | Verify chain supports this RPC method |\n| `missing trie node` | Historical state unavailable | Ensure trace/debug APIs are enabled on your plan |\n| `execution timeout` | Trace/call too complex | Narrow the scope or use `onlyTopCall: true` |\n| `block range too large` | `eth_getLogs` range too wide | Reduce block range to ≤2000 blocks |\n| Connection reset | WebSocket idle timeout | Implement reconnection logic with backoff |\n\n## Documentation Links\n\n- Dwellir docs: [dwellir.com/docs](https://www.dwellir.com/docs)\n- Tracing guide: [dwellir.com/docs/getting-started/tracing](https://www.dwellir.com/docs/getting-started/tracing)\n- Per-chain docs: `https://www.dwellir.com/docs/{chain}` — e.g., [ethereum](https://www.dwellir.com/docs/ethereum), [arbitrum](https://www.dwellir.com/docs/arbitrum), [base](https://www.dwellir.com/docs/base), [polygon](https://www.dwellir.com/docs/polygon)\n- Ethereum JSON-RPC spec: [ethereum.org/en/developers/docs/apis/json-rpc](https://ethereum.org/en/developers/docs/apis/json-rpc)\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}