chore: sync submodule state (parent ref update)
Made-with: Cursor
This commit is contained in:
33
docs/CHANGELOG.md
Normal file
33
docs/CHANGELOG.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Changelog — SolaceScanScout Explorer
|
||||
|
||||
All notable frontend and docs changes are listed here.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- **Search results list:** When using search (Blockscout `/v2/search`), all matches are shown in a list; user can click a row to open address, tx, block, or token.
|
||||
- **Tokens page:** Navigation "Tokens" opens a dedicated view that lists tokens from `/v2/tokens` when available, or prompts to use the search bar.
|
||||
- **Token approval scanner link:** On address detail, a "Check token approvals" link points to revoke.cash (or similar) with the current address and chainId.
|
||||
- **Contract creation and first/last tx:** Address detail shows "Contract created in tx 0x…", "First seen", and "Last seen" when the Blockscout address API returns `creation_tx_hash` / `first_transaction_at` / `last_transaction_at` (or equivalent).
|
||||
- **Pagination:** Blocks list and Transactions list support Prev/Next using `page` and `page_size` (25 per page).
|
||||
- **Event log decoding:** On transaction detail, event logs table has a "Decoded" column; when contract ABI is available from Blockscout, logs are decoded via ethers.js and show event name and arguments.
|
||||
- **Failed tx rate in Gas & Network:** The Gas & Network card shows "Failed (recent): X%" based on the last 100 transactions.
|
||||
- **i18n:** New translation keys (Back, Export CSV, Token Balances, Internal Txns, Read/Write contract, Watchlist, Check approvals, Copied) and French (FR) locale option.
|
||||
- **Copy to clipboard:** Copy buttons on block hash, transaction hash, and address in detail views; toast "Copied" on success.
|
||||
- **Known-address labels:** Curated labels for CCIP bridges, WETH9/10, CCIP Router/Sender; combined with user-defined labels from localStorage.
|
||||
- **Address labels in tables:** Latest transactions (home), block detail (miner), transaction detail (from/to), and all-transactions list use `formatAddressWithLabel()` so labels appear consistently.
|
||||
- **EXPLORER_API_REFERENCE.md:** Section on OpenAPI/Swagger link (if Blockscout exposes it) and "Recent changes" summary.
|
||||
- **CHANGELOG.md:** This file.
|
||||
|
||||
### Changed
|
||||
|
||||
- Blocks and Transactions list now load with pagination (page 1 by default; Prev/Next updates the list).
|
||||
- Search no longer auto-navigates to the first result only; it shows the full search results list for user selection.
|
||||
- Gas & Network widget includes failed transaction rate when on Chain 138.
|
||||
|
||||
---
|
||||
|
||||
## Previous releases
|
||||
|
||||
Earlier work (Tiers 1–3) included: transaction detail (input, internal txs, revert reason, logs); address detail (token balances, internal txs, NFTs, contract ABI/bytecode); contract verification and Read/Write contract; token and NFT profiles; dark mode; CSV exports (blocks, txs, address txs, token balances); permalinks; watchlist and address labels; Analytics/Operator view fix; API reference and recommendations doc.
|
||||
133
docs/ERR_TOO_MANY_REDIRECTS_AND_CHECKS.md
Normal file
133
docs/ERR_TOO_MANY_REDIRECTS_AND_CHECKS.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# ERR_TOO_MANY_REDIRECTS and Operator Checks
|
||||
|
||||
## Screenshot error: "explorer.d-bis.org redirected you too many times"
|
||||
|
||||
**URL:** `https://explorer.d-bis.org/snap/`
|
||||
**Browser:** ERR_TOO_MANY_REDIRECTS
|
||||
|
||||
### Root cause
|
||||
|
||||
1. **NPMplus** (reverse proxy) terminates HTTPS and forwards traffic to the explorer VM (VMID 5000) on **port 80 (HTTP)**.
|
||||
2. The VM’s nginx had **"redirect all HTTP → HTTPS"** for `location /`.
|
||||
3. So: Browser (HTTPS) → NPMplus → VM (HTTP) → nginx returns **301 to HTTPS** → browser requests HTTPS again → same path → loop.
|
||||
|
||||
So the VM was always telling the client "use HTTPS" even when the client was already using HTTPS via the proxy.
|
||||
|
||||
### Fix (already in repo)
|
||||
|
||||
Nginx was updated to **not** redirect to HTTPS when the request is already marked as HTTPS by the proxy:
|
||||
|
||||
- **`X-Forwarded-Proto: https`** → treat as HTTPS and **do not** send 301.
|
||||
|
||||
Scripts that apply the fix (run **inside VMID 5000** or via Proxmox host):
|
||||
|
||||
- **Custom frontend config:** `scripts/fix-nginx-serve-custom-frontend.sh`
|
||||
- **Conflicts / proxy-everything config:** `scripts/fix-nginx-conflicts-vmid5000.sh`
|
||||
|
||||
Both now:
|
||||
|
||||
- Only redirect HTTP→HTTPS when `X-Forwarded-Proto` is not `https`.
|
||||
- Serve **`/snap/`** from `/var/www/html/snap/` (so the Snap companion page doesn’t get proxied to Blockscout and cause 404/redirects).
|
||||
|
||||
**Apply from repo (Proxmox host or with EXPLORER_VM_HOST):**
|
||||
|
||||
```bash
|
||||
cd explorer-monorepo
|
||||
bash scripts/apply-nginx-explorer-fix.sh
|
||||
```
|
||||
|
||||
Or, inside VMID 5000:
|
||||
|
||||
```bash
|
||||
bash /path/to/fix-nginx-serve-custom-frontend.sh
|
||||
# or
|
||||
nginx -t && systemctl reload nginx
|
||||
```
|
||||
|
||||
Ensure **`/var/www/html/snap/`** exists and contains the Snap companion app (e.g. from `metamask-integration/chain138-snap` build). If the directory is missing, `/snap/` will 404 but will no longer redirect in a loop.
|
||||
|
||||
### Deploy Snap companion site to VMID 5000
|
||||
|
||||
1. **Build** (from repo root; requires Node 18+ and pnpm):
|
||||
|
||||
```bash
|
||||
cd metamask-integration/chain138-snap
|
||||
bash scripts/build-snap-site-for-explorer.sh
|
||||
```
|
||||
|
||||
Output: `packages/site/public/`. Build uses `GATSBY_SNAP_API_BASE_URL=https://explorer.d-bis.org` and `GATSBY_PATH_PREFIX=/snap`.
|
||||
|
||||
2. **Deploy** (from repo root). Either:
|
||||
|
||||
- **From the Proxmox host** that has VMID 5000:
|
||||
|
||||
```bash
|
||||
bash explorer-monorepo/scripts/deploy-snap-site-to-vmid5000.sh
|
||||
```
|
||||
|
||||
- **From your dev machine** with SSH key access to the Proxmox node:
|
||||
|
||||
```bash
|
||||
EXPLORER_VM_HOST=root@192.168.11.12 bash explorer-monorepo/scripts/deploy-snap-site-to-vmid5000.sh
|
||||
```
|
||||
|
||||
The script tars `metamask-integration/chain138-snap/packages/site/public/` and deploys it to `/var/www/html/snap/` in VMID 5000. To build and deploy in one go: `BUILD_FIRST=1 bash explorer-monorepo/scripts/deploy-snap-site-to-vmid5000.sh` (from repo root).
|
||||
|
||||
---
|
||||
|
||||
## Disk space (all VMIDs)
|
||||
|
||||
From the **Proxmox host** (or a machine with SSH to the hosts):
|
||||
|
||||
```bash
|
||||
./scripts/maintenance/check-disk-all-vmids.sh
|
||||
```
|
||||
|
||||
Optional CSV:
|
||||
|
||||
```bash
|
||||
./scripts/maintenance/check-disk-all-vmids.sh --csv
|
||||
```
|
||||
|
||||
Requires SSH key access to the Proxmox hosts (see `config/ip-addresses.conf`).
|
||||
VMID 5000 (explorer) specifically:
|
||||
|
||||
```bash
|
||||
pct exec 5000 -- df -h /
|
||||
```
|
||||
|
||||
Or via SSH to the node that runs VMID 5000:
|
||||
|
||||
```bash
|
||||
ssh root@192.168.11.12 'pct exec 5000 -- df -h /'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Links and health checks
|
||||
|
||||
- **Explorer API:**
|
||||
`curl -sS -o /dev/null -w "%{http_code}" https://explorer.d-bis.org/api/v2/stats`
|
||||
Expect **200** (502 = Blockscout not running; see [WHY_INFO_NOT_LOADING.md](./WHY_INFO_NOT_LOADING.md)).
|
||||
|
||||
- **Explorer root:**
|
||||
`curl -sS -o /dev/null -w "%{http_code}" https://explorer.d-bis.org/`
|
||||
Expect **200**.
|
||||
|
||||
- **Explorer /snap/:**
|
||||
`curl -sS -o /dev/null -w "%{http_code}" -L https://explorer.d-bis.org/snap/`
|
||||
After the nginx fix, expect **200** (or 404 if `/var/www/html/snap/` is not deployed).
|
||||
|
||||
- **Doc link checker (internal docs):**
|
||||
`node scripts/check-doc-links.mjs`
|
||||
(from repo root; checks `docs/` internal links.)
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Issue | Cause | Fix |
|
||||
|-------|--------|-----|
|
||||
| ERR_TOO_MANY_REDIRECTS on /snap/ (or any path) | VM nginx always redirects HTTP→HTTPS while NPMplus forwards as HTTP | Use nginx config that skips redirect when `X-Forwarded-Proto: https`; reload nginx |
|
||||
| /snap/ 404 or wrong content | /snap/ proxied to Blockscout or not served | Serve `/snap/` from `/var/www/html/snap/` (location /snap/ in nginx) |
|
||||
| No stats/blocks (502 on /api/) | Blockscout not running on port 4000 | See [WHY_INFO_NOT_LOADING.md](./WHY_INFO_NOT_LOADING.md), run `scripts/fix-502-blockscout.sh` |
|
||||
69
docs/EXPLORER_ADDITIONAL_RECOMMENDATIONS.md
Normal file
69
docs/EXPLORER_ADDITIONAL_RECOMMENDATIONS.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# SolaceScanScout — Additional Recommendations
|
||||
|
||||
This document lists **further improvements** beyond the upgrades already implemented (Tier 1–3 frontend, API docs, watchlist, labels, i18n, etc.). Items are grouped by effort and dependency (frontend-only vs backend).
|
||||
|
||||
---
|
||||
|
||||
## Frontend-only (quick wins)
|
||||
|
||||
| Recommendation | Description | Effort |
|
||||
|----------------|-------------|--------|
|
||||
| **Event log decoding** | On transaction detail, decode log topics/data using contract ABI when available (fetch ABI from Blockscout for log address, match by topic0 signature). | Medium |
|
||||
| **Address labels in more tables** | Use `formatAddressWithLabel()` in latest transactions (home), block detail (miner), and transaction detail (from/to) so labels appear wherever addresses are shown. | Low |
|
||||
| **More i18n keys** | Add translations for common UI strings (e.g. "Back", "Export CSV", "Token Balances", "Internal Txns", "Read contract", "Write contract") and optionally add another language (e.g. French). | Low |
|
||||
| **Failed tx rate in Gas widget** | If Blockscout stats expose a failed-transaction metric, show it in the Gas & Network card (e.g. "Failed (24h): 0.1%"). | Low |
|
||||
| **Copy-to-clipboard on hashes** | Add a small copy icon next to transaction hash, block hash, and address in detail views; onClick copy full value and show toast "Copied". | Low |
|
||||
| **Pagination on list views** | Blocks and Transactions list views currently load a fixed page (e.g. 50). Add "Next / Prev" or infinite scroll using Blockscout's `page` and `page_size`. | Medium |
|
||||
|
||||
---
|
||||
|
||||
## Frontend + existing API
|
||||
|
||||
| Recommendation | Description | Effort |
|
||||
|----------------|-------------|--------|
|
||||
| **Contract creation tx** | On address detail for contracts, if Blockscout returns `creation_tx_hash` or similar, show "Contract created in tx 0x…" with link. | Low |
|
||||
| **First / last tx (address age)** | If the API exposes first and last transaction timestamp or block, show "First seen" / "Last seen" on address detail. | Low |
|
||||
| **Search results list** | Instead of navigating to the first search result only, show a small list of matches (addresses, txs, blocks, tokens) and let the user pick. | Medium |
|
||||
| **Token list / filters** | A dedicated "Tokens" page that lists verified tokens (if Blockscout has a tokens index) with search and optional filter by type (ERC-20 / ERC-721). | Medium |
|
||||
|
||||
---
|
||||
|
||||
## Security & compliance (plan §9)
|
||||
|
||||
| Recommendation | Description | Effort |
|
||||
|----------------|-------------|--------|
|
||||
| **Known-address labels** | Curated list of known addresses (e.g. bridge contracts, WETH, CCIP) with fixed labels (not user-editable). Could be a small JSON in the repo or fetched from a config endpoint. | Low–Medium |
|
||||
| **Token approval scanner** | Link to an external approval-checker (e.g. revoke.cash style) for Chain 138, or a simple "Check approvals" that deep-links to a tool with the address. No backend required for a link-only approach. | Low (link) / High (actual scanner) |
|
||||
|
||||
---
|
||||
|
||||
## Backend or new services
|
||||
|
||||
| Recommendation | Description | Effort |
|
||||
|----------------|-------------|--------|
|
||||
| **Watchlist email alerts** | Notify users when an address has new transactions (or balance change). Requires backend storage and email/sendgrid. | High |
|
||||
| **Portfolio view** | Multi-address aggregation, historical balance, simple PnL. Requires historical index or third-party API. | High |
|
||||
| **API keys & rate limits** | Tiered API access with keys and rate limits. Requires backend (e.g. Go API) in front of Blockscout or a proxy. | Medium (backend) |
|
||||
| **Cross-chain unified view** | One view for an address across Chain 138 and other chains (e.g. Ethereum mainnet). Requires multi-chain indexer or aggregator. | High |
|
||||
| **Analytics / Operator content** | Fill Analytics (Track 3) and Operator (Track 4) views with real features: e.g. network stats, bridge volume, config toggles. Depends on what the backend exposes (stats API, admin API). | Medium–High |
|
||||
|
||||
---
|
||||
|
||||
## Operational & documentation
|
||||
|
||||
| Recommendation | Description |
|
||||
|----------------|-------------|
|
||||
| **Health/readiness endpoint** | A simple `/api/health` or `/api/ready` that returns 200 when Blockscout is up, for load balancers and monitoring. |
|
||||
| **OpenAPI/Swagger** | If Blockscout serves OpenAPI, document the link in [EXPLORER_API_REFERENCE.md](EXPLORER_API_REFERENCE.md) so developers can discover parameters and response shapes. |
|
||||
| **Changelog** | Keep a short `CHANGELOG.md` or "Recent changes" section in the explorer docs when you ship new features (e.g. "Token balances CSV", "Write contract", "Watchlist"). |
|
||||
| **E2E tests** | Add or extend E2E tests (e.g. Playwright) for critical paths: search → address detail, block list → block detail, export CSV, theme toggle, watchlist add/remove. |
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
- **Already done:** Tier 1–2 (tx/address/contract/token/NFT, gas widget, read/write contract, CSV exports, permalinks, dark mode, i18n), Tier 3 frontend (watchlist, address labels), API reference, Analytics/Operator view fix, token balances CSV, address labels in tables.
|
||||
- **Highest-value next (no new backend):** Event log decoding, address labels in all tables, copy-on-click for hashes, pagination on blocks/transactions, known-address labels, and a "Check approvals" link for token approvals.
|
||||
- **With backend:** Email alerts for watchlist, API keys/rate limits, portfolio, and richer Analytics/Operator content.
|
||||
|
||||
Use this list to prioritize the next sprint or backlog.
|
||||
@@ -255,3 +255,5 @@ Run this after every deploy or nginx change to confirm explorer and Snap site ar
|
||||
1. **502 on `/api/v2/*`** → nginx is up, backend (Blockscout on 4000) is down or not proxied.
|
||||
2. **Provide access**: Start Blockscout on 4000, ensure nginx has `location /api/ { proxy_pass http://127.0.0.1:4000; ... }`, then `nginx -t && systemctl reload nginx`.
|
||||
3. **Verify**: `curl -sS -o /dev/null -w "%{http_code}" https://explorer.d-bis.org/api/v2/stats` returns **200** and `scripts/verify-explorer-api-access.sh` passes.
|
||||
|
||||
**Authenticated API (api.explorer.d-bis.org):** Auth/nonce and full Track 2–4 require a database for nonce storage and operator data. Health may report DEGRADED when the DB is unavailable. See repo root `docs/00-meta/REMAINING_TASKS_AND_API_FEATURES.md` (Explorer API) and `explorer-monorepo/docs/DEPLOYMENT_COMPLETE.md`.
|
||||
|
||||
93
docs/EXPLORER_API_REFERENCE.md
Normal file
93
docs/EXPLORER_API_REFERENCE.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# SolaceScanScout Explorer — API Reference
|
||||
|
||||
The SolaceScanScout frontend uses the **Blockscout v2 API** for chain data. When the explorer is served from the same origin (e.g. `https://explorer.d-bis.org` or VM IP), requests go to `/api` and are proxied to Blockscout (port 4000). This document lists the endpoints used by the frontend.
|
||||
|
||||
## Base URL
|
||||
|
||||
- **Same-origin:** `window.location.origin + '/api'` (e.g. `https://explorer.d-bis.org/api`)
|
||||
- **Fallback:** `https://explorer.d-bis.org/api`
|
||||
|
||||
All paths below are relative to this base (e.g. `/v2/stats` → `{base}/v2/stats`).
|
||||
|
||||
---
|
||||
|
||||
## Stats & Network
|
||||
|
||||
| Endpoint | Method | Purpose |
|
||||
|----------|--------|---------|
|
||||
| `/v2/stats` | GET | Total blocks, transactions, addresses; optional `average_block_time`, `transactions_per_second` |
|
||||
| `/v2/blocks?page=1&page_size=N` | GET | Paginated blocks (N = 5–50). Used for stats, gas widget, block list |
|
||||
| `/v2/blocks/{blockNumber}` | GET | Single block by number. Used for block detail and export |
|
||||
|
||||
---
|
||||
|
||||
## Transactions
|
||||
|
||||
| Endpoint | Method | Purpose |
|
||||
|----------|--------|---------|
|
||||
| `/v2/transactions?page=1&page_size=N` | GET | Paginated transactions (list, CSV export) |
|
||||
| `/v2/transactions?address={address}&page=1&page_size=N` | GET | Transactions for an address (address detail tab, CSV export) |
|
||||
| `/v2/transactions?filter=to&page=1&page_size=10` | GET | Latest transactions (home feed) |
|
||||
| `/v2/transactions/{txHash}` | GET | Single transaction (detail, CSV/JSON export) |
|
||||
| `/v2/transactions/{txHash}/internal-transactions` | GET | Internal transactions for a tx (alternate: `internal_transactions`) |
|
||||
| `/v2/transactions/{txHash}/logs` | GET | Event logs for a tx (alternate: `log_entries`) |
|
||||
|
||||
---
|
||||
|
||||
## Addresses
|
||||
|
||||
| Endpoint | Method | Purpose |
|
||||
|----------|--------|---------|
|
||||
| `/v2/addresses/{address}` | GET | Address balance, tx count, token count, is_contract, is_verified |
|
||||
| `/v2/addresses/{address}/token-balances` | GET | Token balances (ERC-20/721/1155). Alternate: `token_balances` |
|
||||
| `/v2/addresses/{address}/nft-inventory` | GET | NFT inventory (alternates: `nft_tokens`, or filter token-balances by type) |
|
||||
| `/v2/addresses/{address}/internal-transactions` | GET | Internal transactions (alternate: `internal_transactions`) |
|
||||
|
||||
---
|
||||
|
||||
## Contracts & Tokens
|
||||
|
||||
| Endpoint | Method | Purpose |
|
||||
|----------|--------|---------|
|
||||
| `/v2/smart-contracts/{address}` | GET | Contract ABI, bytecode, verification (alternate: `/v2/contracts/{address}`) |
|
||||
| `/v2/tokens/{tokenAddress}` | GET | Token info (name, symbol, decimals, total supply, holders). Alternate: `/v2/token/{tokenAddress}` |
|
||||
| `/v2/tokens/{tokenAddress}/transfers?page=1&page_size=N` | GET | Token transfers (token profile page) |
|
||||
| `/v2/tokens/{contractAddress}/nft/{tokenId}` | GET | NFT instance (metadata, image, owner). Alternate: `/v2/nft/{contractAddress}/{tokenId}` |
|
||||
|
||||
---
|
||||
|
||||
## Search
|
||||
|
||||
| Endpoint | Method | Purpose |
|
||||
|----------|--------|---------|
|
||||
| `/v2/search?q={query}` | GET | Search by token/contract name, symbol, address, tx hash, block number |
|
||||
|
||||
---
|
||||
|
||||
## Response Shapes (summary)
|
||||
|
||||
- **Lists:** Usually `{ items: [...] }` or array. Frontend normalizes with `normalizeBlock`, `normalizeTransaction`, `normalizeAddress`.
|
||||
- **Single block:** `height`/`number`, `hash`, `timestamp`, `miner`, `transaction_count`, `gas_used`, `gas_limit`, `base_fee_per_gas`, `burnt_fees`, `parent_hash`, `nonce`, etc. Optional: `consensus`, `finality`, `validated` for finality.
|
||||
- **Single transaction:** `hash`, `from`, `to`, `value`, `block_number`, `gas_used`, `gas_limit`, `input`, `decoded_input`, `revert_reason`, `status`, etc.
|
||||
- **Address:** `hash`/`address`, `balance`/`coin_balance`, `transactions_count`, `token_count`, `is_contract`, `is_verified`.
|
||||
|
||||
---
|
||||
|
||||
## Rate Limits & API Keys
|
||||
|
||||
The frontend does not send API keys. Rate limits are determined by the Blockscout/nginx deployment. For premium or authenticated access, a separate backend (e.g. Go API) would be required (Tier 3).
|
||||
|
||||
---
|
||||
|
||||
## OpenAPI / Swagger
|
||||
|
||||
If your Blockscout instance exposes an OpenAPI (Swagger) spec, it is often at `{base}/api-docs` or `{base}/swagger`. Document that URL for your deployment (e.g. `https://explorer.d-bis.org/api-docs` if enabled).
|
||||
|
||||
## Recent changes
|
||||
|
||||
- Search results list; Tokens page; Token approvals link; Contract creation / first-last tx on address; Pagination (blocks/txs); Event log decoding; Failed tx rate in Gas widget; More i18n + FR; Copy buttons; Known-address labels. See [EXPLORER_ADDITIONAL_RECOMMENDATIONS.md](EXPLORER_ADDITIONAL_RECOMMENDATIONS.md).
|
||||
|
||||
## See Also
|
||||
|
||||
- [EXPLORER_API_ACCESS.md](EXPLORER_API_ACCESS.md) — Troubleshooting API connectivity and 502s
|
||||
- [Blockscout API docs](https://docs.blockscout.com/) — Official Blockscout API documentation
|
||||
167
docs/EXPLORER_CODE_REVIEW.md
Normal file
167
docs/EXPLORER_CODE_REVIEW.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# Explorer Code Review
|
||||
|
||||
**Date:** 2025-02
|
||||
**Scope:** Backend (Go), Frontend (Next.js + SPA), libs, deployment, CI.
|
||||
|
||||
---
|
||||
|
||||
## 1. Architecture Overview
|
||||
|
||||
| Layer | Tech | Purpose |
|
||||
|-------|------|--------|
|
||||
| **API** | Go 1.22, net/http | REST API (blocks, transactions, addresses, search, stats, Etherscan compat, auth, feature flags). Tiered tracks (1–4) with optional/required auth. |
|
||||
| **Indexer** | Go, go-ethereum, pgx | Listens to chain (RPC/WS), processes blocks/txs, writes to PostgreSQL. |
|
||||
| **Frontend (live)** | Vanilla JS SPA | `frontend/public/index.html` — single HTML + inline script, deployed at https://explorer.d-bis.org. Uses Blockscout-style API, ethers.js from CDN, VMID 2201 RPC. |
|
||||
| **Frontend (dev)** | Next.js 15, React, TypeScript | `frontend/src/` — app + pages router, dev/build only; uses shared libs (api-client, ui-primitives). |
|
||||
| **Libs** | In-repo under `backend/libs/`, `frontend/libs/` | go-pgconfig, go-logging, go-chain-adapters, go-rpc-gateway, go-http-middleware, go-bridge-aggregator; frontend-api-client, frontend-ui-primitives. |
|
||||
|
||||
---
|
||||
|
||||
## 2. Backend (Go)
|
||||
|
||||
### 2.1 Strengths
|
||||
|
||||
- **Clear layering:** `cmd/main.go` → `rest.NewServer` → `SetupRoutes` / `SetupTrackRoutes`. DB, chainID, and auth are configured in one place.
|
||||
- **Reusable libs:** DB config (go-pgconfig), RPC gateway (go-rpc-gateway), security headers (go-http-middleware) are extracted and used consistently.
|
||||
- **Validation:** Centralized in `validation.go`: `isValidHash`, `isValidAddress`, `validateBlockNumber`, `validateChainID`, `validatePagination`, `validateSearchQuery`. Routes validate before calling handlers.
|
||||
- **Nil-DB safety:** `requireDB(w)` used in all DB-dependent handlers; tests run without a real DB and get 503 where appropriate.
|
||||
- **Error contract:** `errors.go` defines `ErrorResponse` / `ErrorDetail` and `writeError`, `writeNotFound`, `writeInternalError`, etc. Most handlers use them for consistent JSON errors.
|
||||
- **Track architecture:** Track 1 (public RPC gateway), 2–4 (auth + tier) with middleware; track routes and auth are clearly separated in `track_routes.go`.
|
||||
- **Auth:** Wallet nonce + JWT in `auth/wallet_auth.go`; address normalization, nonce expiry, and DB-backed nonce storage.
|
||||
|
||||
### 2.2 Issues and Recommendations
|
||||
|
||||
| Item | Severity | Location | Recommendation |
|
||||
|------|----------|----------|----------------|
|
||||
| **Block not found response** | Low | `blocks.go` (handleGetBlockByNumber) | Uses `http.Error(w, fmt.Sprintf("Block not found: %v", err), 404)` → plain text. Prefer `writeNotFound(w, "Block")` (or equivalent) for JSON consistency. Same for `handleGetBlockByHash` if it uses `http.Error`. |
|
||||
| **JWT default secret** | Medium | `server.go` | Default `JWT_SECRET` is logged as warning but still used. Ensure production always sets `JWT_SECRET` (deployment checklist / env template). |
|
||||
| **CORS for /api/** | Info | `server.go` | `Access-Control-Allow-Origin: *` on all `/api/` is permissive. Acceptable for public API; tighten if you need origin allowlist. |
|
||||
| **Track 1 routes in routes.go** | Info | `routes.go` | Track 1 handlers are commented out in `SetupRoutes` and only registered in `SetupTrackRoutes`. Intentional; no change needed. |
|
||||
| **Indexer chainID** | Low | `indexer/main.go` | `chainID := 138` is hardcoded; `CHAIN_ID` env is not read. Add `os.Getenv("CHAIN_ID")` with fallback 138 for consistency with API. |
|
||||
|
||||
### 2.3 Security
|
||||
|
||||
- **Input validation:** Hash, address, block number, chain ID, and pagination are validated before DB/RPC.
|
||||
- **Security headers:** Applied via go-http-middleware (CSP, X-Frame-Options, etc.); CSP is configurable via `CSP_HEADER` env.
|
||||
- **Auth:** Nonce is stored and checked; JWT is validated; track middleware enforces tier.
|
||||
|
||||
---
|
||||
|
||||
## 3. Frontend (Next.js / React)
|
||||
|
||||
### 3.1 Strengths
|
||||
|
||||
- **API client:** Single `createApiClient` (frontend-api-client) with `get` / `getSafe` / post/put/delete; `getSafe` allows checking `ok` before setting state and avoids treating 4xx/5xx body as data.
|
||||
- **Response handling:** Address and transaction detail pages use `getSafe`; search checks `response.ok`; blocks API normalizes `{ data }` / `{ items }` in `blocks.ts`.
|
||||
- **UI primitives:** Card, Table, Address, Button in frontend-ui-primitives; Table supports `keyExtractor`; pages use stable keys (e.g. `tx.hash`, `block.number`).
|
||||
- **Hooks:** Data-loading functions wrapped in `useCallback` with correct deps; `useEffect` deps avoid exhaustive-deps warnings.
|
||||
- **Block number validation:** `blocks/[number].tsx` validates `params.number` and shows "Invalid block number" when invalid.
|
||||
- **No dangerouslySetInnerHTML** in React components; no raw `dangerouslySetInnerHTML` in the reviewed code.
|
||||
|
||||
### 3.2 Issues and Recommendations
|
||||
|
||||
| Item | Severity | Location | Recommendation |
|
||||
|------|----------|----------|----------------|
|
||||
| **Frontend test script** | Info | `frontend/package.json` | `npm test` runs lint + type-check only. Add unit tests (e.g. React Testing Library) if you want component/API coverage. |
|
||||
| **Next.js workspace warning** | Low | Build output | Multiple lockfiles (pnpm at parent, npm in repo) trigger Next.js warning. Set `outputFileTracingRoot` in next.config.js or align lockfile strategy. |
|
||||
| **Transactions list API** | Low | `pages/transactions/index.tsx` | Uses raw `fetch` + `response.json()`; no `response.ok` check before `setTransactions(data.data || [])`. Consider using a transactions API module with `getSafe`-style handling (or add `response.ok` check). |
|
||||
|
||||
### 3.3 TypeScript and Lint
|
||||
|
||||
- Types are used for API responses (AddressInfo, Transaction, Block, SearchResult).
|
||||
- Lint and type-check pass; no critical warnings.
|
||||
|
||||
---
|
||||
|
||||
## 4. SPA (frontend/public/index.html)
|
||||
|
||||
### 4.1 Strengths
|
||||
|
||||
- **Ethers.js loading:** Multiple CDNs with fallback; `ethersReady` event for dependent code.
|
||||
- **RPC:** `getRpcUrl()` with health check and failover; `rpcCall` uses `getRpcUrl()`.
|
||||
- **Constants:** `FETCH_TIMEOUT_MS`, `RPC_HEALTH_TIMEOUT_MS`, `FETCH_MAX_RETRIES`, `RETRY_DELAY_MS`, `API_BASE`; `window.DEBUG_EXPLORER` gates console.log/warn.
|
||||
- **rAF cleanup:** `_blocksScrollAnimationId` cancelled in `switchToView` and before re-running block list animation.
|
||||
- **XSS mitigation:** `escapeHtml` and `encodeURIComponent` used in breadcrumbs, watchlist, block cards, tx rows, and API error messages; block breadcrumb identifier escaped.
|
||||
- **CSP:** Meta CSP present; comment notes `unsafe-eval` required by ethers v5 UMD.
|
||||
|
||||
### 4.2 Issues and Recommendations
|
||||
|
||||
| Item | Severity | Location | Recommendation |
|
||||
|------|----------|----------|----------------|
|
||||
| **File size** | Info | `index.html` | ~4.6k+ lines in one file. Hard to maintain. Consider splitting into separate JS files (e.g. `app.js`, `views.js`, `rpc.js`) or migrating critical flows to the Next app. |
|
||||
| **Duplicate logic** | Low | SPA vs Next | Blocks/transactions/addresses exist in both SPA and Next.js pages. Document which is canonical for production (SPA) and that Next is for dev/build only. |
|
||||
| **CSP unsafe-eval** | Info | CSP | Required by ethers v5 UMD. If you upgrade to a build (e.g. ethers v6 without UMD), you can remove `unsafe-eval`. |
|
||||
|
||||
---
|
||||
|
||||
## 5. Libs (backend/libs, frontend/libs)
|
||||
|
||||
- **go-pgconfig:** Used by API and indexer; loads from env, builds pool config. No issues.
|
||||
- **go-rpc-gateway:** Cache (memory/Redis), rate limiter (memory/Redis), RPC gateway. Track 1 uses it; no duplicate in-tree.
|
||||
- **go-http-middleware:** Security headers with configurable CSP. Used in server.
|
||||
- **frontend-api-client:** Axios-based client with `get`/`getSafe`/post/put/delete; ApiResponse/ApiError types. Used by blocks, addresses, transactions services.
|
||||
- **frontend-ui-primitives:** Card, Table, Address, Button. Used by Next pages; Table has `keyExtractor`.
|
||||
|
||||
---
|
||||
|
||||
## 6. Deployment and CI
|
||||
|
||||
- **CI:** Backend tests + build; frontend install + `npm test` + build; lint job runs `go vet`, `npm run lint`, `npm run type-check`. Submodules checked out recursively.
|
||||
- **Deployment:** Docs reference VMID 5000, nginx, Blockscout, RPC VMID 2201; env templates and systemd examples exist under `deployment/`.
|
||||
- **Recommendation:** Ensure production sets `JWT_SECRET`, `RPC_URL`, `CHAIN_ID`, and DB env; run migrations before starting API/indexer.
|
||||
|
||||
---
|
||||
|
||||
## 7. Testing
|
||||
|
||||
- **Backend:** `go test ./...` passes; `api/rest` tests run without DB and accept 200/503/404 as appropriate.
|
||||
- **Frontend:** `npm test` (lint + type-check) and `npm run build` succeed.
|
||||
- **E2E:** Playwright (15 tests) against explorer.d-bis.org; paths, nav, breadcrumbs, block detail covered.
|
||||
- **Gaps:** No backend integration tests with real DB; no frontend unit tests; indexer has no test files. Optional: add integration test job (e.g. with testcontainers) and a few React tests for critical pages.
|
||||
|
||||
---
|
||||
|
||||
## 8. Summary Table
|
||||
|
||||
| Area | Grade | Notes |
|
||||
|------|--------|--------|
|
||||
| Backend structure | A | Clear routes, validation, error handling, nil-DB safety. |
|
||||
| Backend security | A- | Validation and auth in place; JWT default secret and block 404 JSON to tighten. |
|
||||
| Frontend (Next) | A | Type-safe API usage, getSafe, stable keys, validation. |
|
||||
| SPA (index.html) | B+ | Escape/encode in place, rAF cleanup, constants; single large file. |
|
||||
| Libs | A | Used consistently; no duplication. |
|
||||
| CI/CD | A | Tests, build, lint; submodules. |
|
||||
| Docs | A- | README, testing, extraction plan, frontend task list. |
|
||||
|
||||
**Overall:** The explorer codebase is in good shape: clear architecture, consistent validation and error handling, and sensible use of shared libs. The main follow-ups are minor (block 404 JSON, indexer CHAIN_ID env, transactions list response.ok, and optional tests/docs).
|
||||
|
||||
---
|
||||
|
||||
## 9. Recommended next steps – completed
|
||||
|
||||
| Step | Status |
|
||||
|------|--------|
|
||||
| Transactions list: use safe response (ok check) | Done: `transactionsApi.listSafe` used in `frontend/src/pages/transactions/index.tsx`. |
|
||||
| Production: JWT_SECRET + migrations | Done: `docs/PRODUCTION_CHECKLIST.md` and note in `deployment/ENVIRONMENT_TEMPLATE.env`. |
|
||||
| Optional: frontend unit test | Done: Vitest + `frontend/libs/frontend-api-client/client.test.ts`; run `pnpm run test:unit` (after `pnpm install` in frontend). |
|
||||
| Optional: backend integration test | Documented in `backend/README_TESTING.md` (current suite runs without DB; note added for optional DB/testcontainers). |
|
||||
|
||||
**Run verification (as of last run):**
|
||||
|
||||
- `cd backend && go test ./...`: all pass (api/rest, benchmarks).
|
||||
- `cd frontend && npm test` (lint + type-check): pass. Test files excluded from `tsconfig` so type-check does not require Vitest.
|
||||
- `cd frontend && pnpm run test:unit`: 2 Vitest tests pass (api client `getSafe`).
|
||||
- `make test-e2e`: Playwright against live site; address/root tests made more resilient (timeouts and selector fallbacks). Run when needed; live URL may vary.
|
||||
|
||||
---
|
||||
|
||||
## 10. Remaining optional items (all completed)
|
||||
|
||||
| Item | Status |
|
||||
|------|--------|
|
||||
| **Next.js workspace warning** | Done: Comment added in `frontend/next.config.js`; align package manager in frontend or ignore for dev/build. (Next 14 does not support `outputFileTracingRoot` in config; standalone trace uses project root.) |
|
||||
| **CORS** | Done: `CORS_ALLOWED_ORIGIN` env in `server.go`; default `*`, set to e.g. `https://explorer.d-bis.org` to restrict. Documented in `deployment/ENVIRONMENT_TEMPLATE.env`. |
|
||||
| **SPA file size** | Done: main app script extracted to `frontend/public/explorer-spa.js` (~3.5k lines); `index.html` now ~1.15k lines. Deploy scripts copy `explorer-spa.js` (e.g. `deploy-frontend-to-vmid5000.sh`, `deploy.sh`). |
|
||||
| **SPA vs Next canonical** | Done: `README.md` states production serves the SPA, Next.js is for local dev and build validation only. |
|
||||
| **CSP unsafe-eval** | Done: comment in `index.html` CSP meta updated: "Can be removed when moving to ethers v6 build (no UMD eval)." |
|
||||
| **Further product work** | See `docs/EXPLORER_ADDITIONAL_RECOMMENDATIONS.md` (i18n, event log decoding, token list, health endpoint, etc.). |
|
||||
44
docs/EXPLORER_FRONTEND_TESTING.md
Normal file
44
docs/EXPLORER_FRONTEND_TESTING.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Explorer Frontend Testing
|
||||
|
||||
## Summary
|
||||
|
||||
Path-based URLs (e.g. `/address/0x99b3511a2d315a497c8112c1fdd8d508d4b1e506`) now work on the explorer. The fix includes:
|
||||
|
||||
1. **SPA path-based routing** – `applyHashRoute()` in `frontend/public/index.html` reads both `pathname` and `hash`, so `/address/0x...`, `/tx/0x...`, `/block/123`, etc. load correctly.
|
||||
2. **Nginx SPA paths** – Nginx serves `index.html` for `/address`, `/tx`, `/block`, `/token`, `/blocks`, `/transactions`, `/bridge`, `/weth`, `/watchlist`, and `/nft`.
|
||||
3. **HTTP + HTTPS** – Both HTTP (for internal tests) and HTTPS serve the SPA for these paths.
|
||||
|
||||
## Test Commands
|
||||
|
||||
### Shell E2E (curl-based)
|
||||
|
||||
```bash
|
||||
./explorer-monorepo/scripts/e2e-test-explorer.sh
|
||||
```
|
||||
|
||||
Requires network access to `192.168.11.140` (VMID 5000).
|
||||
|
||||
### Playwright E2E
|
||||
|
||||
```bash
|
||||
cd explorer-monorepo
|
||||
EXPLORER_URL="http://192.168.11.140" npx playwright test e2e-explorer-frontend.spec.ts --project=chromium
|
||||
```
|
||||
|
||||
## Links Verified
|
||||
|
||||
| Link | Example |
|
||||
|------|---------|
|
||||
| Address | `/address/0x99b3511a2d315a497c8112c1fdd8d508d4b1e506` |
|
||||
| Tx | `/tx/<hash>` |
|
||||
| Block | `/block/<number>` |
|
||||
| Blocks | `/blocks` |
|
||||
| Transactions | `/transactions` |
|
||||
| Bridge | `/bridge` |
|
||||
| WETH | `/weth` |
|
||||
| Watchlist | `/watchlist` |
|
||||
| MetaMask Snap | `/snap/` |
|
||||
|
||||
## Proxy 301 Note
|
||||
|
||||
If `https://explorer.d-bis.org/address/0x...` returns 301, the proxy (NPMplus/Cloudflare) may need configuration. The VM nginx serves the SPA correctly. Workaround: use `#/address/0x...` or access via LAN.
|
||||
104
docs/EXPLORER_LOADING_TROUBLESHOOTING.md
Normal file
104
docs/EXPLORER_LOADING_TROUBLESHOOTING.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# Explorer "Loading…" / "—" Troubleshooting
|
||||
|
||||
When **`/api/v2/stats`** returns 200 with data but the SPA still shows "—" or "Loading blocks…" / "Loading transactions…" / "Loading bridge data…" / "Tokens: Loading…", the failure is in **frontend→API wiring** or **frontend runtime**.
|
||||
|
||||
## Expected UI (screenshots)
|
||||
|
||||
When the SPA and API are working, the home page shows stats, Gas & Network values, and populated Latest Blocks and Latest Transactions. Reference screenshots (mockups; replace with live captures from https://explorer.d-bis.org/ if desired):
|
||||
|
||||
| View | Image |
|
||||
|------|--------|
|
||||
| Home |  |
|
||||
| Blocks list |  |
|
||||
| Transactions list |  |
|
||||
|
||||
See [docs/images/README.md](../../docs/images/README.md) for how to capture and replace with real screenshots.
|
||||
|
||||
---
|
||||
|
||||
## Do-now checks (fastest to isolate)
|
||||
|
||||
### 1. Browser DevTools on https://explorer.d-bis.org/
|
||||
|
||||
- **Console:** Look for the **first** JS error (red). It usually explains why rendering stopped (e.g. CORS, parse error, missing field).
|
||||
- **Network:** Filter by `api`. Confirm:
|
||||
- `/api/v2/stats` → **200**
|
||||
- `/api/v2/blocks?page=1&page_size=10` → **200**
|
||||
- `/api/v2/transactions?page=1&page_size=10` → **200**
|
||||
- Any **bridge** or **tokens** URL the SPA calls → **200** (not 404/502/CORS).
|
||||
|
||||
If any of these return 4xx/5xx or (failed) CORS, the fix is nginx/upstream or CORS. If all are 200 but the UI still shows "Loading…", the fix is in the SPA (parsing or DOM update).
|
||||
|
||||
### 2. Shell: confirm these endpoints respond
|
||||
|
||||
From any host that can reach the explorer:
|
||||
|
||||
```bash
|
||||
# Stats (you already confirmed this works)
|
||||
curl -sS -o /dev/null -w "%{http_code}" "https://explorer.d-bis.org/api/v2/stats"
|
||||
# Blocks
|
||||
curl -sS -o /dev/null -w "%{http_code}" "https://explorer.d-bis.org/api/v2/blocks?page=1&page_size=10"
|
||||
# Transactions
|
||||
curl -sS -o /dev/null -w "%{http_code}" "https://explorer.d-bis.org/api/v2/transactions?page=1&page_size=10"
|
||||
# Tokens (Blockscout v2)
|
||||
curl -sS -o /dev/null -w "%{http_code}" "https://explorer.d-bis.org/api/v2/tokens?page=1&page_size=10"
|
||||
```
|
||||
|
||||
Expect **200** for each. Bridge monitoring in the SPA uses the same Blockscout API (addresses for bridge contracts); there is no separate "bridge endpoint" other than address/contract pages.
|
||||
|
||||
### 3. Nginx logs (on VMID 5000)
|
||||
|
||||
Check that requests to blocks/transactions are proxied and not 502:
|
||||
|
||||
```bash
|
||||
# On Proxmox host with VMID 5000
|
||||
pct exec 5000 -- tail -n 50 /var/log/nginx/blockscout-access.log | grep -E "v2/blocks|v2/transactions|v2/stats"
|
||||
pct exec 5000 -- tail -n 30 /var/log/nginx/blockscout-error.log
|
||||
```
|
||||
|
||||
Look for 502 (Blockscout down), 404 (wrong path), or upstream timeouts.
|
||||
|
||||
## What was changed in the SPA (to reduce "Loading…")
|
||||
|
||||
- **API base:** The SPA now uses **relative `/api`** when the page is served from the explorer host (`explorer.d-bis.org` or `192.168.11.140`). So all requests (stats, blocks, transactions, tokens, bridge-related address pages) go to the **same host** that served the page, avoiding CORS or origin mismatch (e.g. www vs non-www, or proxy changing the origin).
|
||||
- **Transactions URL:** For Chain 138 the transactions request was updated from `/v2/transactions?filter=to&page=1&page_size=10` to `/v2/transactions?page=1&page_size=10` (removed `filter=to`) to avoid Blockscout rejecting or returning unexpected results.
|
||||
- **Cache-busting:** `index.html` loads the SPA with `explorer-spa.js?v=2` so browsers fetch the updated script after deploy instead of using a cached copy.
|
||||
- **Config reference:** SPA is nginx on VMID 5000, API is `location /api` → `proxy_pass http://127.0.0.1:4000` (Blockscout). Chain ID 138, RPC as in [EXPLORER_METAMASK_TECHNICAL_RESPONSE.md](../../docs/04-configuration/EXPLORER_METAMASK_TECHNICAL_RESPONSE.md).
|
||||
|
||||
## Deploying the SPA fix
|
||||
|
||||
After editing `frontend/public/explorer-spa.js`, redeploy the frontend to VMID 5000 so the change is live:
|
||||
|
||||
```bash
|
||||
# From repo root (with SSH to r630-02)
|
||||
EXPLORER_VM_HOST=root@192.168.11.12 bash explorer-monorepo/scripts/deploy-frontend-to-vmid5000.sh
|
||||
```
|
||||
|
||||
Or from the Proxmox host that runs VMID 5000:
|
||||
|
||||
```bash
|
||||
/path/to/repo/explorer-monorepo/scripts/deploy-frontend-to-vmid5000.sh
|
||||
```
|
||||
|
||||
Then hard-refresh the explorer (Ctrl+Shift+R / Cmd+Shift+R) and re-check Console + Network.
|
||||
|
||||
## Exact API URLs the SPA calls (for DevTools → Network)
|
||||
|
||||
When the page is served from `https://explorer.d-bis.org`, the SPA uses **relative** `/api` (no origin). These are the exact URLs to check in the Network tab:
|
||||
|
||||
| Widget / feature | Method | URL |
|
||||
|------------------|--------|-----|
|
||||
| **Stats (Total Blocks, etc.)** | GET | `/api/v2/stats` |
|
||||
| **Gas & Network** | GET | `/api/v2/blocks?page=1&page_size=20` |
|
||||
| | GET | `/api/v2/stats` |
|
||||
| | GET | `/api/v2/transactions?page=1&page_size=100` |
|
||||
| **Latest Blocks** | GET | `/api/v2/blocks?page=1&page_size=10` |
|
||||
| **Latest Transactions** | GET | `/api/v2/transactions?page=1&page_size=10` |
|
||||
| **Tokens (list)** | GET | `/api/v2/tokens?page=1&page_size=100` |
|
||||
| **Bridge Monitoring** | — | No API call; content is static HTML. If it stays "Loading bridge data…", a JS error may prevent `refreshBridgeData()` from running. |
|
||||
|
||||
If any of these return non-200 or (failed) CORS, that’s the failing path. If all return 200 but the UI still shows "Loading…", the issue is in the SPA (e.g. parsing, DOM update, or an exception after fetch).
|
||||
|
||||
## If it still shows "Loading…"
|
||||
|
||||
Paste (a) the **first console error** and (b) the **failing API request URL + status code** from the Network tab. With that, the fix can be narrowed to: nginx rule, SPA code, or Blockscout route/response shape.
|
||||
@@ -102,7 +102,8 @@ CHAIN138_ETHERSCAN_API_KEY=
|
||||
# ETHEREUM MAINNET CONFIGURATION
|
||||
# =============================================================================
|
||||
# RPC Configuration
|
||||
ETHEREUM_MAINNET_RPC=https://43b945b33d58463a9246cf5ca8aa6286:SdwChVo+UbIAamFy3ptxnOP5bCVCYX4ey7TKiYTQWdZGeUzI66fi9g@mainnet.infura.io/v3/43b945b33d58463a9246cf5ca8aa6286
|
||||
ETHEREUM_MAINNET_RPC=https://mainnet.infura.io/v3/<INFURA_PROJECT_ID>
|
||||
# With Basic Auth: https://<INFURA_PROJECT_ID>:<INFURA_PROJECT_SECRET>@mainnet.infura.io/v3/<INFURA_PROJECT_ID>
|
||||
ETH_MAINNET_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY
|
||||
|
||||
# CCIP Configuration (Ethereum Mainnet)
|
||||
@@ -263,15 +264,15 @@ GNOSISSCAN_API_KEY=89HVZNN68DWKWVZHQRGQJ1B74FGKWBJV1W
|
||||
# =============================================================================
|
||||
# METAMASK & INFURA CONFIGURATION
|
||||
# =============================================================================
|
||||
METAMASK_API_KEY=43b945b33d58463a9246cf5ca8aa6286
|
||||
METAMASK_SECRET=SdwChVo+UbIAamFy3ptxnOP5bCVCYX4ey7TKiYTQWdZGeUzI66fi9g
|
||||
INFURA_GAS_API=https://gas.api.infura.io/v3/43b945b33d58463a9246cf5ca8aa6286
|
||||
METAMASK_API_KEY=<INFURA_PROJECT_ID>
|
||||
METAMASK_SECRET=<INFURA_PROJECT_SECRET>
|
||||
INFURA_GAS_API=https://gas.api.infura.io/v3/<INFURA_PROJECT_ID>
|
||||
|
||||
# =============================================================================
|
||||
# WALLET & SECURITY CONFIGURATION
|
||||
# =============================================================================
|
||||
# ⚠️ WARNING: This private key should be stored securely and not committed to version control
|
||||
PRIVATE_KEY=0x5373d11ee2cad4ed82b9208526a8c358839cbfe325919fb250f062a25153d1c8
|
||||
PRIVATE_KEY=0x... # NEVER commit; use .env
|
||||
|
||||
# Multisig Configuration (Placeholders - to be configured)
|
||||
MULTISIG_OWNER_1=""
|
||||
|
||||
20
docs/PRODUCTION_CHECKLIST.md
Normal file
20
docs/PRODUCTION_CHECKLIST.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Production Checklist
|
||||
|
||||
Before running the Explorer API and indexer in production:
|
||||
|
||||
1. **Set a strong `JWT_SECRET`**
|
||||
Do not use the placeholder from the env template. Generate a secure value, e.g.:
|
||||
```bash
|
||||
export JWT_SECRET=$(openssl rand -hex 32)
|
||||
```
|
||||
See `deployment/ENVIRONMENT_TEMPLATE.env` for all required variables.
|
||||
|
||||
2. **Run database migrations**
|
||||
Apply migrations before starting the API and indexer, e.g.:
|
||||
```bash
|
||||
psql -U explorer -d explorer -f backend/database/migrations/0010_track_schema.up.sql
|
||||
```
|
||||
Or use your migration runner (e.g. `go run backend/database/migrations/migrate.go --up` if applicable).
|
||||
|
||||
3. **Configure DB and RPC**
|
||||
Ensure `DB_*`, `RPC_URL`, `WS_URL`, and `CHAIN_ID` are set correctly for the target environment.
|
||||
285
docs/REUSABLE_COMPONENTS_EXTRACTION_PLAN.md
Normal file
285
docs/REUSABLE_COMPONENTS_EXTRACTION_PLAN.md
Normal file
@@ -0,0 +1,285 @@
|
||||
# Reusable Components Extraction Plan
|
||||
|
||||
**Completion status (in-repo):** All libs are present under `backend/libs/` and `frontend/libs/`. Backend is wired to use **go-pgconfig** (API + indexer), **go-rpc-gateway** (Track 1). Frontend is wired to use **frontend-api-client** (services/api/client) and **frontend-ui-primitives** (all pages using Card, Table, Address). CI uses `submodules: recursive`; README documents clone with submodules. To publish as separate repos, copy each lib to its own repo and add as submodule.
|
||||
|
||||
**Review and test:** Backend handlers that need the DB use `requireDB(w)`; without a DB they return 503. Tests run with a nil DB and accept 200/503/404 as appropriate. Run backend tests: `go test ./...` in `backend/`. Frontend build: `npm run build` in `frontend/` (ESLint uses root `.eslintrc.cjs` and frontend `"root": true` in `.eslintrc.json`). E2E: `npm run e2e` from repo root (Playwright, default base URL https://explorer.d-bis.org; set `EXPLORER_URL` for local).
|
||||
|
||||
---
|
||||
|
||||
**Goal:** Extract reusable, non–Explorer-specific components into their own repositories under `/home/intlc/projects`, and link them back to this monorepo via **git submodules** using best practices.
|
||||
|
||||
**Scope:** Components that are generic (EVM/chain-agnostic, multi-tenant, or generic UI/infra) are candidates. Explorer-specific logic (Chain 138 routes, Blockscout integration, explorer branding) stays in `explorer-monorepo`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Reusable vs Explorer-Specific (Summary)
|
||||
|
||||
| Category | Reusable (extract) | Explorer-specific (keep in monorepo) |
|
||||
|--------|---------------------|--------------------------------------|
|
||||
| **Backend Go** | Bridge/swap aggregators, chain adapters, DB config, wallet auth + tiered access, logging/metrics, generic cache/rate-limit, security middleware (generic part) | REST routes, track* endpoints, indexer (block/processor), Blockscout/etherscan compat, explorer API server |
|
||||
| **Frontend** | Button, Card, Table, generic API client, optional Address (minimal) | Explorer pages, block/tx/address views, SPA `index.html`, explorer API calls |
|
||||
| **Deployment** | Nginx/systemd/Cloudflare/fail2ban templates, generic verify scripts | Explorer deploy scripts, VMID 5000 / Blockscout-specific fixes |
|
||||
| **Docs** | — | All current docs are explorer/deployment-specific |
|
||||
|
||||
---
|
||||
|
||||
## 2. Proposed New Repositories (under `/home/intlc/projects`)
|
||||
|
||||
All new repos live as siblings of `proxmox/explorer-monorepo`, e.g.:
|
||||
|
||||
- `/home/intlc/projects/go-bridge-aggregator`
|
||||
- `/home/intlc/projects/go-chain-adapters`
|
||||
- `/home/intlc/projects/go-pgconfig`
|
||||
- `/home/intlc/projects/go-tiered-auth`
|
||||
- `/home/intlc/projects/go-http-middleware`
|
||||
- `/home/intlc/projects/go-logging`
|
||||
- `/home/intlc/projects/go-rpc-gateway`
|
||||
- `/home/intlc/projects/frontend-ui-primitives`
|
||||
- `/home/intlc/projects/deployment-common`
|
||||
|
||||
Relationship to monorepo: **submodules** inside `explorer-monorepo` (e.g. `backend/vendor/go-bridge-aggregator` or `libs/go-bridge-aggregator`), so the monorepo stays the single checkout for development and CI.
|
||||
|
||||
---
|
||||
|
||||
## 3. Repository-by-Repository Plan
|
||||
|
||||
### 3.1 `go-bridge-aggregator`
|
||||
|
||||
- **Purpose:** Multi-provider bridge quote aggregation (chain-agnostic interface + implementations).
|
||||
- **Source in monorepo:** `backend/bridge/` (all providers: `providers.go`, `ccip_provider.go`, `lifi_provider.go`, `socket_provider.go`, `squid_provider.go`, `symbiosis_provider.go`, `relay_provider.go`, `stargate_provider.go`, `hop_provider.go`).
|
||||
- **Reusability:** Provider interface, `BridgeRequest`/`BridgeQuote`/`BridgeStep`, `Aggregator`, `GetBestQuote`. Chain IDs and integrator names should be config (env or struct), not hardcoded 138.
|
||||
- **New repo path:** `/home/intlc/projects/go-bridge-aggregator`.
|
||||
- **Suggested layout:** `go.mod` (module e.g. `github.com/yourorg/go-bridge-aggregator`), `provider.go`, `aggregator.go`, `providers/` (one file per provider). Dependencies: minimal (HTTP client, context).
|
||||
- **Explorer coupling:** Explorer will depend on this module via Go module (or submodule + replace). CCIP “138 <-> 1” and integrator strings become config in explorer.
|
||||
|
||||
---
|
||||
|
||||
### 3.2 `go-chain-adapters`
|
||||
|
||||
- **Purpose:** Chain abstraction for EVM-compatible chains (block, tx, receipt, balance, code, gas).
|
||||
- **Source:** `backend/chain/adapters/evm.go` (interface `ChainAdapter` + `EVMAdapter`).
|
||||
- **Reusability:** No explorer references; only `go-ethereum`.
|
||||
- **New repo path:** `/home/intlc/projects/go-chain-adapters`.
|
||||
- **Suggested layout:** `go.mod`, `adapter.go` (interface), `evm/evm.go`. Other chains (e.g. non-EVM) can be added later in same repo.
|
||||
- **Explorer coupling:** Explorer indexer and API use chain adapter; import this module.
|
||||
|
||||
---
|
||||
|
||||
### 3.3 `go-pgconfig`
|
||||
|
||||
- **Purpose:** Load PostgreSQL configuration from environment and build `pgxpool.Config`.
|
||||
- **Source:** `backend/database/config/database.go` (and optionally read-replica).
|
||||
- **Reusability:** No explorer references; only `pgx` and `os`.
|
||||
- **New repo path:** `/home/intlc/projects/go-pgconfig`.
|
||||
- **Suggested layout:** `go.mod`, `config.go` (DatabaseConfig, LoadDatabaseConfig, ConnectionString, PoolConfig, ReadReplicaConfig).
|
||||
- **Explorer coupling:** Explorer `api/rest/cmd/main.go` and indexer use DB config; import this module.
|
||||
|
||||
---
|
||||
|
||||
### 3.4 `go-tiered-auth`
|
||||
|
||||
- **Purpose:** Tiered (track) access: wallet-based auth (nonce + JWT), optional “tier” level, and feature access by tier.
|
||||
- **Source:** `backend/auth/` (auth.go, roles.go, wallet_auth.go), `backend/featureflags/flags.go`, and the auth/track parts of `backend/api/middleware/auth.go`.
|
||||
- **Reusability:** Wallet nonce + JWT and “tier” (track) are generic; feature names in `featureflags` can be default map, overridable by consumer. Middleware uses `auth` + `featureflags`; can live in this repo or in `go-http-middleware` with dependency on this repo.
|
||||
- **New repo path:** `/home/intlc/projects/go-tiered-auth`.
|
||||
- **Suggested layout:** `go.mod`, `auth/` (wallet_auth, nonce storage interface), `featureflags/` (HasAccess, GetEnabledFeatures, configurable feature map), `middleware/` (RequireAuth, RequireTier, OptionalAuth). DB tables (e.g. `wallet_nonces`, `operator_roles`) stay defined in explorer migrations; this repo only needs interfaces (e.g. NonceStore, TierResolver).
|
||||
- **Explorer coupling:** Explorer implements storage (existing DB); middleware and WalletAuth stay in explorer but can call into this lib for validation and JWT. Alternatively, move full WalletAuth + middleware here and pass DB and feature map from explorer.
|
||||
|
||||
---
|
||||
|
||||
### 3.5 `go-http-middleware`
|
||||
|
||||
- **Purpose:** Generic HTTP middleware: security headers (CSP, X-Frame-Options, etc.), CORS, compression, logging. No explorer URLs.
|
||||
- **Source:** `backend/api/middleware/security.go` (generic headers only; CSP `connect-src` etc. are explorer-specific and should be supplied by explorer or config).
|
||||
- **Reusability:** Security headers and CORS are generic; CSP should be a parameter or callback.
|
||||
- **New repo path:** `/home/intlc/projects/go-http-middleware`.
|
||||
- **Suggested layout:** `go.mod`, `security.go` (AddSecurityHeaders with configurable CSP), `cors.go` if extracted, `logging.go` if request logging is extracted. Explorer passes CSP string when wiring middleware.
|
||||
- **Explorer coupling:** Explorer server uses this middleware with explorer-specific CSP.
|
||||
|
||||
---
|
||||
|
||||
### 3.6 `go-logging`
|
||||
|
||||
- **Purpose:** Structured logging (context, fields, levels).
|
||||
- **Source:** `backend/logging/logger.go`.
|
||||
- **Reusability:** No explorer references.
|
||||
- **New repo path:** `/home/intlc/projects/go-logging`.
|
||||
- **Suggested layout:** `go.mod`, `logger.go`. Optional: integrate with a standard logger interface (e.g. slog) for compatibility.
|
||||
- **Explorer coupling:** Optional; explorer can keep using it or switch to stdlib/slog and deprecate this in monorepo.
|
||||
|
||||
---
|
||||
|
||||
### 3.7 `go-rpc-gateway`
|
||||
|
||||
- **Purpose:** Generic RPC gateway: in-memory (and optionally Redis) cache, in-memory (and optionally Redis) rate limiter, and a generic HTTP proxy to an upstream RPC URL. No route definitions or explorer semantics.
|
||||
- **Source:** `backend/api/track1/cache.go`, `redis_cache.go`, `rate_limiter.go`, `redis_rate_limiter.go`, `rpc_gateway.go`. Exclude `endpoints.go` (explorer-specific handlers).
|
||||
- **Reusability:** Cache and rate limiter are generic; RPC gateway is “forward request to RPC URL with cache and rate limit.”
|
||||
- **New repo path:** `/home/intlc/projects/go-rpc-gateway`.
|
||||
- **Suggested layout:** `go.mod`, `cache/` (memory + Redis), `ratelimit/` (memory + Redis), `gateway.go` (proxy to single upstream). Explorer track1 endpoints call this gateway and format responses (e.g. chain_id 138).
|
||||
- **Explorer coupling:** Explorer imports gateway + cache + ratelimit; track1 endpoints remain in explorer and use this package.
|
||||
|
||||
---
|
||||
|
||||
### 3.8 `frontend-ui-primitives`
|
||||
|
||||
- **Purpose:** Reusable React UI components: Button, Card, Table. Optionally a minimal Address (truncate + copy) without explorer-specific links.
|
||||
- **Source:** `frontend/src/components/common/Button.tsx`, `Card.tsx`, `Table.tsx`; optionally `frontend/src/components/blockchain/Address.tsx` (strip explorer-specific links/props if any).
|
||||
- **Reusability:** No explorer API or routes; only Tailwind + clsx + React. Table is generic; Address can be “display + copy” only.
|
||||
- **New repo path:** `/home/intlc/projects/frontend-ui-primitives`.
|
||||
- **Suggested layout:** npm package (e.g. `@yourorg/ui-primitives`). Structure: `src/Button.tsx`, `Card.tsx`, `Table.tsx`, `Address.tsx`; export from `index.ts`; build with tsup or similar; peer deps: `react`, `clsx`. Tailwind: consumer app includes Tailwind and uses same class names, or package ships minimal CSS.
|
||||
- **Explorer coupling:** Explorer frontend adds dependency (npm package or git submodule + workspace). If submodule: e.g. `frontend/libs/ui-primitives` and in package.json `"@yourorg/ui-primitives": "file:./libs/frontend-ui-primitives"`.
|
||||
|
||||
---
|
||||
|
||||
### 3.9 `frontend-api-client` (optional)
|
||||
|
||||
- **Purpose:** Generic API client: axios instance, interceptors, optional API key from storage, typed `ApiResponse<T>` and error shape.
|
||||
- **Source:** `frontend/src/services/api/client.ts` (and possibly a minimal `types.ts` for ApiResponse/ApiError).
|
||||
- **Reusability:** No explorer endpoints; base URL and headers are config.
|
||||
- **New repo path:** `/home/intlc/projects/frontend-api-client`.
|
||||
- **Suggested layout:** npm package exporting `createApiClient(baseURL, options?)` and types. Explorer uses `createApiClient(process.env.NEXT_PUBLIC_API_URL)` and keeps explorer-specific API modules (blocks, addresses, transactions) in monorepo.
|
||||
- **Explorer coupling:** Explorer depends on this package; explorer-specific services import client from package and define endpoints locally.
|
||||
|
||||
---
|
||||
|
||||
### 3.10 `deployment-common`
|
||||
|
||||
- **Purpose:** Reusable deployment and ops snippets: nginx (generic reverse proxy, SSL, `location /api/` template), systemd unit templates, Cloudflare Tunnel sample config, fail2ban jail/config, and small generic “verify” scripts (e.g. curl health, check port).
|
||||
- **Source:** `deployment/` – extract generic parts of `setup-nginx.sh`, `systemd/*.service`, `cloudflare/tunnel-config.yml`, `fail2ban/`. Omit explorer-specific env (VMID 5000, Blockscout, explorer.d-bis.org) or make them placeholders.
|
||||
- **Reusability:** No explorer branding or VMIDs; only patterns (proxy to backend, systemd, tunnel, fail2ban).
|
||||
- **New repo path:** `/home/intlc/projects/deployment-common`.
|
||||
- **Suggested layout:** `nginx/`, `systemd/`, `cloudflare/`, `fail2ban/`, `scripts/` (e.g. verify-http-endpoint.sh). README with usage and variable placeholders.
|
||||
- **Explorer coupling:** Explorer’s `deployment/` can include this repo as submodule (e.g. `deployment/common`) and copy or symlink templates, or reference them from docs.
|
||||
|
||||
---
|
||||
|
||||
## 4. Submodule Strategy (Best Practices)
|
||||
|
||||
- **Location of submodules:** Prefer a single directory for “vendored” or “lib” submodules to avoid clutter, e.g.:
|
||||
- **Option A:** `explorer-monorepo/libs/` with one submodule per repo (`libs/go-bridge-aggregator`, `libs/frontend-ui-primitives`, etc.).
|
||||
- **Option B:** Backend libs under `backend/libs/` and frontend under `frontend/libs/` (so Go and Node resolve paths naturally).
|
||||
- **Recommendation:** Use **Option B** for simpler Go/Node resolution:
|
||||
- `backend/libs/go-bridge-aggregator`, `backend/libs/go-chain-adapters`, `backend/libs/go-pgconfig`, `backend/libs/go-tiered-auth`, `backend/libs/go-http-middleware`, `backend/libs/go-logging`, `backend/libs/go-rpc-gateway`.
|
||||
- `frontend/libs/frontend-ui-primitives` (and optionally `frontend/libs/frontend-api-client`).
|
||||
- `deployment/common` → `deployment-common` (or `deployment-common` at repo root if you prefer).
|
||||
|
||||
- **Adding a submodule (example):**
|
||||
```bash
|
||||
cd /home/intlc/projects/proxmox/explorer-monorepo
|
||||
git submodule add -b main https://github.com/yourorg/go-bridge-aggregator.git backend/libs/go-bridge-aggregator
|
||||
```
|
||||
Use SSH or HTTPS consistently; pin to a branch or tag (e.g. `main` or `v0.1.0`).
|
||||
|
||||
- **Go modules:** In explorer’s `backend/go.mod`, use `replace` to point at the local submodule during development:
|
||||
```go
|
||||
replace github.com/yourorg/go-bridge-aggregator => ./libs/go-bridge-aggregator
|
||||
```
|
||||
CI and contributors run `go mod tidy`; when publishing the library, depend on the published module version and remove `replace` for release.
|
||||
|
||||
- **Clone/update instructions:** Document in root README:
|
||||
```bash
|
||||
git clone --recurse-submodules <explorer-monorepo-url>
|
||||
# or after clone:
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
- **Publishing:** When a reusable repo is stable, publish it (Go: tag and push to GitHub; npm: publish to npm or private registry). Explorer can then depend on versioned releases and only use submodules for active development or private forks.
|
||||
|
||||
---
|
||||
|
||||
## 5. Phased Extraction Order
|
||||
|
||||
To minimize breakage and respect dependencies:
|
||||
|
||||
1. **Phase 1 – No dependency on other extracted pieces**
|
||||
- `go-pgconfig` (used by api + indexer)
|
||||
- `go-logging`
|
||||
- `go-chain-adapters`
|
||||
- `go-bridge-aggregator` (make chain IDs/config injectable)
|
||||
- `frontend-ui-primitives`
|
||||
- `deployment-common` (templates only)
|
||||
|
||||
2. **Phase 2 – May depend on Phase 1**
|
||||
- `go-rpc-gateway` (cache + rate limit + gateway; no dependency on auth)
|
||||
- `go-http-middleware` (security headers only)
|
||||
- `go-tiered-auth` (auth + featureflags + optional middleware; depends on DB interface, so explorer keeps DB)
|
||||
- `frontend-api-client` (optional)
|
||||
|
||||
3. **Phase 3 – Integration in explorer**
|
||||
- Replace internal packages with submodule or published module references.
|
||||
- Update explorer `backend/go.mod` and `frontend/package.json`.
|
||||
- Keep explorer-specific code (routes, indexer, Blockscout, SPA) in monorepo; ensure tests and CI pass.
|
||||
|
||||
---
|
||||
|
||||
## 6. What Stays in Explorer Monorepo
|
||||
|
||||
- **Backend:** All REST route handlers, track* endpoint logic, indexer (listener + processor + backfill), Blockscout/etherscan compatibility, explorer-specific config (chain_id 138, RPC URLs), and migrations (schema stays here; libs use interfaces or config).
|
||||
- **Frontend:** All pages and views, `public/index.html` SPA, explorer API service modules (blocks, transactions, addresses), Next.js app and deployment config.
|
||||
- **Deployment:** All explorer- and VMID 5000–specific scripts (`fix-502-blockscout.sh`, `complete-explorer-api-access.sh`, `deploy-frontend-to-vmid5000.sh`, etc.), and nginx/config that reference explorer.d-bis.org and Blockscout.
|
||||
- **Docs:** All current documentation (API access, deployment, runbook, etc.).
|
||||
|
||||
---
|
||||
|
||||
## 7. Checklist for Each New Repo
|
||||
|
||||
- [ ] Create repo under `/home/intlc/projects/<repo-name>` (or under GitHub/GitLab first, then clone there).
|
||||
- [ ] Add minimal `README.md`, `LICENSE`, and `.gitignore`.
|
||||
- [ ] Copy only the reusable code; remove explorer-specific constants or make them config.
|
||||
- [ ] Add `go.mod` / `package.json` with correct module/package name.
|
||||
- [ ] Add tests where feasible (e.g. cache, rate limiter, chain adapter).
|
||||
- [ ] Add to explorer-monorepo as submodule in chosen path (`backend/libs/...` or `frontend/libs/...` or `deployment/common`).
|
||||
- [ ] Update explorer to use the new module (replace directives or npm dependency).
|
||||
- [ ] Document in explorer README that submodules are required (`git clone --recurse-submodules`).
|
||||
|
||||
---
|
||||
|
||||
## 8. Submodule Best Practices (`.gitmodules` and clone)
|
||||
|
||||
- **One submodule = one entry in `.gitmodules`.** After adding submodules, the file will look like:
|
||||
```ini
|
||||
[submodule "backend/libs/go-bridge-aggregator"]
|
||||
path = backend/libs/go-bridge-aggregator
|
||||
url = https://github.com/yourorg/go-bridge-aggregator.git
|
||||
branch = main
|
||||
```
|
||||
- **Use a consistent base URL** (SSH or HTTPS) for all submodules so clones work without reconfiguring.
|
||||
- **Prefer `branch = main`** (or your default branch) so `git submodule update --remote` pulls the right branch; for releases you can pin by committing the submodule at a specific tag.
|
||||
- **Clone explorer-monorepo with submodules (first time):**
|
||||
```bash
|
||||
cd /home/intlc/projects
|
||||
git clone --recurse-submodules <explorer-monorepo-url> proxmox/explorer-monorepo
|
||||
```
|
||||
- **Existing clone – init and update submodules:**
|
||||
```bash
|
||||
cd /home/intlc/projects/proxmox/explorer-monorepo
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
- **Add a new submodule (example for local repo under projects):**
|
||||
```bash
|
||||
cd /home/intlc/projects/proxmox/explorer-monorepo
|
||||
git submodule add -b main ../go-bridge-aggregator backend/libs/go-bridge-aggregator
|
||||
```
|
||||
Or with a remote URL:
|
||||
```bash
|
||||
git submodule add -b main https://github.com/yourorg/go-bridge-aggregator.git backend/libs/go-bridge-aggregator
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Quick Reference: Repo Paths and Submodule Paths
|
||||
|
||||
| New repo (under `/home/intlc/projects`) | Suggested submodule path in explorer-monorepo |
|
||||
|----------------------------------------|------------------------------------------------|
|
||||
| `go-bridge-aggregator` | `backend/libs/go-bridge-aggregator` |
|
||||
| `go-chain-adapters` | `backend/libs/go-chain-adapters` |
|
||||
| `go-pgconfig` | `backend/libs/go-pgconfig` |
|
||||
| `go-tiered-auth` | `backend/libs/go-tiered-auth` |
|
||||
| `go-http-middleware` | `backend/libs/go-http-middleware` |
|
||||
| `go-logging` | `backend/libs/go-logging` |
|
||||
| `go-rpc-gateway` | `backend/libs/go-rpc-gateway` |
|
||||
| `frontend-ui-primitives` | `frontend/libs/frontend-ui-primitives` |
|
||||
| `frontend-api-client` | `frontend/libs/frontend-api-client` |
|
||||
| `deployment-common` | `deployment/common` |
|
||||
|
||||
This plan keeps Explorer-specific behavior in the monorepo while moving generic building blocks into separate, reusable repos linked via submodules and optional published modules.
|
||||
81
docs/RPC_FUNCTIONALITY_AND_BLOCKSCOUT_TRACE.md
Normal file
81
docs/RPC_FUNCTIONALITY_AND_BLOCKSCOUT_TRACE.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# RPC Functionality and Blockscout Trace
|
||||
|
||||
## Summary
|
||||
|
||||
- **Routing**: VMID 5000 (Blockscout) → public RPC 192.168.11.221:8545 (VMID 2201) is correct; same LAN (192.168.11.0/24), no routing issues.
|
||||
- **Basic RPC**: `eth_blockNumber`, `eth_chainId`, and standard ETH/NET/WEB3 methods work on the public RPC.
|
||||
- **Internal transactions / block rewards**: Blockscout requires the **TRACE** API. The public RPC node was configured with `rpc-http-api=["ETH","NET","WEB3"]` only, so `trace_block` and `trace_replayBlockTransactions` returned **"Method not enabled" (-32604)**. **Fix applied:** TRACE was added to `/etc/besu/config-rpc-public.toml` on VMID 2201 and Besu restarted; `trace_block` now returns a result.
|
||||
|
||||
## Checks performed
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| `eth_blockNumber` from host to 192.168.11.221:8545 | OK |
|
||||
| `eth_blockNumber` from VMID 5000 to 192.168.11.221:8545 | OK (routing fine) |
|
||||
| `eth_chainId` on public RPC | OK (0x8a = 138) |
|
||||
| `trace_block` on public RPC | Method not enabled (TRACE not in rpc-http-api) |
|
||||
| `debug_traceBlockByNumber` on public RPC | Method not enabled |
|
||||
|
||||
## Routing
|
||||
|
||||
- **Blockscout (VMID 5000)**: IP 192.168.11.140, host r630-02 (192.168.11.12).
|
||||
- **Public RPC (VMID 2201)**: IP 192.168.11.221, host r630-02 (192.168.11.12). Same host as VMID 5000.
|
||||
- Traffic is host-to-host on 192.168.11.0/24; no firewall or NAT between them in normal setup.
|
||||
|
||||
## Fix: Enable TRACE on the public RPC node (VMID 2201)
|
||||
|
||||
Blockscout uses [trace_block and trace_replayBlockTransactions](https://docs.blockscout.com/setup/requirements/node-tracing-json-rpc-requirements) for internal transactions and block rewards. Besu exposes these when the **TRACE** API is enabled.
|
||||
|
||||
### 1. Config templates (already updated in repo)
|
||||
|
||||
- **smom-dbis-138-proxmox/templates/besu-configs/config-rpc.toml**: `rpc-http-api` and `rpc-ws-api` now include `"TRACE"`.
|
||||
- **smom-dbis-138/config/config-rpc-public.toml**: `rpc-http-api` now includes `"TRACE"`.
|
||||
|
||||
Use these for new or redeployed nodes.
|
||||
|
||||
### 2. Live node (VMID 2201)
|
||||
|
||||
On the **Proxmox host that runs VMID 2201** (r630-02 / 192.168.11.12):
|
||||
|
||||
1. **Locate Besu config** inside the container. The `besu-rpc.service` on VMID 2201 uses **`/etc/besu/config-rpc-public.toml`** (see `ExecStart` in the unit). Other nodes may use `config-rpc.toml` or `config.toml`.
|
||||
|
||||
2. **Add TRACE** to the RPC APIs. In the config file, change:
|
||||
- `rpc-http-api=["ETH","NET","WEB3"]` → `rpc-http-api=["ETH","NET","WEB3","TRACE"]`
|
||||
- If present: `rpc-ws-api=["ETH","NET","WEB3"]` → `rpc-ws-api=["ETH","NET","WEB3","TRACE"]`
|
||||
|
||||
3. **Restart Besu** in the container:
|
||||
```bash
|
||||
pct exec 2201 -- systemctl restart besu-rpc
|
||||
# or whatever the Besu service name is, e.g. besu
|
||||
```
|
||||
|
||||
4. **Verify** (from any host that can reach 192.168.11.221):
|
||||
```bash
|
||||
curl -sS -X POST -H "Content-Type: application/json" \
|
||||
--data '{"jsonrpc":"2.0","method":"trace_block","params":["0x1"],"id":1}' \
|
||||
http://192.168.11.221:8545
|
||||
```
|
||||
You should get a JSON result (or an empty array for block 1), not `"Method not enabled"`.
|
||||
|
||||
### 3. Script (recommended)
|
||||
|
||||
From repo root (VMID 2201 is on r630-02; script uses `RPC_VM_2201_HOST=root@192.168.11.12` by default):
|
||||
|
||||
```bash
|
||||
bash scripts/besu/enable-trace-api-vmid2201.sh
|
||||
```
|
||||
|
||||
The script finds the Besu config in the container, adds TRACE to `rpc-http-api` and `rpc-ws-api`, restarts Besu, and verifies `trace_block`. Or follow the manual steps in §2 and verify with the curl in §2 step 4.
|
||||
|
||||
## After enabling TRACE
|
||||
|
||||
- Blockscout will stop logging "Method not enabled" for internal transaction and block-reward fetchers (after it retries).
|
||||
- Internal transactions and block rewards will index over time.
|
||||
- No change to Blockscout env: it already points at `ETHEREUM_JSONRPC_HTTP_URL=http://192.168.11.221:8545`.
|
||||
|
||||
## References
|
||||
|
||||
- [Blockscout: Node tracing / JSON RPC requirements](https://docs.blockscout.com/setup/requirements/node-tracing-json-rpc-requirements)
|
||||
- [Besu TRACE API](https://besu.hyperledger.org/public-networks/reference/api)
|
||||
- `config/ip-addresses.conf`: `RPC_PUBLIC_1`, `RPC_URL_138_PUBLIC`
|
||||
- `docs/04-configuration/RPC_ENDPOINTS_MASTER.md`
|
||||
39
docs/WHY_INFO_NOT_LOADING.md
Normal file
39
docs/WHY_INFO_NOT_LOADING.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Why Is No Explorer Data Loading?
|
||||
|
||||
If the explorer at **https://explorer.d-bis.org** shows no stats, no blocks, and no transactions (or only "—" and "Loading..."), the **Explorer API backend is not responding**.
|
||||
|
||||
## Root cause
|
||||
|
||||
- The frontend loads all data from **`/api/`** (e.g. `/api/v2/stats`, `/api/v2/blocks`, `/api/v2/transactions`).
|
||||
- Nginx proxies **`/api/`** to **Blockscout** on **port 4000** (`http://127.0.0.1:4000`).
|
||||
- When Blockscout is not running or not reachable, nginx returns **502 Bad Gateway** (sometimes 503).
|
||||
- Every API request then fails, so **no info loads**.
|
||||
|
||||
## How to fix it
|
||||
|
||||
1. **On the Proxmox host** that runs the explorer VM (VMID 5000):
|
||||
```bash
|
||||
cd /path/to/explorer-monorepo
|
||||
bash scripts/fix-502-blockscout.sh
|
||||
```
|
||||
Or from your machine if the script supports SSH:
|
||||
```bash
|
||||
EXPLORER_VM_HOST=root@192.168.11.12 bash scripts/fix-502-blockscout.sh
|
||||
```
|
||||
|
||||
2. **Manually** (inside the explorer VM, VMID 5000):
|
||||
- Start PostgreSQL if used: `docker start blockscout-postgres`
|
||||
- Start Blockscout: `cd /opt/blockscout && docker compose up -d`
|
||||
- Ensure the Blockscout container is listening on **port 4000**.
|
||||
|
||||
3. **Verify** the API is up:
|
||||
```bash
|
||||
curl -sS -o /dev/null -w "%{http_code}" https://explorer.d-bis.org/api/v2/stats
|
||||
```
|
||||
You should see `200`. If you see `502`, the backend is still down.
|
||||
|
||||
## More detail
|
||||
|
||||
- **502** = nginx is up but the upstream (Blockscout on port 4000) is down or unreachable.
|
||||
- Full runbook: [EXPLORER_API_ACCESS.md](./EXPLORER_API_ACCESS.md) (Fix 502, Blockscout, nginx proxy).
|
||||
- API reference: [EXPLORER_API_REFERENCE.md](./EXPLORER_API_REFERENCE.md).
|
||||
@@ -70,7 +70,8 @@ CHAIN138_ETHERSCAN_API_KEY=
|
||||
# ETHEREUM MAINNET CONFIGURATION
|
||||
# =============================================================================
|
||||
# RPC Configuration
|
||||
ETHEREUM_MAINNET_RPC=https://43b945b33d58463a9246cf5ca8aa6286:SdwChVo+UbIAamFy3ptxnOP5bCVCYX4ey7TKiYTQWdZGeUzI66fi9g@mainnet.infura.io/v3/43b945b33d58463a9246cf5ca8aa6286
|
||||
# Use Infura with Basic Auth: https://<INFURA_PROJECT_ID>:<INFURA_PROJECT_SECRET>@mainnet.infura.io/v3/<INFURA_PROJECT_ID>
|
||||
ETHEREUM_MAINNET_RPC=https://mainnet.infura.io/v3/<INFURA_PROJECT_ID>
|
||||
ETH_MAINNET_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY
|
||||
|
||||
# CCIP Configuration (Ethereum Mainnet)
|
||||
@@ -231,15 +232,15 @@ GNOSISSCAN_API_KEY=89HVZNN68DWKWVZHQRGQJ1B74FGKWBJV1W
|
||||
# =============================================================================
|
||||
# METAMASK & INFURA CONFIGURATION
|
||||
# =============================================================================
|
||||
METAMASK_API_KEY=43b945b33d58463a9246cf5ca8aa6286
|
||||
METAMASK_SECRET=SdwChVo+UbIAamFy3ptxnOP5bCVCYX4ey7TKiYTQWdZGeUzI66fi9g
|
||||
INFURA_GAS_API=https://gas.api.infura.io/v3/43b945b33d58463a9246cf5ca8aa6286
|
||||
METAMASK_API_KEY=<INFURA_PROJECT_ID>
|
||||
METAMASK_SECRET=<INFURA_PROJECT_SECRET>
|
||||
INFURA_GAS_API=https://gas.api.infura.io/v3/<INFURA_PROJECT_ID>
|
||||
|
||||
# =============================================================================
|
||||
# WALLET & SECURITY CONFIGURATION
|
||||
# =============================================================================
|
||||
# ⚠️ WARNING: This private key should be stored securely and not committed to version control
|
||||
PRIVATE_KEY=0x5373d11ee2cad4ed82b9208526a8c358839cbfe325919fb250f062a25153d1c8
|
||||
PRIVATE_KEY=0x... # NEVER commit real key; use .env and add to .gitignore
|
||||
|
||||
# Multisig Configuration (Placeholders - to be configured)
|
||||
MULTISIG_OWNER_1=""
|
||||
|
||||
Reference in New Issue
Block a user