cdp-wallet-onramp-kit
Version:
Complete toolkit for Coinbase Developer Platform (CDP) Embedded Wallets and Onramp integration with reusable components, utilities, and documentation
283 lines (245 loc) • 8 kB
text/typescript
/**
* Environment validation utilities for CDP Wallet & Onramp integration
* Helps developers debug configuration issues
*/
export interface ValidationResult {
isValid: boolean;
errors: string[];
warnings: string[];
suggestions: string[];
}
export interface EnvironmentStatus {
projectId: ValidationResult;
apiKey: ValidationResult;
apiKeyName: ValidationResult;
structure: ValidationResult;
overall: ValidationResult;
}
/**
* Validate CDP project ID
*/
export function validateProjectId(): ValidationResult {
const projectId = process.env.NEXT_PUBLIC_CDP_PROJECT_ID;
if (!projectId) {
return {
isValid: false,
errors: ['NEXT_PUBLIC_CDP_PROJECT_ID is not set'],
warnings: [],
suggestions: [
'Add NEXT_PUBLIC_CDP_PROJECT_ID=your-project-id to your .env.local file',
'Get your project ID from https://portal.cdp.coinbase.com'
]
};
}
// Check format (UUID-like)
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
if (!uuidPattern.test(projectId)) {
return {
isValid: false,
errors: ['Project ID format appears invalid'],
warnings: [],
suggestions: [
'Project ID should be a UUID format like: 12345678-1234-1234-1234-123456789012',
'Double-check your project ID in CDP Portal'
]
};
}
return {
isValid: true,
errors: [],
warnings: [],
suggestions: []
};
}
/**
* Validate CDP API credentials for server-side operations
*/
export function validateApiCredentials(): ValidationResult {
const apiKeyName = process.env.CDP_API_KEY_NAME;
const privateKey = process.env.CDP_API_KEY_PRIVATE_KEY;
const errors: string[] = [];
const warnings: string[] = [];
const suggestions: string[] = [];
if (!apiKeyName) {
errors.push('CDP_API_KEY_NAME is not set');
suggestions.push('Add CDP_API_KEY_NAME=your-api-key-name to your .env.local file');
}
if (!privateKey) {
errors.push('CDP_API_KEY_PRIVATE_KEY is not set');
suggestions.push('Add CDP_API_KEY_PRIVATE_KEY=your-private-key to your .env.local file');
}
if (privateKey && privateKey.length < 50) {
warnings.push('Private key appears too short - may be incomplete');
suggestions.push('Ensure you copied the complete private key from CDP Portal');
}
if (errors.length === 0 && warnings.length === 0) {
return {
isValid: true,
errors: [],
warnings: [],
suggestions: ['API credentials look good! 🎉']
};
}
return {
isValid: errors.length === 0,
errors,
warnings,
suggestions: [
...suggestions,
'Create API credentials at: https://portal.cdp.coinbase.com → API Keys → Secret API Keys'
]
};
}
/**
* Validate project structure for Next.js compatibility
*/
export function validateProjectStructure(): ValidationResult {
const hasApp = require('fs').existsSync('app');
const hasSrcApp = require('fs').existsSync('src/app');
const hasPages = require('fs').existsSync('pages');
const hasSrcPages = require('fs').existsSync('src/pages');
const errors: string[] = [];
const warnings: string[] = [];
const suggestions: string[] = [];
if (!hasApp && !hasSrcApp && !hasPages && !hasSrcPages) {
errors.push('No Next.js structure detected (no app/ or pages/ directory found)');
suggestions.push('Ensure you are in a Next.js project directory');
suggestions.push('Run this command from your Next.js project root');
} else if (hasPages || hasSrcPages) {
warnings.push('Pages Router detected - CDP components designed for App Router');
suggestions.push('Consider migrating to Next.js App Router for best compatibility');
suggestions.push('Or check component compatibility with Pages Router');
} else if (hasApp || hasSrcApp) {
suggestions.push('App Router detected - perfect for CDP components! 🎉');
}
return {
isValid: errors.length === 0,
errors,
warnings,
suggestions
};
}
/**
* Run comprehensive environment validation
*/
export function validateCDPEnvironment(): EnvironmentStatus {
const projectId = validateProjectId();
const apiKey = validateApiCredentials();
const apiKeyName = { ...apiKey }; // Same validation for now
const structure = validateProjectStructure();
const allErrors = [
...projectId.errors,
...apiKey.errors,
...structure.errors
];
const allWarnings = [
...projectId.warnings,
...apiKey.warnings,
...structure.warnings
];
const allSuggestions = [
...projectId.suggestions,
...apiKey.suggestions,
...structure.suggestions
];
const overall: ValidationResult = {
isValid: allErrors.length === 0,
errors: allErrors,
warnings: allWarnings,
suggestions: allSuggestions
};
return {
projectId,
apiKey,
apiKeyName,
structure,
overall
};
}
/**
* Format validation results for console output
*/
export function formatValidationResults(status: EnvironmentStatus): string {
const sections: string[] = [];
sections.push('🔍 CDP Environment Validation Results');
sections.push('='.repeat(50));
// Overall status
if (status.overall.isValid) {
sections.push('✅ Overall Status: READY TO GO! 🎉');
} else {
sections.push('❌ Overall Status: Issues found that need attention');
}
sections.push('');
// Project ID
sections.push('📋 Project ID:');
if (status.projectId.isValid) {
sections.push(' ✅ Valid');
} else {
status.projectId.errors.forEach(error => sections.push(` ❌ ${error}`));
}
// API Credentials
sections.push('🔑 API Credentials:');
if (status.apiKey.isValid) {
sections.push(' ✅ Valid');
} else {
status.apiKey.errors.forEach(error => sections.push(` ❌ ${error}`));
}
status.apiKey.warnings.forEach(warning => sections.push(` ⚠️ ${warning}`));
// Project Structure
sections.push('📁 Project Structure:');
if (status.structure.isValid) {
sections.push(' ✅ Compatible');
} else {
status.structure.errors.forEach(error => sections.push(` ❌ ${error}`));
}
status.structure.warnings.forEach(warning => sections.push(` ⚠️ ${warning}`));
// Suggestions
if (status.overall.suggestions.length > 0) {
sections.push('');
sections.push('💡 Suggestions:');
status.overall.suggestions.forEach(suggestion => sections.push(` • ${suggestion}`));
}
sections.push('');
sections.push('Need help? Check: https://docs.cdp.coinbase.com/');
return sections.join('\n');
}
/**
* Quick validation check - returns true if environment is ready
*/
export function isEnvironmentReady(): boolean {
const status = validateCDPEnvironment();
return status.overall.isValid;
}
/**
* Test CDP API connectivity (async validation)
*/
export async function testCDPConnectivity(): Promise<ValidationResult> {
try {
// This would require the actual CDP SDK to test connectivity
// For now, just validate that credentials are present
const apiValidation = validateApiCredentials();
const projectValidation = validateProjectId();
if (!apiValidation.isValid || !projectValidation.isValid) {
return {
isValid: false,
errors: ['Cannot test connectivity - missing credentials'],
warnings: [],
suggestions: ['Fix credential issues first, then test connectivity']
};
}
// TODO: Add actual CDP API connectivity test
return {
isValid: true,
errors: [],
warnings: ['Connectivity test not implemented yet'],
suggestions: ['Credentials look good - try using CDP components to test']
};
} catch (error) {
return {
isValid: false,
errors: [`Connectivity test failed: ${error instanceof Error ? error.message : 'Unknown error'}`],
warnings: [],
suggestions: ['Check your internet connection and CDP credentials']
};
}
}