diff --git a/.codex/config.toml b/.codex/config.toml new file mode 100644 index 0000000..f06e2a4 --- /dev/null +++ b/.codex/config.toml @@ -0,0 +1,7 @@ +[mcp_servers.context7] +url = "https://mcp.context7.com/mcp/oauth" + +[mcp_servers.github] +url = "https://api.githubcopilot.com/mcp/" +bearer_token_env_var = "GIVETH_GITHUB_MCP_PAT" +http_headers = { "X-MCP-Toolsets" = "default,projects,notifications" } diff --git a/.cursor/mcp.json b/.cursor/mcp.json new file mode 100644 index 0000000..7f5e531 --- /dev/null +++ b/.cursor/mcp.json @@ -0,0 +1,14 @@ +{ + "mcpServers": { + "context7": { + "url": "https://mcp.context7.com/mcp/oauth" + }, + "github": { + "url": "https://api.githubcopilot.com/mcp/", + "headers": { + "Authorization": "Bearer ${env:GIVETH_GITHUB_MCP_PAT}", + "X-MCP-Toolsets": "default,projects,notifications" + } + } + } +} diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..fab618d --- /dev/null +++ b/.mcp.json @@ -0,0 +1,16 @@ +{ + "mcpServers": { + "context7": { + "type": "http", + "url": "https://mcp.context7.com/mcp/oauth" + }, + "github": { + "type": "http", + "url": "https://api.githubcopilot.com/mcp/", + "headers": { + "Authorization": "Bearer ${GIVETH_GITHUB_MCP_PAT:-}", + "X-MCP-Toolsets": "default,projects,notifications" + } + } + } +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..4828bfc --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,29 @@ +# Repository Guidelines + +## Project Structure & Module Organization + +Source lives in `src/`. `src/server.ts` boots the HTTP service, while `src/index.ts` exposes the library entrypoint. `src/api/` contains the Express app, route handlers, and middleware. `src/services/` holds transaction verification, price lookups, chain-specific integrations, and Safe support. Shared configuration is under `src/config/`, reusable helpers under `src/utils/`, and domain types under `src/types/`. Tests are colocated with code as `*.test.ts` files, for example `src/api/routes/transaction.routes.test.ts`. Reference material lives in `docs/`, and `dist/` is the TypeScript build output. + +## Build, Test, and Development Commands + +Run `npm ci` first to install the locked dependency set. Use `npm run dev` to start the API with hot reload from `src/server.ts`. Use `npm run build` to compile TypeScript into `dist/`, then `npm start` to run the compiled server. Run `npm test` for the Mocha suite, `npm run test:coverage` for NYC coverage output, and `npm run test:watch` while iterating. Use `npm run lint`, `npm run lint:fix`, and `npm run prettify` for style checks and formatting. For containerized local runs, copy `.env.example` to `.env` and use `docker-compose up -d`. + +## Coding Style & Naming Conventions + +This project uses TypeScript with ESLint and Prettier. Follow formatter settings: 2-space indentation, semicolons, single quotes, trailing commas, and an 80-character print width. Use `PascalCase` for classes and error types, `camelCase` for functions, services, and variables, and keep file names descriptive and consistent with patterns such as `transactionVerificationService.ts`, `chains.routes.ts`, and `*.test.ts`. + +## Testing Guidelines + +Tests run with Mocha, Chai, Sinon, and Supertest through `ts-node/register`. Add tests beside the code you change and name them `*.test.ts`. Prefer stubbing external RPC or service calls rather than hitting live networks. There is no enforced coverage gate in the repo today, so new features and bug fixes should include focused route or service tests to prevent regressions. + +## Commit & Pull Request Guidelines + +Recent history favors short, descriptive commit subjects such as `Add AA donation verification`, `fix service name`, and `Update healthcheck commands...`. Keep commits small and scoped to one change. Pull requests should describe the behavior change, note any required `.env` or deployment updates, link the related issue, and include sample requests or responses when API contracts change. + +## Security & Configuration Tips + +Start from `.env.example` and never commit secrets, RPC keys, or deployment credentials. Verify changes to Docker, health checks, or ports against the GitHub Actions workflows in `.github/workflows/`, since `staging` and `main` trigger image build and deploy pipelines. + +## Architecture & External Services + +If your task involves understanding how this service connects to other Giveth services, what external APIs or RPC providers it depends on, or how giveth-v6-core consumes it, read [docs/EXTERNAL-SERVICES.md](docs/EXTERNAL-SERVICES.md). diff --git a/docs/EXTERNAL-SERVICES.md b/docs/EXTERNAL-SERVICES.md new file mode 100644 index 0000000..3f8f3d4 --- /dev/null +++ b/docs/EXTERNAL-SERVICES.md @@ -0,0 +1,91 @@ +# External Services — Blockchain Integration Service + +> Every external service and internal consumer this repo connects to. For implementation details, read the source files referenced in each section. + +--- + +## System Diagram + +``` + + ┌──────────────────────────────────────┐ + │ giveth-v6-core (NestJS · GraphQL) │ + └──────────────┬───────────────────────┘ + │ HTTP REST + ▼ + ┌──────────────────────────────────────┐ + │ Blockchain Integration Service │ + │ Express · REST │ + └──┬───┬───┬───┬───────────────────────┘ + │ │ │ │ + ┌───────────────┘ │ │ └────────────────────┐ + │ ┌─────────┘ └──────────┐ │ + ▼ ▼ ▼ ▼ + ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌───────────┐ + │ EVM RPC │ │ Solana │ │ CoinGecko │ │ Safe API │ + │Providers │ │ RPC │ │ (prices) │ │ (multisig)│ + └────┬─────┘ └──────────┘ └────────────┘ └───────────┘ + │ + ▼ + ┌──────────────────────────────────────────────────────────┐ + │ DonationHandler.sol contracts + ERC-20 token contracts │ + └──────────────────────────────────────────────────────────┘ + +``` + +--- + +## Consumer + +### giveth-v6-core + +The only direct consumer. v6-core proxies all blockchain interaction through this service via REST endpoints for transaction verification, token price lookups, and chain metadata queries. + +- **Their client code:** `giveth-v6-core/src/integrations/blockchain/blockchain.service.ts` +- **Endpoints actively consumed:** `POST /api/verify`, `POST /api/timestamp`, `POST /api/price`, `GET /api/chains`, `GET /api/chains/:networkId/transaction-url/:txHash` +- **Endpoint wired but not yet called:** `POST /api/verify-batch` (client method exists in v6-core but no call site uses it) + +--- + +## Dependencies + +### EVM RPC Providers + +JSON-RPC connections to 9 EVM networks (Ethereum, Polygon, Optimism, Arbitrum, Gnosis, Celo, Base, BSC, Avalanche) via ethers.js. Used for fetching transaction receipts, parsing event logs, and reading token metadata. Also supports `debug_traceTransaction` for Account Abstraction (EIP-4337) internal transfers, with graceful fallback. + +- **Config:** `src/config/networks.ts` — each network has a `*_RPC_URL` env var. + +### Solana RPC + +Direct connection via `@solana/web3.js` for parsing Solana transactions and calculating SOL/SPL token balance changes. + +- **Config:** `SOLANA_RPC_URL` env var. + +### CoinGecko API + +Token price lookups in USD by symbol or contract address. Results cached in-memory (1-min TTL). + +- **Source:** `src/services/priceService.ts` + +### Safe API (Gnosis Safe) + +Resolves Safe multisig `safeTxHash` values to actual on-chain transaction hashes so the service can then verify the real transaction. + +- **Package:** `@safe-global/api-kit` +- **Source:** `src/services/safe/safeTransactionService.ts` + +### DonationHandler Smart Contracts + +Giveth's upgradeable Solidity contracts (repo: `donation-handler-foundry`) deployed on 7 EVM networks. This service parses their `DonationMade` events to verify individual donations within batch transactions. + +- **Address registry:** `src/config/donationHandlers.ts` + +### ERC-20 Token Contracts + +Interacts with ERC-20 contracts for `symbol()` validation, `decimals()` lookups (some paths fall back to 18), and `Transfer` event log parsing during donation verification. + +--- + +## Infrastructure + +Deployed via Docker Compose (repo: `giveth-v6-deploy`) alongside giveth-v6-core, Redis, and Caddy reverse proxy. This service is **stateless** — no database and no persistent business data. It does hold in-memory caches and connection pools (CoinGecko price cache, EVM provider instances, Solana connections, chain handler registry) that are rebuilt on restart. diff --git a/docs/ai-onboarding.md b/docs/ai-onboarding.md new file mode 100644 index 0000000..de99fbf --- /dev/null +++ b/docs/ai-onboarding.md @@ -0,0 +1,245 @@ +# AI Onboarding + +This project uses two MCP servers as the default AI context layer for day-to-day development: + +- **Context7 MCP** for current, version-aware library documentation and examples +- **GitHub MCP** for repository, issue, pull request, and workflow access + +These MCPs are **developer-tool integrations**, not runtime dependencies of the Express app. + +## Repository-Shared MCP Config + +This repository now includes project-scoped MCP config for the three main clients we use: + +- **Cursor**: `.cursor/mcp.json` +- **Claude Code**: `.mcp.json` +- **Codex**: `.codex/config.toml` in trusted projects + +These committed files share the **server definitions**, but they do **not** store secrets. +For Codex, open this repository as a trusted project before running project-specific MCP commands, otherwise Codex may fall back to user-level MCP config. + +## Per-User Authentication Model + +### Context7 MCP + +- This repo uses the **OAuth endpoint**: `https://mcp.context7.com/mcp/oauth`. +- That avoids committing a shared API key. +- Each developer authenticates interactively inside their client after the server is added. +- If a client does not support MCP OAuth, Context7 documents API key auth as the fallback. + +### GitHub MCP + +- This repo uses GitHub's hosted remote MCP server. +- **Cursor**, **Claude Code**, and **Codex** use a per-user `GIVETH_GITHUB_MCP_PAT`. +- In Claude Code, if `GIVETH_GITHUB_MCP_PAT` is missing, GitHub may show `Failed to connect` or return `401` while the other project MCP servers still load. +- We do **not** share one PAT across the team. +- Access stays tied to the developer's own GitHub identity and token scopes. + +## What We Use Each MCP For + +### Context7 MCP + +**What it is** + +Context7 is an MCP server for up-to-date, version-specific documentation and code examples pulled directly from source docs and repositories. + +**Why we want it here** + +- This repo depends on fast-moving tools where stale examples are expensive +- It is useful for Express, TypeScript, Ethers.js, Viem, Mocha, Chai, Sinon, and Supertest +- It gives agents a safer default path for API verification before they suggest changes + +**Project choice** + +- We use the **OAuth** endpoint in shared config: `https://mcp.context7.com/mcp/oauth` +- That keeps Context7 credentials out of version control +- In Codex, open and trust this repo first, then run `codex mcp get context7` and confirm the URL is `https://mcp.context7.com/mcp/oauth` +- After that check, authenticate it with `codex mcp login context7` + +**Official docs** + +- [Context7 overview](https://context7.com/docs/overview) +- [Context7 installation](https://context7.com/docs/installation) +- [Context7 OAuth](https://context7.com/docs/howto/oauth) +- [Adding libraries to Context7](https://context7.com/docs/adding-libraries) + +**Client setup links** + +- Cursor: [Context7 Cursor setup](https://context7.com/docs/clients/cursor) +- Claude Code: [Context7 Claude Code setup](https://context7.com/docs/clients/claude-code) +- Codex: [OpenAI Codex MCP docs](https://developers.openai.com/codex/mcp) plus [Context7 all clients](https://context7.com/docs/resources/all-clients) and [Context7 OAuth](https://context7.com/docs/howto/oauth) + +Inference from the official docs and local verification: + +- Context7's published Codex example currently shows the API-key variant using `https://mcp.context7.com/mcp` and `CONTEXT7_API_KEY`. +- This repo intentionally uses Context7's OAuth endpoint instead, because current Codex supports MCP OAuth and can authenticate it with `codex mcp login context7`. + +### GitHub MCP + +**What it is** + +GitHub's official MCP server connects AI tools directly to GitHub for repository browsing, code access, issues, pull requests, workflows, releases, and other platform data. + +**Why we want it here** + +- Inspect PRs, issues, and workflow runs without leaving the coding flow +- Work with remote repository state that local git history does not fully cover +- Support review and triage tasks that need live GitHub context + +**Project choice** + +- We use GitHub's hosted remote server +- Cursor, Claude Code, and Codex reference a per-user `GIVETH_GITHUB_MCP_PAT` +- In Claude Code, the shared `.mcp.json` uses `${GIVETH_GITHUB_MCP_PAT:-}` so a missing PAT does not break the rest of the project-scoped config + +**Official docs** + +- [GitHub MCP Server repository](https://github.com/github/github-mcp-server) +- [Host integration and auth](https://github.com/github/github-mcp-server/blob/main/docs/host-integration.md) +- [Extend GitHub Copilot coding agent with MCP](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/extend-coding-agent-with-mcp) + +**Client setup links** + +- Cursor: [GitHub MCP Cursor guide](https://github.com/github/github-mcp-server/blob/main/docs/installation-guides/install-cursor.md) +- Claude Code: [Anthropic Claude Code MCP docs](https://docs.anthropic.com/en/docs/claude-code/mcp) plus [GitHub MCP Claude Code guide](https://github.com/github/github-mcp-server/blob/main/docs/installation-guides/install-claude.md) +- Codex: [GitHub MCP Codex guide](https://github.com/github/github-mcp-server/blob/main/docs/installation-guides/install-codex.md) + +## Shared Config Files In This Repo + +### `.cursor/mcp.json` + +- Provides project-scoped config for Cursor +- Uses `context7` and `github` +- Uses `${env:GIVETH_GITHUB_MCP_PAT}` for GitHub auth + +### `.mcp.json` + +- Provides project-scoped config for Claude Code +- Uses explicit `type: "http"` entries, matching Claude Code's current project config format +- Uses the hosted GitHub MCP URL with an `Authorization` header built from `${GIVETH_GITHUB_MCP_PAT:-}` +- The `:-` default avoids breaking `.mcp.json` parsing when `GIVETH_GITHUB_MCP_PAT` is unset +- If `GIVETH_GITHUB_MCP_PAT` is not set, GitHub may appear as `Failed to connect` in Claude Code while Context7 still loads + +### `.codex/config.toml` + +- Provides project-scoped config for Codex +- Applies in trusted projects +- Uses `context7` and `github` +- Uses the Context7 OAuth endpoint +- Before authenticating Context7, run `codex mcp get context7` in this repo and confirm it resolves to `https://mcp.context7.com/mcp/oauth` +- If `codex mcp get context7` resolves to `https://mcp.context7.com/mcp`, Codex is still using a user-level Context7 server and the project config is not active yet +- Once the project config is active, authenticate Context7 with `codex mcp login context7` +- Uses `bearer_token_env_var = "GIVETH_GITHUB_MCP_PAT"` for GitHub auth + +## Setting Up `GIVETH_GITHUB_MCP_PAT` for Terminal and Desktop Apps + +On macOS, GUI apps (Claude, Codex, Cursor) do **not** read shell config files like `~/.zshenv`. You need to set the env var in two places. + +### 1. Terminal apps (shell) + +Add this to `~/.zshenv`: + +```bash +export GIVETH_GITHUB_MCP_PAT='github_pat_YOUR_TOKEN_HERE' +``` + +This covers Claude Code CLI and any terminal-based tool. + +### 2. Desktop / GUI apps (launchctl) + +macOS GUI apps inherit environment from `launchd`, not from your shell. To make the variable visible to Claude, Codex, and Cursor desktop apps, add this line to `~/.zshenv` **after** the export: + +```bash +launchctl setenv GIVETH_GITHUB_MCP_PAT "$GIVETH_GITHUB_MCP_PAT" +``` + +Your `~/.zshenv` should look like: + +```bash +export GIVETH_GITHUB_MCP_PAT='github_pat_YOUR_TOKEN_HERE' +launchctl setenv GIVETH_GITHUB_MCP_PAT "$GIVETH_GITHUB_MCP_PAT" +``` + +### Verifying + +- **Terminal**: `echo $GIVETH_GITHUB_MCP_PAT` +- **GUI apps**: `launchctl getenv GIVETH_GITHUB_MCP_PAT` + +Both should print your token. + +### Caveat: GUI apps opened before any terminal + +The `~/.zshenv` approach only runs `launchctl setenv` when a **zsh shell process starts**. If you reboot and open Claude, Codex, or Cursor **before** opening a terminal, no shell has run yet, so the variable won't be set for those apps. + +For most developers this is fine — opening a terminal is usually one of the first things you do. But if you want the variable available to GUI apps **unconditionally at login** (even without opening a terminal first), use a **LaunchAgent plist** instead. + +### Alternative: LaunchAgent plist (guaranteed at login) + +Create `~/Library/LaunchAgents/com.giveth.github-pat.plist`: + +```xml + + + + + Label + com.giveth.github-pat + ProgramArguments + + /bin/launchctl + setenv + GIVETH_GITHUB_MCP_PAT + github_pat_YOUR_TOKEN_HERE + + RunAtLoad + + + +``` + +Then load it (or log out and back in): + +```bash +launchctl load ~/Library/LaunchAgents/com.giveth.github-pat.plist +``` + +This runs at every login, before any GUI app starts, so the variable is always available. Note that the plist contains the **raw token value** (not a shell variable reference) because it runs outside of any shell context. + +### Important notes + +- **After changing the token in `~/.zshenv`**: open a new terminal (so the new export and `launchctl setenv` run), then restart any already-running desktop apps. +- **After changing the token in the plist**: you must reload the agent (`launchctl unload` then `launchctl load` the plist, or log out and back in) before restarting desktop apps — simply restarting the apps is not enough, because `launchd` still has the old value until the plist is reloaded. +- Do **not** wrap the token in `$(echo ...)` — pass it as a plain string or use `"$VARIABLE"` expansion. +- The plist file is local to your machine and should **not** be committed to version control. + +## Verification Checklist + +After pulling the repo config, each developer should verify: + +1. **Context7**: in Codex, open and trust this repo, run `codex mcp get context7`, confirm the URL is `https://mcp.context7.com/mcp/oauth`, then run `codex mcp login context7`; in other clients, authenticate after the OAuth endpoint appears +2. **GitHub**: `GIVETH_GITHUB_MCP_PAT` is available in Cursor, Claude Code, and Codex +3. **Cursor**: the servers appear in the MCP settings and show as connected +4. **Claude Code**: run `claude mcp list`; if GitHub shows `Failed to connect`, confirm `GIVETH_GITHUB_MCP_PAT` is set in the Claude Code environment +5. **Codex**: start Codex in this repository, verify the project-scoped MCP servers are available from MCP settings, and confirm Context7 is logged in against the project-scoped `/oauth` server + +## Sources + +Official vendor documentation and official repositories were used, and local CLI verification was performed where client behavior needed confirmation. + +- Context7: [Overview](https://context7.com/docs/overview) +- Context7: [Installation](https://context7.com/docs/installation) +- Context7: [Cursor setup](https://context7.com/docs/clients/cursor) +- Context7: [Claude Code setup](https://context7.com/docs/clients/claude-code) +- Context7: [OAuth](https://context7.com/docs/howto/oauth) +- Context7: [All clients](https://context7.com/docs/resources/all-clients) +- Context7: [Adding libraries](https://context7.com/docs/adding-libraries) +- Cursor: [Model Context Protocol docs](https://docs.cursor.com/context/model-context-protocol) +- Anthropic: [Claude Code MCP docs](https://docs.anthropic.com/en/docs/claude-code/mcp) +- OpenAI: [Codex MCP docs](https://developers.openai.com/codex/mcp) +- GitHub: [GitHub MCP Server repository](https://github.com/github/github-mcp-server) +- GitHub: [Host integration and auth](https://github.com/github/github-mcp-server/blob/main/docs/host-integration.md) +- GitHub: [Cursor installation guide](https://github.com/github/github-mcp-server/blob/main/docs/installation-guides/install-cursor.md) +- GitHub: [Claude Code installation guide](https://github.com/github/github-mcp-server/blob/main/docs/installation-guides/install-claude.md) +- GitHub: [Codex installation guide](https://github.com/github/github-mcp-server/blob/main/docs/installation-guides/install-codex.md) +- GitHub Docs: [Extend GitHub Copilot coding agent with MCP](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/extend-coding-agent-with-mcp)