This guide explains how to configure the SwiftRemit system for different environments using environment variables.
SwiftRemit uses environment variables for configuration to support different deployment environments (local development, testnet, mainnet) without modifying code. Configuration is centralized in:
.envfile: Your local environment configuration (gitignored).env.example: Template with all available configuration optionsexamples/config.js: JavaScript configuration module that loads and validates environment variables- Deployment scripts:
deploy.shanddeploy.ps1read environment variables for deployment
-
Copy the example environment file:
cp .env.example .env
-
Edit
.envand fill in your values:# Required for client operations SWIFTREMIT_CONTRACT_ID=your_contract_id_here USDC_TOKEN_ID=your_usdc_token_id_here # Optional: customize other settings NETWORK=testnet DEFAULT_FEE_BPS=250
-
Run your application - configuration is loaded automatically
- Description: Stellar network to connect to
- Type: String
- Valid Values:
testnet,mainnet - Default:
testnet - Example:
NETWORK=testnet
- Description: RPC endpoint URL for Soroban network
- Type: String (HTTPS URL)
- Default:
https://soroban-testnet.stellar.org:443 - Example:
RPC_URL=https://soroban-testnet.stellar.org:443 - Validation: Must be an HTTPS URL
- Description: Deployed SwiftRemit contract address
- Type: String
- Required: Yes (for client operations)
- Example:
SWIFTREMIT_CONTRACT_ID=CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSC4
- Description: USDC token contract address
- Type: String
- Required: Yes (for client operations)
- Example:
USDC_TOKEN_ID=CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSC4
- Description: Default platform fee in basis points (1 bps = 0.01%)
- Type: Number
- Range: 0-10000 (0% to 100%)
- Default: 250 (2.5%)
- Example:
DEFAULT_FEE_BPS=250 - Validation: Must be between 0 and 10000
- Description: Transaction fee in stroops
- Type: String (numeric)
- Default:
100000 - Example:
TRANSACTION_FEE=100000
- Description: Transaction timeout in seconds
- Type: Number
- Range: Positive integer
- Default: 30
- Example:
TRANSACTION_TIMEOUT=30
- Description: Polling interval for transaction status in milliseconds
- Type: Number
- Range: Positive integer
- Default: 1000
- Example:
POLL_INTERVAL_MS=1000
- Description: Number of decimal places for USDC token
- Type: Number
- Range: Positive integer
- Default: 7
- Example:
USDC_DECIMALS=7
- Description: Admin account secret key
- Type: String
- Required: No (optional for testing)
- Example:
ADMIN_SECRET=SXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- Description: Sender account secret key
- Type: String
- Required: No (optional for testing)
- Example:
SENDER_SECRET=SXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- Description: Agent account secret key
- Type: String
- Required: No (optional for testing)
- Example:
AGENT_SECRET=SXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- Description: Soroban CLI identity name for deployment
- Type: String
- Default:
deployer - Example:
DEPLOYER_IDENTITY=deployer
- Description: Initial platform fee for contract initialization (basis points)
- Type: Number
- Range: 0-10000 (0% to 100%)
- Default: 250 (2.5%)
- Example:
INITIAL_FEE_BPS=250 - Validation: Must be between 0 and 10000
- Description: Enable debug logging
- Type: Boolean
- Valid Values:
true,false - Default:
true - Example:
ENABLE_DEBUG_LOG=true
# .env for local development
NETWORK=testnet
RPC_URL=https://soroban-testnet.stellar.org:443
SWIFTREMIT_CONTRACT_ID=CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSC4
USDC_TOKEN_ID=CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSC4
DEFAULT_FEE_BPS=250
TRANSACTION_FEE=100000
TRANSACTION_TIMEOUT=30
POLL_INTERVAL_MS=1000
USDC_DECIMALS=7
DEPLOYER_IDENTITY=deployer
INITIAL_FEE_BPS=250
ENABLE_DEBUG_LOG=true# .env for testnet deployment
NETWORK=testnet
RPC_URL=https://soroban-testnet.stellar.org:443
DEPLOYER_IDENTITY=testnet-deployer
INITIAL_FEE_BPS=250
ENABLE_DEBUG_LOG=true# .env for mainnet deployment
NETWORK=mainnet
RPC_URL=https://soroban-mainnet.stellar.org:443
DEPLOYER_IDENTITY=mainnet-deployer
INITIAL_FEE_BPS=200
ENABLE_DEBUG_LOG=falseThese values are hardcoded in the Rust contract code and cannot be changed via environment variables:
- MAX_FEE_BPS: 10000 (100%) - Maximum allowed fee
- FEE_DIVISOR: 10000 - Used for fee calculation
- SCHEMA_VERSION: 1 - Event schema version
These constants ensure consistent on-chain behavior across all deployments.
These values are set when the contract is deployed and initialized:
- initial fee_bps: Set via
INITIAL_FEE_BPSenvironment variable during deployment- Used in
deploy.shanddeploy.ps1 - Passed to contract
initialize()function - Can be updated later by admin via
update_fee()function
- Used in
These values affect client behavior but not on-chain logic:
- Network settings (NETWORK, RPC_URL)
- Transaction parameters (TRANSACTION_FEE, TRANSACTION_TIMEOUT, POLL_INTERVAL_MS)
- Token configuration (USDC_DECIMALS)
- Feature flags (ENABLE_DEBUG_LOG)
Cause: Required environment variable not set
Solution: Add the variable to your .env file:
SWIFTREMIT_CONTRACT_ID=your_contract_id_hereCause: Fee value outside valid range
Solution: Set fee to a value between 0 and 10000:
DEFAULT_FEE_BPS=250Error: "RPC_URL must be an HTTPS URL, got: http://example.com"
Cause: Non-HTTPS URL provided
Solution: Use HTTPS URL:
RPC_URL=https://soroban-testnet.stellar.org:443Cause: Invalid network value
Solution: Use valid network value:
NETWORK=testnetCause: Non-numeric value for numeric configuration
Solution: Provide numeric value:
TRANSACTION_TIMEOUT=30The configuration module validates all values at startup (fail-fast approach):
- All required variables must be present
- Numeric values must be valid numbers
- Numeric values must be within valid ranges
- URLs must be properly formatted HTTPS URLs
- Network must be 'testnet' or 'mainnet'
If any validation fails, the application will throw a descriptive error and exit before executing any business logic.
- Check that
.envfile exists in the project root - Verify
.envfile is not empty - Ensure no typos in variable names
- Check that values match expected types and ranges
- Look for error messages that indicate which variable is invalid
- Never commit
.envfiles: The.envfile is gitignored to prevent committing secrets - Use
.env.exampleas template: Keep.env.exampleupdated with all variables (without sensitive values) - Rotate secrets regularly: Change account secrets periodically
- Use different secrets per environment: Don't reuse testnet secrets on mainnet
- Limit secret access: Only share secrets with authorized team members
- Use environment-specific identities: Create separate Soroban identities for testnet and mainnet
SwiftRemit supports AWS Secrets Manager for secure secret management in production environments. This integration eliminates plaintext secrets in environment variables.
All the following secrets must be stored in AWS Secrets Manager:
| Secret Name | Description | Required |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | Yes |
ADMIN_SECRET_KEY |
Stellar admin keypair secret (for contract operations) | Yes |
CONTRACT_ID |
Deployed SwiftRemit contract address | Yes |
JWT_SECRET |
Secret key for JWT signing (API service) | Yes |
FX_API_KEY |
External FX rate API key | No (optional) |
WEBHOOK_SECRET_{ANCHOR_ID} |
HMAC secrets for webhook verification | Required per anchor |
Configure the following environment variables to enable AWS Secrets Manager:
# Enable Secrets Manager integration (set to 'false' to disable)
SECRETS_MANAGER_ENABLED=true
# AWS region for Secrets Manager
AWS_REGION=us-east-1
# Cache TTL for secrets (default: 5 minutes)
SECRETS_CACHE_TTL_MS=300000
# Rotation check interval (default: 1 minute)
SECRETS_ROTATION_CHECK_INTERVAL_MS=60000# Create DATABASE_URL secret
aws secretsmanager create-secret \
--name swiftremit/DATABASE_URL \
--secret-string "postgresql://user:password@rds-endpoint:5432/swiftremit"
# Create ADMIN_SECRET_KEY secret
aws secretsmanager create-secret \
--name swiftremit/ADMIN_SECRET_KEY \
--secret-string "SXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# Create CONTRACT_ID secret
aws secretsmanager create-secret \
--name swiftremit/CONTRACT_ID \
--secret-string "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSC4"
# Create JWT_SECRET secret
aws secretsmanager create-secret \
--name swiftremit/JWT_SECRET \
--secret-string "your-jwt-signing-secret-here"
# Create webhook secrets (per anchor)
aws secretsmanager create-secret \
--name swiftremit/WEBHOOK_SECRET_PRIMARY \
--secret-string "webhook-hmac-secret-here"SwiftRemit supports automatic secret rotation detection. When secrets are rotated in AWS Secrets Manager:
- The application polls for changes (configurable via
SECRETS_ROTATION_CHECK_INTERVAL_MS) - Rotation hooks update in-memory caches automatically
- New values take effect immediately without service restart
For manual rotation via API:
# Rotate a secret programmatically
curl -X POST http://localhost:3000/api/secrets/rotate \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"secretId": "FX_API_KEY", "newValue": "new-api-key"}'When deploying via Helm, secrets should be injected via AWS Secrets and Configs Controller or External Secrets Operator:
# values.production.yaml
api:
secret:
DATABASE_URL: "" # Injected from AWS Secrets Manager
JWT_SECRET: "" # Injected from AWS Secrets Manager
backend:
secret:
DATABASE_URL: "" # Injected from AWS Secrets Manager
ADMIN_SECRET_KEY: "" # Injected from AWS Secrets Manager
CONTRACT_ID: "" # Injected from AWS Secrets ManagerFor AWS Secrets Manager with External Secrets Operator:
# Create ExternalSecret resource
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: swiftremit-api-secrets
spec:
secretStoreRef:
name: aws-secrets-manager
kind: SecretStore
target:
name: swiftremit-api
data:
- secretKey: DATABASE_URL
remoteRef:
key: swiftremit/DATABASE_URL
- secretKey: JWT_SECRET
remoteRef:
key: swiftremit/JWT_SECRETFor local development, secrets can still be loaded from .env files. Set SECRETS_MANAGER_ENABLED=false or leave AWS_REGION unset to use environment variables.
# .env for local development
SECRETS_MANAGER_ENABLED=false
DATABASE_URL=postgresql://user:password@localhost:5432/swiftremit
ADMIN_SECRET_KEY=SXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
CONTRACT_ID=CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSC4
JWT_SECRET=development-jwt-secret