A Tenderly-equivalent developer toolchain for PulseChain (chain ID 369). Seven developer tools — transaction simulation, block explorer, monitoring & alerting, virtual testnets (Anvil forks), smart-contract debugger, enhanced JSON-RPC proxy, and serverless Web3 Actions — delivered as a TypeScript monorepo plus a published @valve-tech/trace-sdk npm package.
| Package | Purpose |
|---|---|
packages/api/ |
Express 4 backend (port 10100). Routes + services architecture; most services split into per-responsibility subdirectories. Postgres via pg for persistence. |
packages/web/ |
React 19 SPA, Vite dev server (port 11800). React Router v7 across 12 routes; TanStack Query persisted to IndexedDB. |
packages/sdk/ |
@valve-tech/trace-sdk — standalone EVM trace loaders, traversal, parsers, risk analysis, and React components. Published to npm; consumed internally by packages/web. ESM-only, MIT, 100% coverage gate. |
shared/ |
PulseChain network constants (chain ID, RPC URL, BlockScout API). No build step. |
For full architecture, service dependencies, data flows, and gotchas, see docs/CODEBASE_MAP.md.
# Install
npm install
# Bring up Postgres (the API requires it)
docker compose up -d postgres
# Run API + Web concurrently
npm run dev
# Or just one
npm run dev:api # API on http://localhost:10100
npm run dev:web # Web on http://localhost:11800The Vite dev server proxies /api, /rpc, /health, and /ws to the API on :10100.
| Variable | Default | Purpose |
|---|---|---|
PORT |
10100 |
API server port |
DATABASE_URL |
postgres://valvetech:valvetech@localhost:5432/valvetech |
Postgres connection |
PULSECHAIN_RPC_URL |
https://rpc.pulsechain.com |
PulseChain RPC endpoint |
DEBUG_RPC_URL |
falls back to PULSECHAIN_RPC_URL |
Debug-enabled node for debug_* methods |
BLOCKSCOUT_API_URL |
https://api.scan.pulsechain.com/api |
BlockScout REST API for ABIs + explorer data |
Local .env is auto-loaded by dotenv/config in packages/api/src/index.ts. .env is gitignored — never commit private RPC URLs or tokens.
# API integration tests — require a live API server on :10100 + live PulseChain RPC
npm run test --workspace=packages/api
# SDK unit tests — Vitest; 100% coverage threshold enforced (CI fails on any uncovered branch)
npm run test --workspace=packages/sdk
# Web unit tests — Vitest + Testing Library + jsdom
npm run test --workspace=packages/webThe API tests use Node's built-in node:test; SDK and web tests use Vitest. Postgres needs to be running for the API tests.
┌──────────────┐ ┌──────────────────────┐ ┌─────────────────┐
│ packages/ │ │ packages/api │ │ PulseChain RPC │
│ web (Vite) ├──────►│ (Express, :10100) ├──────►│ + BlockScout │
│ React 19 │ │ │ │ + Sourcify │
└──────┬───────┘ └─────┬────────┬───────┘ └─────────────────┘
│ │ │
│ imports │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────┐ ┌──────────────────┐
│ packages/sdk │ │ Postgres │ │ Anvil forks │
│ (npm pkg) │ │ (pg) │ │ (one per testnet)│
└──────────────┘ └──────────┘ └──────────────────┘
Each PulseChain interaction passes through the SDK's normalization layer so the same TraceFrame / OpcodeStep shapes power the web UI and external SDK consumers.
| Layer | Tech |
|---|---|
| Frontend | React 19, React Router 7, Vite 6, Tailwind CSS v4, TanStack Query 5 |
| Backend | Express 4, TypeScript, Node 22, pg (Pool) |
| SDK | TypeScript, viem (peer), React (optional peer), Vitest + Testing Library |
| Ethereum | viem 2.23+, Anvil/Foundry (forks), Slither via Docker |
| Validation | Zod |
| Database | Postgres (JSONB columns, advisory-lock-guarded migrations) |
| Real-time | WebSocket /ws/alerts |
| Deploy | Railway via packages/api/Dockerfile (multi-stage, Node 22 alpine) |
- Per-responsibility splits — any component or service over ~200 LOC tends to live in a sibling directory:
Foo.tsx(orchestrator) next toFoo/(split pieces). Seepackages/web/src/components/debugger/StepDebugger/for a fully-developed example. - Backend — Express routes wire Zod validation to service-layer functions;
ApiError+respond.failinpackages/api/src/lib/respond.tsstandardize error envelopes; BigInts are serialized to strings before JSON responses. - Frontend — TanStack Query for server state with IDB persistence; local
useStatefor UI; CSS custom properties inindex.css@themeblock (dark theme only). - SDK — ESM-only,
.jsextensions in TypeScript imports, headless components themed viaclassNamesslot prop.
npm install @valve-tech/trace-sdk viemimport { loadTraceFromHash, parseSwaps, RisksWidget } from "@valve-tech/trace-sdk";See packages/sdk/README.md for the SDK-specific docs.
The @valve-tech/trace-sdk npm package is MIT-licensed; see packages/sdk/LICENSE. The rest of the repository is private to Valve Tech.