Skip to main content

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:

  1. Creates the Central organization — an Organization of type CENTRAL (default name Central Bank), status ACTIVE.
  2. 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.
  3. Creates the bridging user — the system identity (UserKind.BRIDGING) used for fiat↔CBDC conversions.
  4. Registers the native token — at a fixed id so the dashboard's VITE_NATIVE_TOKEN_ID stays stable across fresh installs.
  5. 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):

VarDefaultPurpose
SEED_ADMIN_EMAILadmin@cbdc.localFirst admin login
SEED_ADMIN_PASSWORDadmin123456First admin password
SEED_ADMIN_NAMESystem AdminDisplay name
SEED_CENTRAL_ORGANIZATION_NAMECentral BankCentral org name
SEED_BRIDGING_EMAILbridging@cbdc.localBridging identity
SEED_TOKEN_NAMELempiraNative 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:

VarDefaultPurpose
SETUP_VOTING_PERIOD_SECONDS86400Proposal voting window
SETUP_EXECUTION_DELAY_SECONDS0Min delay before execution

Because cbdc-node is an Ethermint-based fork, the script signs manually with eth_secp256k1 (coin type 60) and the /ethermint.crypto.v1.ethsecp256k1.PubKey type URL rather than relying on the default CosmJS signer.

Production deployment

Differences from local development:

  • DATABASE_SSL=true and DATABASE_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 to false.
  • EMAIL_PROVIDER=ses (AWS SES) or resend (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) and CUSTODY_SECRET.
  • Set APP_CORS_ORIGIN to the dashboard origin, and build the dashboard with the correct VITE_API_URL.