Initial setup
Default path targets Plume Mainnet. You’ll end up with Mongo + API (Docker) and the product UI on the host.
Quick start: pnpm install && REUSE_TAP_FACTORY=1 pnpm bootstrap, set NEXT_PUBLIC_* in .env and app/.env.local, then pnpm app:dev. Server PRIVATE_KEY is optional for the wallet UI.
Secrets and env files
Three wallets / keys
These are easy to conflate. They are not the same wallet.
| Role | What it controls | Where it lives | Needed for golden path? |
|---|---|---|---|
| Factory owner | Beacon upgrades for that factory’s cap tables (updateCapTableImplementation) | Cold / hardware / vault. Used only for rare deploy or upgrade CLI runs | No for day-to-day product work |
| Issuer ADMIN | The wallet that called createCapTable — governance + day-to-day writes (admins count as operators onchain) | Browser wallet in /app | Yes — connect an extension wallet |
| Server / operator | API process signing server-side txs (/*/create, API transfer, etc.). Often the address passed as operator at mint | Root .env → PRIVATE_KEY (key) and NEXT_PUBLIC_OPERATOR_ADDRESS (address only) | No if you only use the wallet UI + poller |
What to do in practice
- Wallet-first
/appUI — ADMIN signs in the browser. Poller needs RPC only. LeavePRIVATE_KEY=UPDATE_ME(or unset). Server runs read-only for chain writes; that is expected. ADMIN alone is enough for the manage UI. NEXT_PUBLIC_OPERATOR_ADDRESS— an address grantedOPERATOR_ROLEon new mints (for server/automation later). Setting it does not put a key on the server. You only need that private key in.envif the API itself will sign as operator.- Factory owner key — never put this in the long-running Docker/API env. Compromise would let an attacker upgrade every cap table on that factory. Inject only for a one-shot
pnpm deploy-factoryor upgrade script (separate env file / CI secret), then remove. - Shared Plume demo factory (
0xcd6…) — owner is TAP Admin (0x366a…), not your issuer wallet. Reusing it does not make you factory owner.
PRIVATE_KEY in local .env is dev/demo only. Optional for the wallet-first path. Never put production or factory-owner keys here. Do not commit real keys.
1. Root .env
cp .env.example .env.env.example defaults to Plume (CHAIN_ID=98866, RPC_URL=https://rpc.plume.org). Typical local values:
| Variable | Purpose |
|---|---|
PRIVATE_KEY | Optional for wallet UI. Funded dev key only if you need server-signed API routes or CLI deploy-factory from this machine. Demo placeholder is fine otherwise. |
NEXT_PUBLIC_OPERATOR_ADDRESS | Address granted OPERATOR_ROLE on new cap tables (often a server/ops address; not a private key) |
NEXT_PUBLIC_FACTORY_ADDRESS | Factory the app mints against |
2. Frontend app/.env.local
Host pnpm app:dev reads app/.env.local, not only root .env. Copy the same NEXT_PUBLIC_* values there. Bootstrap creates a starter file if missing.
Wallet connection is first-party (EIP-6963). Install a browser extension (Rabby, MetaMask, etc.) — no third-party cloud account required.
Bootstrap the stack
# Demo / issuer-dev: register TAP’s shared Plume factory in Mongo (owner is TAP Admin, not you)
REUSE_TAP_FACTORY=1 pnpm bootstrap
# Transfer-agent path: after bootstrap with no factory, deploy your own instead
# pnpm deploy-factoryBootstrap is idempotent: deps, contract build (chain/out), Docker volume, compose up, API health, optional factory register.
| Service | URL |
|---|---|
| API | http://localhost:8293 |
| Product UI | pnpm app:dev → http://localhost:3000/app |
| MongoDB | localhost:27017 |
Prefer host pnpm app:dev for wallet work. Docker app is optional.
Demo reuse vs your own factory
| Path | Command | You own beacon upgrades? |
|---|---|---|
| Shared demo factory | REUSE_TAP_FACTORY=1 pnpm bootstrap | No (protocol builder / TAP Admin) |
| Your TA factory | pnpm deploy-factory | Yes |
Issuers can mint cap tables on either factory (createCapTable is permissionless). Using the demo factory is normal for local product work; production transfer agents should deploy their own.
Anvil (local chain) alternate
For pure contract tests without Plume:
# .env: RPC_URL=http://127.0.0.1:8545 CHAIN_ID=31337 + Anvil PRIVATE_KEY
anvil
pnpm setup
pnpm deploy-factory
pnpm docker:up # or bootstrap without REUSE_TAP_FACTORYAnvil keys are test-only — never use them on mainnet.
Next: Run server / app and Deploy factory.