Files
explorer-monorepo/docs/specs/api/etherscan-compatible-api.md

323 lines
6.8 KiB
Markdown

# Etherscan-Compatible API Specification
## Overview
This document specifies the Etherscan-compatible API layer that provides an API surface matching Blockscout/Etherscan APIs for tool compatibility and easier migration.
**Base URL**: `https://api.explorer.d-bis.org/api`
**Note**: This is a compatibility layer that translates Etherscan API calls to our internal API.
## API Surface Mapping
### Account Endpoints
#### Get Account Balance
**Etherscan**: `GET /api?module=account&action=balance&address={address}&tag=latest`
**Our Implementation**:
- Maps to: `GET /v1/addresses/{chain_id}/{address}` (extract balance)
**Response Format** (matches Etherscan):
```json
{
"status": "1",
"message": "OK",
"result": "1000000000000000000"
}
```
#### Get Token Balance
**Etherscan**: `GET /api?module=account&action=tokenbalance&contractaddress={token}&address={address}&tag=latest`
**Our Implementation**:
- Maps to: `GET /v1/addresses/{chain_id}/{address}/tokens` (filter by token address)
**Response Format**:
```json
{
"status": "1",
"message": "OK",
"result": "1000000000000000000"
}
```
#### Get Transaction List
**Etherscan**: `GET /api?module=account&action=txlist&address={address}&startblock=0&endblock=99999999&page=1&offset=10&sort=desc`
**Our Implementation**:
- Maps to: `GET /v1/addresses/{chain_id}/{address}/transactions` (with pagination)
**Response Format**:
```json
{
"status": "1",
"message": "OK",
"result": [
{
"blockNumber": "12345",
"timeStamp": "1640995200",
"hash": "0x...",
"from": "0x...",
"to": "0x...",
"value": "1000000000000000000",
"gas": "21000",
"gasPrice": "20000000000",
"gasUsed": "21000",
"isError": "0",
"txreceipt_status": "1"
}
]
}
```
### Transaction Endpoints
#### Get Transaction Status
**Etherscan**: `GET /api?module=transaction&action=getstatus&txhash={hash}`
**Our Implementation**:
- Maps to: `GET /v1/transactions/{chain_id}/{hash}` (extract status)
**Response Format**:
```json
{
"status": "1",
"message": "OK",
"result": {
"isError": "0",
"errDescription": ""
}
}
```
#### Get Transaction Receipt Status
**Etherscan**: `GET /api?module=transaction&action=gettxreceiptstatus&txhash={hash}`
**Response Format**:
```json
{
"status": "1",
"message": "OK",
"result": {
"status": "1"
}
}
```
### Block Endpoints
#### Get Block by Number
**Etherscan**: `GET /api?module=proxy&action=eth_getBlockByNumber&tag={number}&boolean=true`
**Our Implementation**:
- Maps to: `GET /v1/blocks/{chain_id}/{number}` (transform format)
**Response Format** (Ethereum JSON-RPC format):
```json
{
"jsonrpc": "2.0",
"result": {
"number": "0x3039",
"hash": "0x...",
"transactions": [...]
}
}
```
### Contract Endpoints
#### Get Contract ABI
**Etherscan**: `GET /api?module=contract&action=getabi&address={address}`
**Our Implementation**:
- Maps to: `GET /v1/contracts/{chain_id}/{address}/abi`
**Response Format**:
```json
{
"status": "1",
"message": "OK",
"result": "[{...}]"
}
```
#### Verify Contract
**Etherscan**: `POST /api?module=contract&action=verifysourcecode`
**Our Implementation**:
- Maps to: `POST /v1/contracts/{chain_id}/{address}/verify`
**Parameter Mapping**:
- `sourceCode``source_code`
- `codeformat``verification_method`
- `contractaddress``address`
- `compilerversion``compiler_version`
### Token Endpoints
#### Get Token Total Supply
**Etherscan**: `GET /api?module=stats&action=tokensupply&contractaddress={address}`
**Our Implementation**:
- Maps to: `GET /v1/tokens/{chain_id}/{address}` (extract total_supply)
### Event Logs
#### Get Event Logs
**Etherscan**: `GET /api?module=logs&action=getLogs&address={address}&topic0={topic0}&fromBlock={fromBlock}&toBlock={toBlock}`
**Our Implementation**:
- Maps to: `GET /v1/logs` (with filters)
**Response Format**:
```json
{
"status": "1",
"message": "OK",
"result": [
{
"address": "0x...",
"topics": ["0x..."],
"data": "0x...",
"blockNumber": "0x3039",
"transactionHash": "0x...",
"logIndex": "0x0"
}
]
}
```
## Parameter Translation
### Common Parameters
| Etherscan | Our API | Notes |
|-----------|---------|-------|
| `module` | N/A | Determines endpoint category |
| `action` | N/A | Determines specific action |
| `address` | `address` | Same |
| `tag` | `block_number` | Convert "latest" to current block |
| `startblock` | `from_block` | Same |
| `endblock` | `to_block` | Same |
| `page` | `page` | Same |
| `offset` | `page_size` | Same |
| `sort` | `order` | Same (asc/desc) |
### Chain ID Handling
**Etherscan**: No chain_id parameter (single chain)
**Our API**: Require `chain_id` parameter or use default from context
**Mapping**: Add `chain_id` parameter to all requests
## Response Format Compatibility
### Status Codes
**Etherscan Format**:
- `status: "1"` = Success
- `status: "0"` = Error
**Our Format**:
- HTTP 200 = Success (map to status "1")
- HTTP 4xx/5xx = Error (map to status "0")
### Error Messages
**Etherscan Format**:
```json
{
"status": "0",
"message": "NOTOK",
"result": "Error message here"
}
```
**Our Mapping**:
- Map our error codes to Etherscan error messages
- Preserve error details in result field
## Migration Guide
### For Tools Using Etherscan API
**Step 1**: Update base URL
- Old: `https://api.etherscan.io/api`
- New: `https://api.explorer.d-bis.org/api`
**Step 2**: Add chain_id parameter (if needed)
- Add `&chainid=138` to requests
- Or use default chain from connection
**Step 3**: Test compatibility
- Verify response formats match
- Check error handling
- Validate data accuracy
### For New Integrations
**Recommendation**: Use native REST API instead of Etherscan-compatible API
- More features
- Better performance
- Clearer API design
## Limitations
### Not All Endpoints Supported
**Supported**:
- Account operations
- Transaction queries
- Block queries
- Contract verification
- Token operations
- Event logs
**Not Supported** (Etherscan-specific):
- Gas tracker (use our analytics API)
- Historical stats (use our analytics API)
- Token list (use our token API)
### Response Format Differences
**Some differences may exist**:
- Field naming (camelCase vs snake_case)
- Data precision
- Additional fields in our responses
## Implementation
### Translation Layer
**Architecture**:
- Request interceptor: Parse Etherscan-style requests
- Parameter mapper: Convert to our API format
- Response transformer: Convert our responses to Etherscan format
**Code Structure**:
```
compatibility/
├── etherscan/
│ ├── request_parser.py # Parse Etherscan requests
│ ├── parameter_mapper.py # Map parameters
│ └── response_transformer.py # Transform responses
```
## References
- REST API: See `rest-api.md`
- API Gateway: See `api-gateway.md`