This project is a fork of `psf-bch-api` with one major change: paid access now uses the `x402` protocol on the Base ecosystem, with pricing in USDC, instead of `x402-bch` on BCH.
The API surface remains focused on BCH infrastructure (BCH full node, Fulcrum, and SLP indexer), but monetization and payment verification are handled through x402-compatible middleware and facilitator endpoints.
- Optional facilitators: **Dexter** (`PRIMARY_FACILITATOR=dexter`) and **PayAI** (`PRIMARY_FACILITATOR=payai`, default URL `https://facilitator.payai.network`, no API keys).
- **Bazaar** discovery metadata on payment requirements via `@x402/extensions/bazaar`, and optional **multi-facilitator** mode (`ACTIVE_FACILITATORS=cdp,dexter,payai`) so clients can verify/settle through CDP, Dexter, or PayAI (`@x402/core` picks a matching facilitator).
-`PRIMARY_FACILITATOR` (default: `cdp`) — one of `cdp`, `dexter`, or `payai`. Used for **single-facilitator** mode when `ACTIVE_FACILITATORS` is unset; selects the default facilitator base URL unless `x402_FACILITATOR_URL` is set.
-`ACTIVE_FACILITATORS` — optional comma-separated list (e.g. `dexter,payai`). When set with multi-facilitator mode, the server registers **multiple**`HTTPFacilitatorClient` instances. **`PRIMARY_FACILITATOR` is always first** in that list (x402 gives earlier facilitators precedence); remaining names follow in the order listed, deduped. Each facilitator uses its default base URL (`x402_FACILITATOR_URL` applies only in **single-facilitator** mode).
-`X402_BAZAAR_ENABLED` (default: `true`) — attach Bazaar **discovery** extension to protected route payment requirements (for facilitator catalogs). Set `false` to disable.
-`x402_FACILITATOR_URL` — optional override for the facilitator HTTP base URL (must expose `/verify`, `/settle`, and `/supported` like the x402 reference facilitator). When unset, the URL is derived from `PRIMARY_FACILITATOR`. **Ignored per-facilitator when `ACTIVE_FACILITATORS` lists more than one entry** (each entry uses its provider URL).
-`PAYAI_FACILITATOR_URL` — optional; when `PRIMARY_FACILITATOR=payai` and `x402_FACILITATOR_URL` is unset, defaults to `https://facilitator.payai.network`.
The script is configured for Base mainnet by default (`viem/chains``base`). You can switch it to Base Sepolia by using the commented testnet import in the file.
These are CDP Secret API Key credentials from the Coinbase Developer Platform API Keys dashboard and are used to generate JWT auth headers for `/verify` and `/settle`.
A Docker setup is provided in the `production/docker/` directory for production deployments. The target OS is Ubuntu Linux.
1. Install [Docker and Docker Compose](https://docs.docker.com/engine/install/ubuntu/).
2. Navigate to the Docker directory:
`cd production/docker`
3. Create and configure the `.env` file. An example is provided:
`cp .env-example .env`
Edit `.env` to match your production infrastructure. Note that inside a Docker container, `localhost` refers to the container itself. Use `172.17.0.1` (the default Docker bridge gateway) to reach services running on the host machine:
Set `APIDOC_URL` to the public base URL for your deployment (for example `https://api.example.com` or your subdomain). The container entrypoint applies this value to `apidoc.json` and the `apidoc` section of `package.json`, then runs `npm run docs` before starting the server so generated HTML matches each instance. The compose file mounts `./.env` to `/home/safeuser/psf-bch-api/.env` so it matches `dotenv.config()` in the app.
The container maps host port `5942` to container port `5942`. The `.env` file is mounted into the container as a volume, so you can update configuration without rebuilding.
To view logs:
`docker logs -f psf-bch-api`
To stop the container:
`docker-compose down`
A helper script `cleanup-images.sh` is provided to remove dangling Docker images after rebuilds.
## Testing
The project includes both unit tests and integration tests. Tests use [Mocha](https://mochajs.org/) as the test runner, [Chai](https://www.chaijs.com/) for assertions, and [Sinon](https://sinonjs.org/) for mocking. Code coverage is provided by [c8](https://github.com/bcoe/c8).
### Unit Tests
Unit tests are located in `test/unit/` and cover adapters, controllers, and use cases. They do not require any running infrastructure. To run:
`npm test`
This will first lint the code with [Standard](https://standardjs.com/), then execute all unit tests with code coverage.
To generate an HTML coverage report:
`npm run coverage`
The report is written to the `coverage/` directory.
### Integration Tests
Integration tests are located in `test/integration/` and require the back end infrastructure (full node, Fulcrum, SLP indexer) to be running. To run:
`npm run test:integration`
Integration tests have a 25-second timeout per test to accommodate network calls.
## Configuration Reference
All configuration values are read from environment variables (via the `.env` file). The complete list:
- `PORT` - Server listen port. Default: `5942`
- `NODE_ENV` - Environment (`development` or `production`). Default: `development`
- `API_PREFIX` - URL prefix for all REST endpoints. Default: `/v6`