Local Setup
1. Clone and install
The chain lives in a git submodule, so clone recursively (or initialise it after cloning):
git clone --recurse-submodules <repo-url>
cd cbdc-issuer
# if you already cloned without --recurse-submodules:
git submodule update --init --recursive
pnpm install
2. Start PostgreSQL
The only Docker service in this repo. It starts a PostgreSQL 15 instance on port 5432 with database cbdc_issuer:
docker compose up -d
3. Configure environment
cp .env.example .env
The critical values for local dev (sensible defaults are already in .env.example):
DATABASE_*— match the Docker Compose Postgres (hostlocalhost, user/passpostgres)JWT_SECRET/JWT_REFRESH_SECRET— random strings, ≥32 chars (validated at startup)CUSTODY_SECRET— random string used to encrypt custody keysCHAIN_RPC_ENDPOINT—http://localhost:26657for the local node (step 5)CHAIN_ID/CHAIN_PREFIX/CHAIN_DENOM— defaultscbdc_1449999-1/hnl/ahnlCURRENCY_NAME— display symbol (e.g.HNL)SEED_ADMIN_EMAIL/SEED_ADMIN_PASSWORD— the first admin created by the seed
Email is console by default (logs to stdout), so invitation/reset emails work locally without AWS SES or Resend credentials.
4. Run the database migrations
Migrations run automatically on API startup (DATABASE_MIGRATIONS_RUN=true). To apply them manually:
cd apps/api && pnpm db:migration:run
5. Start the chain node
The local CBDC chain is built from the apps/chain submodule and run as a single-node localnet:
pnpm dev:chain # = make run in apps/chain: builds cbdcd, inits genesis, starts node
It exposes Tendermint RPC on http://localhost:26657. Leave it running in its own terminal. To wipe chain data and start from a fresh genesis: pnpm reset:chain.
6. Seed the database and on-chain groups
With the chain running, bootstrap the platform — creates the admin user, registers the native token, and provisions the on-chain group policies (Standby / Distribution multisigs):
pnpm bootstrap # build api + pnpm seed + pnpm setup:chain
You can also run the pieces individually:
cd apps/api && pnpm seed # admin user, native token, multisig records (off-chain)
pnpm setup:chain # create on-chain group policies (chain must be running)
See Seed & Deployment for what each step does.
7. Start development
pnpm dev # all apps in parallel via Turborepo
| App | URL | Description |
|---|---|---|
| API | http://localhost:3001 | NestJS backend + Swagger at /api/docs |
| Dashboard | http://localhost:3000 | Vite + React console |
| Docs | http://localhost:3003 | This documentation site |
| Chain RPC | http://localhost:26657 | Local Cosmos node (started in step 5) |
To start a single app:
pnpm dev:api # backend only
pnpm dev:dashboard # frontend only
pnpm dev:docs # docs only
pnpm dev:chain # chain node only
Log in to the dashboard with the SEED_ADMIN_EMAIL / SEED_ADMIN_PASSWORD from your .env.
Full reset
When you need a clean slate (e.g. after changing voting period or thresholds):
pnpm reset:all # drop all DB tables + wipe chain data
pnpm dev:chain # start the chain (separate terminal, wait for it)
pnpm bootstrap # re-seed DB + re-create on-chain group policies