@posit/config
Centralized configuration with runtime validation
Overview
The config package provides type-safe, validated configuration for all apps and packages. It uses Zod for runtime validation and fails fast on missing or invalid configuration.
Design Principles
- Fail fast: App refuses to start if config is invalid
- Type-safe: Full TypeScript inference from Zod schemas
- Centralized: All config in one place, imported everywhere
- Environment-aware: Supports dev/staging/production
- Multi-chain: Configuration for Solana, Base, and Hyperliquid
Usage
import { config } from '@posit/config';
// Access validated config
const heliusKey = config.chains.solana.heliusApiKey;
const baseRpc = config.chains.base.rpcUrl;
const hlApiUrl = config.chains.hyperliquid.apiUrl;
// Config is fully typed
config.chains.solana.rpcUrl // string
config.features.debugMode // boolean
Schema Structure
const configSchema = z.object({
env: z.enum(['development', 'staging', 'production']),
chains: z.object({
solana: z.object({
rpcUrl: z.string().url(),
heliusApiKey: z.string(),
network: z.enum(['mainnet-beta', 'devnet']),
}),
base: z.object({
rpcUrl: z.string().url().optional(),
alchemyApiKey: z.string().optional(),
chainId: z.number().default(8453),
}),
hyperliquid: z.object({
apiUrl: z.string().url().default('https://api.hyperliquid.xyz'),
wsUrl: z.string().url().default('wss://api.hyperliquid.xyz/ws'),
}),
}),
pricing: z.object({
jupiterApiUrl: z.string().url(),
birdeyeApiKey: z.string().optional(),
}),
auth: z.object({
privyAppId: z.string(),
privyAppSecret: z.string(),
encryptionMasterKey: z.string().optional(),
}),
database: z.object({
url: z.string().url(),
}),
features: z.object({
debugMode: z.boolean().default(false),
enableMockData: z.boolean().default(false),
}),
});
Environment Variables
Required
| Variable | Config Path | Description |
|---|---|---|
DATABASE_URL |
config.database.url |
PostgreSQL connection string |
HELIUS_API_KEY |
config.chains.solana.heliusApiKey |
Helius API key for Solana |
PRIVY_APP_ID |
config.auth.privyAppId |
Privy application ID |
PRIVY_APP_SECRET |
config.auth.privyAppSecret |
Privy app secret |
Multi-Chain (Optional)
| Variable | Config Path | Description |
|---|---|---|
BASE_RPC_URL |
config.chains.base.rpcUrl |
Base chain RPC endpoint |
ALCHEMY_API_KEY |
config.chains.base.alchemyApiKey |
Alchemy API key (multi-chain) |
HYPERLIQUID_API_URL |
config.chains.hyperliquid.apiUrl |
Hyperliquid API URL |
HYPERLIQUID_WS_URL |
config.chains.hyperliquid.wsUrl |
Hyperliquid WebSocket URL |
Pricing
| Variable | Config Path | Description |
|---|---|---|
BIRDEYE_API_KEY |
config.pricing.birdeyeApiKey |
Birdeye API key (fallback pricing) |
Security
| Variable | Config Path | Description |
|---|---|---|
ENCRYPTION_MASTER_KEY |
config.auth.encryptionMasterKey |
Master key for wallet-user mapping encryption |
WEBHOOK_SIGNING_SECRET |
config.webhooks.signingSecret |
Secret for webhook signature verification |
Adding New Config
- Add the Zod schema in
packages/config/src/index.ts - Add the env var mapping in the loader function
- Update
.env.exampleat the repo root - Document in the Environments page
Note: Never import
process.env directly in apps. Always go through @posit/config.
Chain Type Helpers
The config package exports a ChainEnum type for type-safe chain handling:
import { ChainEnum, asChain } from '@posit/config';
// Type-safe chain enum
type ChainEnum = 'solana' | 'base' | 'hyperliquid';
// Safe string to enum conversion
const chain = asChain(userInput); // Returns ChainEnum
const chain = asChain(undefined, 'solana'); // Default to solana