Seed & Deployment
Bootstrapping a fresh deployment is two steps: pnpm seed (off-chain data in Postgres) and pnpm setup:chain (on-chain group policies). pnpm bootstrap runs both (after building the API). Both steps are idempotent — re-running them won't create duplicates.
pnpm seed
Run from apps/api (cd apps/api && pnpm seed), it builds the API and executes src/seed.ts, which:
- Creates the Central organization — an
Organizationof typeCENTRAL(default nameCentral Bank), statusACTIVE. - Creates the admin user — bcrypt-hashes the password and generates a custody key (encrypted on-chain signing key). Belongs to the central org with role
ADMINISTRATOR. - Creates the bridging user — the system identity (
UserKind.BRIDGING) used for fiat↔CBDC conversions. - Registers the native token — at a fixed id so the dashboard's
VITE_NATIVE_TOKEN_IDstays stable across fresh installs. - Creates the multisig records — the Standby and Distribution accounts plus their members and token links (the off-chain representation; the on-chain group policies come from
setup:chain).
It reads these env vars (all optional, with defaults):
| Var | Default | Purpose |
|---|---|---|
SEED_ADMIN_EMAIL | admin@cbdc.local | First admin login |
SEED_ADMIN_PASSWORD | admin123456 | First admin password |
SEED_ADMIN_NAME | System Admin | Display name |
SEED_CENTRAL_ORGANIZATION_NAME | Central Bank | Central org name |
SEED_BRIDGING_EMAIL | bridging@cbdc.local | Bridging identity |
SEED_TOKEN_NAME | Lempira | Native token display name |
The console prints the admin email, password and derived chain address on first creation.
pnpm setup:chain
Runs apps/api/scripts/setup-chain.ts against a running chain node. It reads apps/api/scripts/test-env.config.json (override with SETUP_CHAIN_CONFIG), which defines the test identities (committed mnemonics + expected addresses) and the group definitions (Admin, Standby Multisig, Distribution Multisig). For each group it submits MsgCreateGroupWithPolicy with a ThresholdDecisionPolicy, then records the resulting group id and policy address.
Tunables:
| Var | Default | Purpose |
|---|---|---|
SETUP_VOTING_PERIOD_SECONDS | 86400 | Proposal voting window |
SETUP_EXECUTION_DELAY_SECONDS | 0 | Min delay before execution |
Because
cbdc-nodeis an Ethermint-based fork, the script signs manually witheth_secp256k1(coin type 60) and the/ethermint.crypto.v1.ethsecp256k1.PubKeytype URL rather than relying on the default CosmJS signer.
Production deployment
Differences from local development:
DATABASE_SSL=trueandDATABASE_SYNCHRONIZE=false(always — schema is owned by migrations).DATABASE_MIGRATIONS_RUN=true(default) so migrations apply on startup, or run them out-of-band and set it tofalse.EMAIL_PROVIDER=ses(AWS SES) orresend(Resend) with the matching credentials.- A production
CHAIN_RPC_ENDPOINT,CHAIN_ID,CHAIN_PREFIX,CHAIN_DENOM. - Strong, unique
JWT_SECRET,JWT_REFRESH_SECRET(≥32 chars) andCUSTODY_SECRET. - Set
APP_CORS_ORIGINto the dashboard origin, and build the dashboard with the correctVITE_API_URL.