# 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`

