environments - saltict/Demo-Docs GitHub Wiki
This document covers environment-specific configurations, deployment settings, and runtime parameters for the SubWallet Services SDK across different environments.
- 📋 Overview
- 🏗️ Environment Types
- ⚙️ Configuration Management
- 🔐 Security & Secrets
- 🌐 Registry Configuration
- 📊 Monitoring & Logging
The SubWallet Services SDK supports multiple deployment environments with specific configurations for each. Environment management ensures optimal performance, security, and reliability across development, staging, and production deployments.
Purpose: Local development and unit testing
// File: src/config/development.ts
export const developmentConfig = {
environment: 'development',
apiEndpoints: {
priceHistory: 'http://localhost:3001/api/price-history',
balanceDetection: 'http://localhost:3002/api/balance',
xcm: 'http://localhost:3003/api/xcm',
cardano: 'http://localhost:3004/api/cardano',
swap: 'http://localhost:3005/api/swap'
},
logging: {
level: 'debug',
enableConsole: true,
enableFile: false
},
cache: {
enabled: false,
ttl: 60
},
security: {
rateLimiting: false,
apiKeyRequired: false
}
};
Purpose: Integration testing and UAT
// File: src/config/staging.ts
export const stagingConfig = {
environment: 'staging',
apiEndpoints: {
priceHistory: 'https://staging-api.subwallet.io/price-history',
balanceDetection: 'https://staging-api.subwallet.io/balance',
xcm: 'https://staging-api.subwallet.io/xcm',
cardano: 'https://staging-api.subwallet.io/cardano',
swap: 'https://staging-api.subwallet.io/swap'
},
logging: {
level: 'info',
enableConsole: true,
enableFile: true
},
cache: {
enabled: true,
ttl: 300
},
security: {
rateLimiting: true,
apiKeyRequired: true
}
};
Purpose: Live production deployment
// File: src/config/production.ts
export const productionConfig = {
environment: 'production',
apiEndpoints: {
priceHistory: 'https://api.subwallet.io/price-history',
balanceDetection: 'https://api.subwallet.io/balance',
xcm: 'https://api.subwallet.io/xcm',
cardano: 'https://api.subwallet.io/cardano',
swap: 'https://api.subwallet.io/swap'
},
logging: {
level: 'warn',
enableConsole: false,
enableFile: true
},
cache: {
enabled: true,
ttl: 600
},
security: {
rateLimiting: true,
apiKeyRequired: true,
encryption: true
}
};
// File: src/config/index.ts
import { developmentConfig } from './development';
import { stagingConfig } from './staging';
import { productionConfig } from './production';
export interface SDKConfig {
environment: string;
apiEndpoints: Record<string, string>;
logging: {
level: string;
enableConsole: boolean;
enableFile: boolean;
};
cache: {
enabled: boolean;
ttl: number;
};
security: {
rateLimiting: boolean;
apiKeyRequired: boolean;
encryption?: boolean;
};
}
export function getConfig(): SDKConfig {
const env = process.env.NODE_ENV || 'development';
switch (env) {
case 'development':
return developmentConfig;
case 'staging':
return stagingConfig;
case 'production':
return productionConfig;
default:
console.warn(`Unknown environment: ${env}, falling back to development`);
return developmentConfig;
}
}
export const config = getConfig();
# Core Configuration
NODE_ENV=production
SDK_VERSION=0.1.3-beta.5
# API Configuration
PRICE_HISTORY_API_URL=https://api.subwallet.io/price-history
BALANCE_DETECTION_API_URL=https://api.subwallet.io/balance
XCM_API_URL=https://api.subwallet.io/xcm
CARDANO_API_URL=https://api.subwallet.io/cardano
SWAP_API_URL=https://api.subwallet.io/swap
# Registry Configuration
NPM_REGISTRY=https://registry.konistudio.xyz
NPM_TOKEN=your_npm_token_here
# Security
API_KEY=your_api_key_here
ENCRYPTION_KEY=your_encryption_key_here
# Logging
LOG_LEVEL=info
LOG_FILE_PATH=/var/log/subwallet-sdk.log
# Cache Configuration
CACHE_ENABLED=true
CACHE_TTL=600
CACHE_REDIS_URL=redis://localhost:6379
# Performance Tuning
REQUEST_TIMEOUT=30000
MAX_CONCURRENT_REQUESTS=10
RETRY_ATTEMPTS=3
# Monitoring
METRICS_ENABLED=true
METRICS_PORT=9090
HEALTH_CHECK_ENABLED=true
# Debug Options
DEBUG_MODE=false
VERBOSE_LOGGING=false
PERFORMANCE_MONITORING=true
// File: src/config/validator.ts
import Joi from 'joi';
const configSchema = Joi.object({
environment: Joi.string().valid('development', 'staging', 'production').required(),
apiEndpoints: Joi.object({
priceHistory: Joi.string().uri().required(),
balanceDetection: Joi.string().uri().required(),
xcm: Joi.string().uri().required(),
cardano: Joi.string().uri().required(),
swap: Joi.string().uri().required()
}).required(),
logging: Joi.object({
level: Joi.string().valid('debug', 'info', 'warn', 'error').required(),
enableConsole: Joi.boolean().required(),
enableFile: Joi.boolean().required()
}).required(),
cache: Joi.object({
enabled: Joi.boolean().required(),
ttl: Joi.number().min(0).required()
}).required(),
security: Joi.object({
rateLimiting: Joi.boolean().required(),
apiKeyRequired: Joi.boolean().required(),
encryption: Joi.boolean().optional()
}).required()
});
export function validateConfig(config: any): void {
const { error } = configSchema.validate(config);
if (error) {
throw new Error(`Configuration validation failed: ${error.message}`);
}
}
%%{init: {'theme':'dark'}}%%
graph TB
App[Application] --> Vault[Secret Vault]
Vault --> Env[Environment Variables]
Vault --> Files[Secret Files]
Vault --> KMS[Key Management Service]
Env --> Runtime[Runtime Configuration]
Files --> Runtime
KMS --> Runtime
Runtime --> Services[SDK Services]
style App fill:#2d3748,stroke:#4a5568,color:#fff
style Vault fill:#1a202c,stroke:#2d3748,color:#fff
style Env fill:#553c9a,stroke:#6b46c1,color:#fff
style Files fill:#553c9a,stroke:#6b46c1,color:#fff
style KMS fill:#553c9a,stroke:#6b46c1,color:#fff
style Runtime fill:#2d3748,stroke:#4a5568,color:#fff
style Services fill:#10b981,stroke:#059669,color:#fff
// File: src/config/secrets.ts
export class SecretManager {
private static instance: SecretManager;
private secrets: Map<string, string> = new Map();
static getInstance(): SecretManager {
if (!SecretManager.instance) {
SecretManager.instance = new SecretManager();
}
return SecretManager.instance;
}
async loadSecrets(): Promise<void> {
// Load from environment variables
this.loadFromEnvironment();
// Load from secret files (in production)
if (process.env.NODE_ENV === 'production') {
await this.loadFromFiles();
}
// Load from external vault (if configured)
if (process.env.VAULT_URL) {
await this.loadFromVault();
}
}
private loadFromEnvironment(): void {
const secretKeys = [
'API_KEY',
'ENCRYPTION_KEY',
'NPM_TOKEN',
'CACHE_REDIS_URL'
];
secretKeys.forEach(key => {
const value = process.env[key];
if (value) {
this.secrets.set(key, value);
}
});
}
getSecret(key: string): string | undefined {
return this.secrets.get(key);
}
hasSecret(key: string): boolean {
return this.secrets.has(key);
}
}
// File: src/config/encryption.ts
export interface EncryptionConfig {
algorithm: string;
keyLength: number;
ivLength: number;
}
export const encryptionConfig: EncryptionConfig = {
algorithm: 'aes-256-gcm',
keyLength: 32,
ivLength: 16
};
export function createEncryptionKey(): string {
return crypto.randomBytes(encryptionConfig.keyLength).toString('hex');
}
# Configure for npmjs.org
npm config set registry https://registry.npmjs.org/
npm config set @subwallet-monorepos:registry https://registry.npmjs.org/
# Configure for private registry
npm config set registry https://registry.konistudio.xyz
npm config set @subwallet-monorepos:registry https://registry.konistudio.xyz
npm config set //registry.konistudio.xyz/:_authToken "${NPM_TOKEN}"
// File: src/config/registry.ts
export interface RegistryConfig {
url: string;
authToken?: string;
scope?: string;
}
export function getRegistryConfig(): RegistryConfig {
const registryUrl = process.env.NPM_REGISTRY || 'https://registry.npmjs.org/';
return {
url: registryUrl,
authToken: process.env.NPM_TOKEN,
scope: '@subwallet-monorepos'
};
}
export async function verifyRegistryAccess(config: RegistryConfig): Promise<boolean> {
try {
const response = await fetch(`${config.url}ping`);
return response.ok;
} catch (error) {
console.error('Registry access verification failed:', error);
return false;
}
}
// File: src/config/logging.ts
import winston from 'winston';
import { config } from './index';
export function createLogger(): winston.Logger {
const transports: winston.transport[] = [];
// Console transport for development
if (config.logging.enableConsole) {
transports.push(new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple()
)
}));
}
// File transport for staging/production
if (config.logging.enableFile) {
transports.push(new winston.transports.File({
filename: process.env.LOG_FILE_PATH || 'subwallet-sdk.log',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
)
}));
}
return winston.createLogger({
level: config.logging.level,
transports
});
}
export const logger = createLogger();
// File: src/config/monitoring.ts
export interface PerformanceMetrics {
requestDuration: number;
memoryUsage: NodeJS.MemoryUsage;
cpuUsage: NodeJS.CpuUsage;
timestamp: Date;
}
export class PerformanceMonitor {
private metrics: PerformanceMetrics[] = [];
captureMetrics(): PerformanceMetrics {
const metric: PerformanceMetrics = {
requestDuration: 0, // Set by individual services
memoryUsage: process.memoryUsage(),
cpuUsage: process.cpuUsage(),
timestamp: new Date()
};
this.metrics.push(metric);
// Keep only last 1000 metrics
if (this.metrics.length > 1000) {
this.metrics.shift();
}
return metric;
}
getAverageMetrics(): Partial<PerformanceMetrics> {
if (this.metrics.length === 0) return {};
const totals = this.metrics.reduce((acc, metric) => ({
requestDuration: acc.requestDuration + metric.requestDuration,
heapUsed: acc.heapUsed + metric.memoryUsage.heapUsed,
external: acc.external + metric.memoryUsage.external
}), { requestDuration: 0, heapUsed: 0, external: 0 });
return {
requestDuration: totals.requestDuration / this.metrics.length,
memoryUsage: {
...process.memoryUsage(),
heapUsed: totals.heapUsed / this.metrics.length,
external: totals.external / this.metrics.length
}
};
}
}
Feature | Development | Staging | Production |
---|---|---|---|
API Endpoints | Localhost | staging.subwallet.io | api.subwallet.io |
Logging Level | debug | info | warn |
Caching | Disabled | Enabled (5min) | Enabled (10min) |
Rate Limiting | Disabled | Enabled | Enabled |
API Keys | Optional | Required | Required |
Encryption | Disabled | Enabled | Enabled |
Monitoring | Basic | Full | Full |
Registry | Local/Public | Private | Private |
# Dockerfile
FROM node:18-alpine
# Set environment variables
ENV NODE_ENV=production
ENV NPM_REGISTRY=https://registry.konistudio.xyz
ENV LOG_LEVEL=info
# Copy configuration
COPY config/ /app/config/
COPY .env.production /app/.env
WORKDIR /app
CMD ["node", "index.js"]
# k8s-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: subwallet-sdk-config
data:
NODE_ENV: "production"
PRICE_HISTORY_API_URL: "https://api.subwallet.io/price-history"
BALANCE_DETECTION_API_URL: "https://api.subwallet.io/balance"
XCM_API_URL: "https://api.subwallet.io/xcm"
CARDANO_API_URL: "https://api.subwallet.io/cardano"
SWAP_API_URL: "https://api.subwallet.io/swap"
LOG_LEVEL: "info"
CACHE_ENABLED: "true"
CACHE_TTL: "600"
Next Steps:
- Review Build Process
- Configure Testing Environment
- Set up Monitoring
Navigation: ← Release Process | Deployment Overview | Development →