- Updated branding from "SolaceScanScout" to "Solace" across various files including deployment scripts, API responses, and documentation. - Changed default base URL for Playwright tests and updated security headers to reflect the new branding. - Enhanced README and API documentation to include new authentication endpoints and product access details. This refactor aligns the project branding and improves clarity in the API documentation.
781 lines
14 KiB
Markdown
781 lines
14 KiB
Markdown
# Track API Contracts
|
|
|
|
Complete API contract definitions for all 4 tracks of SolaceScan Explorer.
|
|
|
|
## Track 1: Public Meta Explorer (No Auth Required)
|
|
|
|
### Base URL
|
|
```
|
|
/api/v1/track1
|
|
```
|
|
|
|
### Rate Limits
|
|
- **Anonymous**: 10 req/s, 100 req/min per IP
|
|
- **Caching**: 10-30s TTL via Redis
|
|
|
|
### Endpoints
|
|
|
|
#### GET /api/v1/track1/blocks/latest
|
|
Get latest blocks.
|
|
|
|
**Query Parameters:**
|
|
- `limit` (optional, default: 10, max: 50): Number of blocks to return
|
|
- `page` (optional, default: 1): Page number
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"number": 12345,
|
|
"hash": "0x...",
|
|
"timestamp": "2024-01-20T10:30:00Z",
|
|
"transaction_count": 42,
|
|
"gas_used": "15000000",
|
|
"gas_limit": "30000000"
|
|
}
|
|
],
|
|
"pagination": {
|
|
"page": 1,
|
|
"limit": 10,
|
|
"total": 1000
|
|
}
|
|
}
|
|
```
|
|
|
|
**Error Responses:**
|
|
- `429 Too Many Requests`: Rate limit exceeded
|
|
- `500 Internal Server Error`: RPC error
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track1/txs/latest
|
|
Get latest transactions.
|
|
|
|
**Query Parameters:**
|
|
- `limit` (optional, default: 10, max: 50): Number of transactions to return
|
|
- `page` (optional, default: 1): Page number
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"hash": "0x...",
|
|
"from": "0x...",
|
|
"to": "0x...",
|
|
"value": "1000000000000000000",
|
|
"block_number": 12345,
|
|
"timestamp": "2024-01-20T10:30:00Z"
|
|
}
|
|
],
|
|
"pagination": {
|
|
"page": 1,
|
|
"limit": 10,
|
|
"total": 5000
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track1/block/:number
|
|
Get block by number.
|
|
|
|
**Path Parameters:**
|
|
- `number` (required): Block number (integer)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"number": 12345,
|
|
"hash": "0x...",
|
|
"parent_hash": "0x...",
|
|
"timestamp": "2024-01-20T10:30:00Z",
|
|
"transaction_count": 42,
|
|
"gas_used": "15000000",
|
|
"gas_limit": "30000000",
|
|
"base_fee_per_gas": "20000000000",
|
|
"miner": "0x...",
|
|
"difficulty": "0"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Error Responses:**
|
|
- `404 Not Found`: Block not found
|
|
- `400 Bad Request`: Invalid block number
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track1/tx/:hash
|
|
Get transaction by hash.
|
|
|
|
**Path Parameters:**
|
|
- `hash` (required): Transaction hash (0x...)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"hash": "0x...",
|
|
"from": "0x...",
|
|
"to": "0x...",
|
|
"value": "1000000000000000000",
|
|
"gas": "21000",
|
|
"gas_price": "20000000000",
|
|
"block_number": 12345,
|
|
"block_hash": "0x...",
|
|
"transaction_index": 0,
|
|
"status": "success",
|
|
"timestamp": "2024-01-20T10:30:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Error Responses:**
|
|
- `404 Not Found`: Transaction not found
|
|
- `400 Bad Request`: Invalid hash format
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track1/address/:addr/balance
|
|
Get address ETH balance.
|
|
|
|
**Path Parameters:**
|
|
- `addr` (required): Ethereum address (0x...)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"address": "0x...",
|
|
"balance": "1000000000000000000",
|
|
"balance_wei": "1000000000000000000",
|
|
"balance_ether": "1.0"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Error Responses:**
|
|
- `400 Bad Request`: Invalid address format
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track1/bridge/status
|
|
Get bridge monitoring status.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"status": "operational",
|
|
"chains": {
|
|
"138": {
|
|
"name": "Defi Oracle Meta Mainnet",
|
|
"status": "operational",
|
|
"last_sync": "2024-01-20T10:30:00Z"
|
|
},
|
|
"1": {
|
|
"name": "Ethereum Mainnet",
|
|
"status": "operational",
|
|
"last_sync": "2024-01-20T10:29:00Z"
|
|
}
|
|
},
|
|
"total_transfers_24h": 150,
|
|
"total_volume_24h": "5000000000000000000000"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Track 2: Full Indexed Explorer (Track 2 Required)
|
|
|
|
### Base URL
|
|
```
|
|
/api/v1/track2
|
|
```
|
|
|
|
### Authentication
|
|
- **Required**: JWT token with `track: 2` claim
|
|
- **Header**: `Authorization: Bearer <token>`
|
|
|
|
### Rate Limits
|
|
- **Track 2**: 100 req/s, 1000 req/min per user
|
|
|
|
### Endpoints
|
|
|
|
#### GET /api/v1/track2/address/:addr/txs
|
|
Get address transaction history (paginated).
|
|
|
|
**Path Parameters:**
|
|
- `addr` (required): Ethereum address (0x...)
|
|
|
|
**Query Parameters:**
|
|
- `page` (optional, default: 1): Page number
|
|
- `limit` (optional, default: 20, max: 100): Items per page
|
|
- `type` (optional): Filter by type (`sent`, `received`, `all`)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"hash": "0x...",
|
|
"from": "0x...",
|
|
"to": "0x...",
|
|
"value": "1000000000000000000",
|
|
"block_number": 12345,
|
|
"timestamp": "2024-01-20T10:30:00Z",
|
|
"status": "success",
|
|
"direction": "sent"
|
|
}
|
|
],
|
|
"pagination": {
|
|
"page": 1,
|
|
"limit": 20,
|
|
"total": 500,
|
|
"total_pages": 25
|
|
}
|
|
}
|
|
```
|
|
|
|
**Error Responses:**
|
|
- `401 Unauthorized`: Missing or invalid token
|
|
- `403 Forbidden`: Insufficient track level
|
|
- `400 Bad Request`: Invalid address format
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track2/address/:addr/tokens
|
|
Get address token balances (ERC-20).
|
|
|
|
**Path Parameters:**
|
|
- `addr` (required): Ethereum address (0x...)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"address": "0x...",
|
|
"tokens": [
|
|
{
|
|
"contract": "0x...",
|
|
"symbol": "USDC",
|
|
"name": "USD Coin",
|
|
"decimals": 6,
|
|
"balance": "1000000",
|
|
"balance_formatted": "1.0",
|
|
"price_usd": "1.00",
|
|
"value_usd": "1.00"
|
|
}
|
|
],
|
|
"total_tokens": 5,
|
|
"total_value_usd": "1500.00"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track2/token/:contract
|
|
Get token information and stats.
|
|
|
|
**Path Parameters:**
|
|
- `contract` (required): Token contract address (0x...)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"contract": "0x...",
|
|
"symbol": "USDC",
|
|
"name": "USD Coin",
|
|
"decimals": 6,
|
|
"total_supply": "1000000000000000",
|
|
"holders": 5000,
|
|
"transfers_24h": 1500,
|
|
"volume_24h": "5000000000000"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track2/search?q=
|
|
Unified search endpoint.
|
|
|
|
**Query Parameters:**
|
|
- `q` (required): Search query (address, tx hash, or block number)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"type": "address",
|
|
"result": {
|
|
"address": "0x...",
|
|
"balance": "1000000000000000000",
|
|
"tx_count": 500
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Search Types:**
|
|
- `address`: Returns address data
|
|
- `transaction`: Returns transaction data
|
|
- `block`: Returns block data
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track2/address/:addr/internal-txs
|
|
Get internal transactions for an address.
|
|
|
|
**Path Parameters:**
|
|
- `addr` (required): Ethereum address (0x...)
|
|
|
|
**Query Parameters:**
|
|
- `page` (optional, default: 1): Page number
|
|
- `limit` (optional, default: 20, max: 100): Items per page
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"transaction_hash": "0x...",
|
|
"from": "0x...",
|
|
"to": "0x...",
|
|
"value": "1000000000000000000",
|
|
"block_number": 12345,
|
|
"timestamp": "2024-01-20T10:30:00Z"
|
|
}
|
|
],
|
|
"pagination": {
|
|
"page": 1,
|
|
"limit": 20,
|
|
"total": 100
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Track 3: Analytics & Forensics (Track 3 Required)
|
|
|
|
### Base URL
|
|
```
|
|
/api/v1/track3
|
|
```
|
|
|
|
### Authentication
|
|
- **Required**: JWT token with `track: 3` claim
|
|
- **Header**: `Authorization: Bearer <token>`
|
|
|
|
### Rate Limits
|
|
- **Track 3**: 50 req/s, 500 req/min per user (lower due to complexity)
|
|
|
|
### Endpoints
|
|
|
|
#### GET /api/v1/track3/analytics/flows
|
|
Get flow tracking data (address → address).
|
|
|
|
**Query Parameters:**
|
|
- `from` (optional): Source address
|
|
- `to` (optional): Destination address
|
|
- `token` (optional): Token contract address
|
|
- `start_date` (optional): Start date (ISO 8601)
|
|
- `end_date` (optional): End date (ISO 8601)
|
|
- `limit` (optional, default: 50, max: 200): Number of flows
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"flows": [
|
|
{
|
|
"from": "0x...",
|
|
"to": "0x...",
|
|
"token": "0x...",
|
|
"amount": "1000000000000000000",
|
|
"count": 5,
|
|
"first_seen": "2024-01-20T10:00:00Z",
|
|
"last_seen": "2024-01-20T10:30:00Z"
|
|
}
|
|
],
|
|
"total_flows": 100,
|
|
"total_volume": "5000000000000000000000"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track3/analytics/bridge
|
|
Get bridge analytics and flow history.
|
|
|
|
**Query Parameters:**
|
|
- `chain_from` (optional): Source chain ID
|
|
- `chain_to` (optional): Destination chain ID
|
|
- `start_date` (optional): Start date (ISO 8601)
|
|
- `end_date` (optional): End date (ISO 8601)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"transfers_24h": 150,
|
|
"volume_24h": "5000000000000000000000",
|
|
"chains": {
|
|
"138": {
|
|
"outbound": 75,
|
|
"inbound": 75,
|
|
"volume_out": "2500000000000000000000",
|
|
"volume_in": "2500000000000000000000"
|
|
}
|
|
},
|
|
"top_tokens": [
|
|
{
|
|
"token": "0x...",
|
|
"symbol": "USDC",
|
|
"transfers": 50,
|
|
"volume": "2000000000000000000000"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track3/analytics/token-distribution
|
|
Get token concentration and distribution analysis.
|
|
|
|
**Path Parameters:**
|
|
- `contract` (required): Token contract address (0x...)
|
|
|
|
**Query Parameters:**
|
|
- `top_n` (optional, default: 100): Number of top holders
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"contract": "0x...",
|
|
"symbol": "USDC",
|
|
"total_supply": "1000000000000000",
|
|
"holders": 5000,
|
|
"distribution": {
|
|
"top_10_percent": "60.5",
|
|
"top_1_percent": "25.0",
|
|
"gini_coefficient": "0.75"
|
|
},
|
|
"top_holders": [
|
|
{
|
|
"address": "0x...",
|
|
"balance": "100000000000000",
|
|
"percentage": "10.0"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track3/analytics/address-risk
|
|
Get address risk analysis.
|
|
|
|
**Path Parameters:**
|
|
- `addr` (required): Ethereum address (0x...)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"address": "0x...",
|
|
"risk_score": 0.25,
|
|
"risk_level": "low",
|
|
"factors": {
|
|
"suspicious_activity": false,
|
|
"known_scam": false,
|
|
"high_volume": true,
|
|
"token_concentration": "medium"
|
|
},
|
|
"flags": []
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Track 4: Operator Tools (Track 4 Required)
|
|
|
|
### Base URL
|
|
```
|
|
/api/v1/track4
|
|
```
|
|
|
|
### Authentication
|
|
- **Required**: JWT token with `track: 4` claim
|
|
- **Additional**: Wallet signature verification
|
|
- **Header**: `Authorization: Bearer <token>`
|
|
- **Header**: `X-Wallet-Signature: <signature>`
|
|
|
|
### Security
|
|
- **IP Whitelist**: Required
|
|
- **Role Allow-list**: Required
|
|
- **Audit Logging**: All requests logged immutably
|
|
|
|
### Rate Limits
|
|
- **Track 4**: 20 req/s, 200 req/min per user (strict limits)
|
|
|
|
### Endpoints
|
|
|
|
#### GET /api/v1/track4/operator/bridge/events
|
|
Get bridge operator events and control state.
|
|
|
|
**Query Parameters:**
|
|
- `chain_id` (optional): Filter by chain ID
|
|
- `event_type` (optional): Filter by event type
|
|
- `start_date` (optional): Start date (ISO 8601)
|
|
- `end_date` (optional): End date (ISO 8601)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"events": [
|
|
{
|
|
"id": "evt_123",
|
|
"chain_id": 138,
|
|
"event_type": "transfer",
|
|
"timestamp": "2024-01-20T10:30:00Z",
|
|
"status": "completed",
|
|
"details": {}
|
|
}
|
|
],
|
|
"control_state": {
|
|
"paused": false,
|
|
"maintenance_mode": false,
|
|
"last_update": "2024-01-20T10:30:00Z"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Error Responses:**
|
|
- `401 Unauthorized`: Missing or invalid token
|
|
- `403 Forbidden`: Insufficient track level or not on IP whitelist
|
|
- `403 Forbidden`: Invalid wallet signature
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track4/operator/validators
|
|
Get validator/sequencer status and information.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"validators": [
|
|
{
|
|
"address": "0x...",
|
|
"status": "active",
|
|
"stake": "1000000000000000000000",
|
|
"uptime": "99.5",
|
|
"last_block": 12345,
|
|
"last_seen": "2024-01-20T10:30:00Z"
|
|
}
|
|
],
|
|
"total_validators": 10,
|
|
"active_validators": 9
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track4/operator/contracts
|
|
Get contract registry and status.
|
|
|
|
**Query Parameters:**
|
|
- `chain_id` (optional): Filter by chain ID
|
|
- `type` (optional): Filter by contract type
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"contracts": [
|
|
{
|
|
"address": "0x...",
|
|
"chain_id": 138,
|
|
"type": "bridge",
|
|
"name": "CCIP Router",
|
|
"status": "active",
|
|
"version": "1.0.0",
|
|
"last_verified": "2024-01-20T10:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### GET /api/v1/track4/operator/protocol-state
|
|
Get protocol configuration and state.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"protocol_version": "1.0.0",
|
|
"chain_id": 138,
|
|
"config": {
|
|
"bridge_enabled": true,
|
|
"max_transfer_amount": "1000000000000000000000000",
|
|
"fee_structure": {}
|
|
},
|
|
"state": {
|
|
"total_locked": "50000000000000000000000000",
|
|
"total_bridged": "10000000000000000000000000",
|
|
"active_bridges": 2
|
|
},
|
|
"last_updated": "2024-01-20T10:30:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Common Error Responses
|
|
|
|
All endpoints may return these common errors:
|
|
|
|
### 400 Bad Request
|
|
```json
|
|
{
|
|
"error": "bad_request",
|
|
"message": "Invalid request parameters",
|
|
"details": {}
|
|
}
|
|
```
|
|
|
|
### 401 Unauthorized
|
|
```json
|
|
{
|
|
"error": "unauthorized",
|
|
"message": "Authentication required"
|
|
}
|
|
```
|
|
|
|
### 403 Forbidden
|
|
```json
|
|
{
|
|
"error": "forbidden",
|
|
"message": "Insufficient permissions",
|
|
"required_track": 2
|
|
}
|
|
```
|
|
|
|
### 404 Not Found
|
|
```json
|
|
{
|
|
"error": "not_found",
|
|
"message": "Resource not found"
|
|
}
|
|
```
|
|
|
|
### 429 Too Many Requests
|
|
```json
|
|
{
|
|
"error": "rate_limit_exceeded",
|
|
"message": "Rate limit exceeded",
|
|
"retry_after": 60
|
|
}
|
|
```
|
|
|
|
### 500 Internal Server Error
|
|
```json
|
|
{
|
|
"error": "internal_error",
|
|
"message": "An internal error occurred",
|
|
"request_id": "req_123"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Authentication Flow
|
|
|
|
### Wallet Authentication (Tracks 2-4)
|
|
|
|
1. **Request Nonce**
|
|
```
|
|
POST /api/v1/auth/nonce
|
|
Body: { "address": "0x..." }
|
|
Response: { "nonce": "random_string", "expires_at": "..." }
|
|
```
|
|
|
|
2. **Sign and Authenticate**
|
|
```
|
|
POST /api/v1/auth/wallet
|
|
Body: {
|
|
"address": "0x...",
|
|
"signature": "0x...",
|
|
"nonce": "random_string"
|
|
}
|
|
Response: {
|
|
"token": "jwt_token",
|
|
"expires_at": "...",
|
|
"track": 2,
|
|
"permissions": [...]
|
|
}
|
|
```
|
|
|
|
3. **Use Token**
|
|
```
|
|
Authorization: Bearer <jwt_token>
|
|
```
|
|
|
|
---
|
|
|
|
## Rate Limit Headers
|
|
|
|
All responses include rate limit headers:
|
|
|
|
```
|
|
X-RateLimit-Limit: 100
|
|
X-RateLimit-Remaining: 95
|
|
X-RateLimit-Reset: 1640995200
|
|
```
|
|
|
|
---
|
|
|
|
## Pagination
|
|
|
|
Paginated endpoints use consistent pagination:
|
|
|
|
**Query Parameters:**
|
|
- `page`: Page number (1-indexed)
|
|
- `limit`: Items per page
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"pagination": {
|
|
"page": 1,
|
|
"limit": 20,
|
|
"total": 500,
|
|
"total_pages": 25,
|
|
"has_next": true,
|
|
"has_prev": false
|
|
}
|
|
}
|
|
```
|