Skip to content

Environment Variables ​

Web (apps/web) ​

VariableRequiredDefaultDescription
VITE_API_URLNo""Base URL of the API server. Empty means same origin. In local dev, Vite proxies /api to localhost:3001 so this is not needed.
VITE_ADMIN_ADDRESSESNo""Comma-separated Stellar public keys allowed onto /admin. Client-side only, and inlined into the public build like every VITE_ variable. It is a placeholder gate for the Keeper Health/Vault State panels until #614 lands real server-enforced admin auth. Never treat this as access control for anything sensitive.

API: serverless (api/v1/) and Fastify (apps/api-local) ​

VariableRequiredDefaultDescription
STELLAR_NETWORKNo"mainnet"Selects the network the API talks to. Any value other than "testnet" resolves to mainnet, the product's live deployment; testnet requires setting this explicitly. Controls which CONTRACT_ADDRESSES/STELLAR_NETWORKS entry (packages/shared/src/constants.ts) is used for every contract call the API makes. .env.example sets testnet explicitly for local development.
DEFINDEX_VAULT_IDNo""Overrides the DeFindex vault contract address at runtime. When empty, the address from CONTRACT_ADDRESSES.testnet.defindex.vault in packages/shared/src/constants.ts is used. Blend and vault contract addresses are always sourced from constants.
PORTNo3001Fastify server port (local dev only).
ALLOWED_ORIGINNo"https://usemeridian.vercel.app"CORS allowed origin for the Fastify server. Set to your frontend domain in production if running Fastify as a standalone server.
REDIS_URLNo""Redis URL for @fastify/rate-limit in apps/api-local (ioredis). Unset: in-memory store (single process); production: set for distributed rate limits.
UPSTASH_REDIS_REST_URLYes (prod)""Upstash Redis REST endpoint. Backs distributed rate limiting (api/_lib/middleware.ts) and the keepers' cross-invocation submission records. The API refuses to start without it when VERCEL_ENV=production; the migration keeper refuses on any deployment, preview included, since preview also signs real transactions. UPSTASH_REDIS_REST_KV_REST_API_URL (the name Vercel's Upstash Marketplace integration provisions) is accepted as a fallback if this isn't set.
UPSTASH_REDIS_REST_TOKENYes (prod)""Auth token for UPSTASH_REDIS_REST_URL. Same requirement and same consumers. UPSTASH_REDIS_REST_KV_REST_API_TOKEN is accepted as a fallback, same as its URL counterpart.
CRON_SECRETYes""Bearer token required by scheduled keeper endpoints in production and preview deployments. Only true local dev (no VERCEL_ENV set) is permissive without it.
MERIDIAN_KEEPER_SECRET_KEYYes (keeper)""Stellar secret seed for the funded account that submits Blend accrue() transactions. Store in a secrets manager or deployment environment variables; never commit it.
MERIDIAN_KEEPER_MAX_ATTEMPTSNo3Maximum attempts per submission. Shared by both the accrue keeper and the migration keeper (rebalance.ts), not accrue-specific despite the name; sizing it affects both.
MERIDIAN_KEEPER_RETRY_BASE_DELAY_MSNo1000Initial exponential-backoff delay for transient keeper failures. Shared by both the accrue keeper and the migration keeper.
MERIDIAN_KEEPER_RPC_TIMEOUT_MSNo10000Timeout for keeper RPC calls, in milliseconds. Shared by both the accrue keeper and the migration keeper. Fully governs submission calls; discovery reads are additionally capped at a hardcoded 10s ceiling shared with the rest of stellar-sdk-helpers, so values above 10000 only extend the submission side.
MERIDIAN_KEEPER_SUBMISSION_TTL_MSNo360000How long a recorded, still-unconfirmed keeper submission keeps blocking a new one for the same target, in milliseconds. Defaults to the 300s transaction validity window plus 60s of clock-skew margin; past it the transaction can never land, so the record is cleared and a retry is allowed. Rejected below 300000, since a shorter window would expire the record while its transaction can still land. Shared by both keepers. See apps/docs/operations/migration-keeper.md.
MERIDIAN_MIGRATION_KEEPER_SECRET_KEYYes (keeper)""Stellar secret seed for the migration keeper. Must be the vault's actual admin address; migrate_adapter is admin-gated, unlike the permissionless accrue(), so this key carries full vault admin authority. Deliberately separate from MERIDIAN_KEEPER_SECRET_KEY. See apps/docs/operations/migration-keeper.md.
MERIDIAN_MIGRATION_MAX_SLIPPAGE_BPSNo100max_slippage_bps passed to every migrate_adapter call. The config loader rejects anything above 500, the contract's own MAX_ADMIN_SLIPPAGE_BPS hard cap (#557).
MERIDIAN_MIGRATION_MIN_IMPROVEMENT_BPSNo50Minimum rate improvement, in basis points, a candidate protocol must clear before the keeper migrates to it.
MERIDIAN_ADAPTER_<PROTOCOL>_IDNo""Candidate adapter contract address the migration keeper may migrate the vault to, one var per protocol (e.g. MERIDIAN_ADAPTER_BLEND_ID, MERIDIAN_ADAPTER_DEFINDEX_ID). Not a fixed list: any <PROTOCOL> is picked up automatically, adding a new protocol needs no code change. Unset excludes that protocol from consideration, no fallback default.
MERIDIAN_ALERT_WEBHOOK_URLYes (keeper)""Slack or Discord incoming-webhook URL the admin-event alert keeper posts to. See apps/docs/operations/alert-keeper.md.

Deploy scripts (scripts/) ​

These are shell environment variables read by scripts/deploy-testnet.sh and scripts/redeploy-blend-adapter.sh at deploy time, not application runtime variables, and not read from .env files.

VariableRequiredDescription
DEPLOYERYes (both scripts)A funded Stellar secret key that pays transaction fees and signs setup calls only. It is disposable and does not need to be kept after the script finishes.
ADMINNo (deploy-testnet.sh only)A public key that becomes the deployed vault's permanent admin. Defaults to DEPLOYER's own address if unset (with a warning), but a throwaway default is unsuitable past a quick test. Set it explicitly to a separate, durable key; it is required ahead of mainnet.
USDC_IDNoOverrides the testnet USDC contract address the deployed adapter/vault is wired to.
BLEND_POOL_IDNoOverrides the testnet Blend pool address the deployed BlendAdapter is wired to.
VAULT_IDYes (redeploy-blend-adapter.sh only)The already-live vault contract ID to eventually point at the newly deployed adapter via set_adapter.

deploy-testnet.sh prints three contract IDs on success (VAULT_CONTRACT_ID, BLEND_ADAPTER_CONTRACT_ID, MUSDC_CONTRACT_ID). None of these are environment variables the app reads either; VAULT_CONTRACT_ID and MUSDC_CONTRACT_ID need to be copied into CONTRACT_ADDRESSES/KNOWN_POOLS in packages/shared/src/constants.ts and packages/stellar-sdk-helpers/src/known-pools.ts respectively. See Testnet Deployment.

Vercel ​

Set environment variables in the Vercel dashboard under Project Settings > Environment Variables, or via the CLI:

bash
vercel env add DEFINDEX_VAULT_ID

Variables prefixed with VITE_ are inlined at build time and exposed to the browser. Do not put secrets in VITE_ variables.

Local development ​

Create .env files at the package level if needed:

bash
# apps/api-local/.env
PORT=3001
DEFINDEX_VAULT_ID=C...   # optional, leave empty to use the address in constants.ts

The Fastify server loads .env via the dotenv package on startup.