|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +Ethernal is an open-source block explorer for EVM-based chains. It consists of a Vue 3 frontend and a Node.js/Express backend with PostgreSQL database. |
| 8 | + |
| 9 | +## Common Commands |
| 10 | + |
| 11 | +### Frontend (root directory) |
| 12 | +```bash |
| 13 | +yarn dev # Start dev server with Vite |
| 14 | +yarn build # Production build |
| 15 | +yarn test # Run Vitest tests |
| 16 | +yarn test:update # Update test snapshots |
| 17 | +yarn lint # ESLint with auto-fix |
| 18 | +``` |
| 19 | + |
| 20 | +### Backend (run/ directory) |
| 21 | +```bash |
| 22 | +cd run |
| 23 | +npm start # Start server with nodemon |
| 24 | +npm test # Run Jest tests |
| 25 | +npm run test:update # Update snapshots |
| 26 | +npm run worker:high # Start high priority worker |
| 27 | +npm run worker:medium # Start medium priority worker |
| 28 | +npm run worker:low # Start low priority worker |
| 29 | +``` |
| 30 | + |
| 31 | +### Database Migrations |
| 32 | +```bash |
| 33 | +cd run |
| 34 | +npx sequelize db:migrate # Run migrations |
| 35 | +npx sequelize db:seed:all # Run all seeders |
| 36 | +``` |
| 37 | + |
| 38 | +### Docker (self-hosted production) |
| 39 | +```bash |
| 40 | +make start # Start production stack (generates env files on first run) |
| 41 | +make stop # Stop all containers |
| 42 | +make update # Pull latest images and run migrations |
| 43 | +make nuke # Remove everything including volumes |
| 44 | +``` |
| 45 | + |
| 46 | +## Architecture |
| 47 | + |
| 48 | +### Frontend (`src/`) |
| 49 | +- **Vue 3** with Vuetify 3 for UI components |
| 50 | +- **Pinia** stores in `src/stores/` for state management |
| 51 | +- **Vite** for build tooling, Vitest for testing |
| 52 | +- Components in `src/components/` - major ones include Block, Transaction, Address, Contract views |
| 53 | +- Router in `src/plugins/router.js` - includes Etherscan-compatible routes |
| 54 | + |
| 55 | +### Backend (`run/`) |
| 56 | +- **Express** server with Sequelize ORM |
| 57 | +- **BullMQ** for job queues with Redis |
| 58 | +- **Soketi** (Pusher-compatible) for real-time updates |
| 59 | +- API routes in `run/api/` - RESTful endpoints for blocks, transactions, contracts, explorers |
| 60 | +- Sequelize models in `run/models/` |
| 61 | +- Background jobs in `run/jobs/` - block syncing, contract processing, token transfers |
| 62 | +- Workers in `run/workers/` - high/medium/low priority queues |
| 63 | + |
| 64 | +### Job Queue System |
| 65 | +Jobs are prioritized into three queues (high, medium, low) plus a dedicated `processHistoricalBlocks` queue. Workers process jobs like `blockSync`, `processContract`, `processTokenTransfer`. |
| 66 | + |
| 67 | +### Key Models |
| 68 | +- `Explorer` - represents a blockchain explorer instance |
| 69 | +- `Block`, `Transaction`, `Contract` - core blockchain data |
| 70 | +- `TokenTransfer`, `ERC721Token` - token-related data |
| 71 | +- `User`, `Workspace` - user and workspace management |
| 72 | + |
| 73 | +## Testing |
| 74 | + |
| 75 | +Frontend tests: `tests/unit/` directory, uses Vitest with Vue Test Utils |
| 76 | +Backend tests: `run/tests/` directory, uses Jest with supertest |
| 77 | + |
| 78 | +Run a single frontend test: |
| 79 | +```bash |
| 80 | +yarn test -- path/to/test.spec.js |
| 81 | +``` |
| 82 | + |
| 83 | +Run a single backend test: |
| 84 | +```bash |
| 85 | +cd run && npm test -- path/to/test.spec.js |
| 86 | +``` |
| 87 | + |
| 88 | +## Code Style |
| 89 | + |
| 90 | +- Preserve existing code comments unless completely irrelevant after changes |
| 91 | +- Fix Vue console warnings (`[Vue warn]`) |
| 92 | +- Use `@/` alias for imports from `src/` in frontend code |
| 93 | + |
| 94 | +## Documentation Requirements |
| 95 | + |
| 96 | +All new files and functions must include JSDoc documentation. Use the `/**` format (not `/*`). |
| 97 | + |
| 98 | +### Vue Components (Frontend) |
| 99 | + |
| 100 | +Add a JSDoc comment block before the `<script>` or `<script setup>` tag: |
| 101 | + |
| 102 | +```vue |
| 103 | +/** |
| 104 | + * @fileoverview Brief description of the component's purpose. |
| 105 | + * Additional details about functionality if needed. |
| 106 | + * @component ComponentName |
| 107 | + * |
| 108 | + * @prop {string} propName - Description of the prop |
| 109 | + * @prop {Object} [optionalProp] - Optional prop with brackets |
| 110 | + * @emits eventName - Description of when this event is emitted |
| 111 | + */ |
| 112 | +<script setup> |
| 113 | +``` |
| 114 | + |
| 115 | +### Backend Functions (Node.js) |
| 116 | + |
| 117 | +Add JSDoc before each exported function: |
| 118 | + |
| 119 | +```javascript |
| 120 | +/** |
| 121 | + * Brief description of what the function does. |
| 122 | + * |
| 123 | + * @param {string} param1 - Description of param1 |
| 124 | + * @param {Object} options - Configuration options |
| 125 | + * @param {boolean} [options.optional] - Optional parameter |
| 126 | + * @returns {Promise<ReturnType>} Description of return value |
| 127 | + * @throws {Error} When something fails |
| 128 | + */ |
| 129 | +const myFunction = async (param1, options = {}) => { |
| 130 | +``` |
| 131 | +
|
| 132 | +### Sequelize Models |
| 133 | +
|
| 134 | +Add file-level and class-level documentation: |
| 135 | +
|
| 136 | +```javascript |
| 137 | +/** |
| 138 | + * @fileoverview Model description |
| 139 | + * @module models/ModelName |
| 140 | + */ |
| 141 | + |
| 142 | +/** |
| 143 | + * ModelName model class. |
| 144 | + * Detailed description of what this model represents. |
| 145 | + * |
| 146 | + * @class ModelName |
| 147 | + * @extends Sequelize.Model |
| 148 | + * |
| 149 | + * @property {number} id - Primary key |
| 150 | + * @property {string} name - Description of the field |
| 151 | + */ |
| 152 | +``` |
| 153 | +
|
| 154 | +### API Routes |
| 155 | +
|
| 156 | +Document the route file and each endpoint: |
| 157 | +
|
| 158 | +```javascript |
| 159 | +/** |
| 160 | + * @fileoverview API endpoints for resource management |
| 161 | + * @module api/resources |
| 162 | + */ |
| 163 | + |
| 164 | +/** |
| 165 | + * GET /resources |
| 166 | + * Retrieves a paginated list of resources. |
| 167 | + * |
| 168 | + * @param {Object} req.query - Query parameters |
| 169 | + * @param {number} [req.query.page=1] - Page number |
| 170 | + * @returns {Object} { items: Resource[], total: number } |
| 171 | + */ |
| 172 | +router.get('/', async (req, res) => { |
| 173 | +``` |
| 174 | +
|
| 175 | +### Key Documentation Tags |
| 176 | +
|
| 177 | +| Tag | Usage | |
| 178 | +|-----|-------| |
| 179 | +| `@fileoverview` | File-level description (first line of JSDoc) | |
| 180 | +| `@module` | Module path for backend files | |
| 181 | +| `@component` | Vue component name | |
| 182 | +| `@param` | Function parameter with type and description | |
| 183 | +| `@returns` | Return value with type and description | |
| 184 | +| `@throws` | Exceptions that may be thrown | |
| 185 | +| `@prop` | Vue component prop | |
| 186 | +| `@emits` | Vue component event | |
| 187 | +| `@property` | Object/class property | |
| 188 | +
|
| 189 | +## Module Reference |
| 190 | +
|
| 191 | +All source files include JSDoc documentation. Below is a reference of the main modules. |
| 192 | +
|
| 193 | +### Backend Core Libraries (`run/lib/`) |
| 194 | +
|
| 195 | +| Module | Description | |
| 196 | +|--------|-------------| |
| 197 | +| `utils.js` | Common utilities (sanitize, slugify, BigNumber handling, sleep, timeout) | |
| 198 | +| `queue.js` | BullMQ job queue management (enqueue, bulkEnqueue) | |
| 199 | +| `rpc.js` | Ethereum RPC connectors (ProviderConnector, ContractConnector, Tracer, ERC721Connector) | |
| 200 | +| `crypto.js` | Encryption (AES-256), JWT encoding, Firebase Scrypt password hashing | |
| 201 | +| `pusher.js` | Real-time notifications via Pusher/Soketi WebSockets | |
| 202 | +| `pm2.js` | PM2 process management client for sync processes | |
| 203 | +| `logger.js` | Winston-based structured JSON logging | |
| 204 | +| `env.js` | Environment variable accessors | |
| 205 | +| `flags.js` | Feature flags (isSelfHosted, isPusherEnabled, isStripeEnabled, etc.) | |
| 206 | +| `abi.js` | ABI encoding/decoding, token standard detection (ERC20/721/1155) | |
| 207 | +| `trace.js` | Transaction trace parsing (debug_traceTransaction) | |
| 208 | +
|
| 209 | +### Backend Models (`run/models/`) |
| 210 | +
|
| 211 | +Core data models using Sequelize ORM: |
| 212 | +
|
| 213 | +| Model | Description | |
| 214 | +|-------|-------------| |
| 215 | +| `Block` | Blockchain blocks with transactions | |
| 216 | +| `Transaction` | Transactions with receipts and logs | |
| 217 | +| `Contract` | Smart contracts with verification status | |
| 218 | +| `TokenTransfer` | ERC20/721/1155 token transfers | |
| 219 | +| `Explorer` | Explorer instances with branding and settings | |
| 220 | +| `Workspace` | User workspaces linked to explorers | |
| 221 | +| `User` | User accounts with authentication | |
| 222 | +| `StripeSubscription` | Billing subscriptions | |
| 223 | +| `OrbitChainConfig` | Arbitrum Orbit L2 chain configuration | |
| 224 | +| `OpChainConfig` | OP Stack L2 chain configuration | |
| 225 | +
|
| 226 | +### Backend API Routes (`run/api/`) |
| 227 | +
|
| 228 | +RESTful endpoints grouped by resource: |
| 229 | +
|
| 230 | +| Route File | Endpoints | |
| 231 | +|------------|-----------| |
| 232 | +| `blocks.js` | GET /blocks, GET /blocks/:number | |
| 233 | +| `transactions.js` | GET /transactions, GET /transactions/:hash | |
| 234 | +| `contracts.js` | GET /contracts, POST /contracts/:address/verify | |
| 235 | +| `explorers.js` | CRUD operations for explorer management | |
| 236 | +| `workspaces.js` | Workspace CRUD and settings | |
| 237 | +
|
| 238 | +### Backend Jobs (`run/jobs/`) |
| 239 | +
|
| 240 | +Background job handlers for async processing: |
| 241 | +
|
| 242 | +| Job | Description | |
| 243 | +|-----|-------------| |
| 244 | +| `blockSync` | Synchronizes blocks from RPC to database | |
| 245 | +| `processContract` | Detects token standards, fetches metadata | |
| 246 | +| `processTokenTransfer` | Creates token transfer records from logs | |
| 247 | +| `integrityCheck` | Verifies block sequence integrity | |
| 248 | +
|
| 249 | +### Frontend Plugins (`src/plugins/`) |
| 250 | +
|
| 251 | +| Plugin | Description | |
| 252 | +|--------|-------------| |
| 253 | +| `server.js` | API client with all backend endpoints | |
| 254 | +| `router.js` | Vue Router configuration with all routes | |
| 255 | +| `pusher.js` | Pusher/Soketi WebSocket client | |
| 256 | +| `firebase.js` | Firebase authentication client | |
| 257 | +| `vuetify.js` | Vuetify 3 UI framework setup | |
| 258 | +
|
| 259 | +### Frontend Stores (`src/stores/`) |
| 260 | +
|
| 261 | +Pinia state management: |
| 262 | +
|
| 263 | +| Store | Description | |
| 264 | +|-------|-------------| |
| 265 | +| `user.js` | Current user state and authentication | |
| 266 | +| `explorer.js` | Current explorer configuration | |
| 267 | +| `currentWorkspace.js` | Active workspace settings | |
| 268 | +| `env.js` | Environment and domain info | |
| 269 | +| `walletStore.js` | Web3 wallet connection state | |
| 270 | +
|
| 271 | +### PM2 Server (`pm2-server/`) |
| 272 | +
|
| 273 | +Process management server for blockchain synchronization: |
| 274 | +
|
| 275 | +| File | Description | |
| 276 | +|------|-------------| |
| 277 | +| `app.js` | Express server with PM2 management endpoints | |
| 278 | +| `logListener.js` | Event listener for Orbit/OP Stack L1 events | |
| 279 | +| `lib/pm2.js` | PM2 process control functions | |
0 commit comments