**Motivations:** - website-skeleton needs a real service contract with valid UUIDs and validators - Service wallet required for production use with configurable public key - Iframe styling needs improvement to remove scrollbars and match UserWallet theme **Root causes:** - DEFAULT_VALIDATEURS used placeholder public key that cannot verify signatures - No service wallet generation script for production deployment - Iframe had fixed height causing scrollbars and visual mismatch with dark theme **Correctifs:** - Created real service contract in src/serviceContract.ts with dedicated UUIDs (skeleton-service-uuid-4nkweb-2026) - Added service wallet generation script (generate-service-wallet.mjs) with .env and .env.private files - Improved iframe container styling: increased height (800px), dark background (#1a1a1a), better shadows, hidden scrollbars - Added .env.private to .gitignore for security **Evolutions:** - Service contract automatically loaded on startup and sent to UserWallet iframe - Public key configurable via VITE_SKELETON_SERVICE_PUBLIC_KEY environment variable - Added npm script 'generate-wallet' for easy wallet generation - Enhanced iframe visual integration with UserWallet dark theme **Pages affectées:** - website-skeleton/src/serviceContract.ts (new) - website-skeleton/src/config.ts - website-skeleton/src/main.ts - website-skeleton/generate-service-wallet.mjs (new) - website-skeleton/index.html - website-skeleton/package.json - website-skeleton/.gitignore - website-skeleton/.env (new) - website-skeleton/.env.private (new)
84 lines
3.0 KiB
JavaScript
Executable File
84 lines
3.0 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Generate a service wallet (secp256k1 key pair) for website-skeleton.
|
|
* Creates .env file with VITE_SKELETON_SERVICE_PUBLIC_KEY and .env.private with private key.
|
|
*/
|
|
|
|
import { getPublicKey, utils as secpUtils } from '@noble/secp256k1';
|
|
import { bytesToHex } from '@noble/hashes/utils';
|
|
import { writeFileSync, existsSync } from 'fs';
|
|
import { join } from 'path';
|
|
import { webcrypto } from 'crypto';
|
|
|
|
// Set up crypto for @noble/secp256k1 in Node.js
|
|
if (typeof globalThis.crypto === 'undefined') {
|
|
globalThis.crypto = webcrypto;
|
|
}
|
|
|
|
// Generate key pair
|
|
const privateKeyBytes = secpUtils.randomSecretKey();
|
|
const publicKeyBytes = getPublicKey(privateKeyBytes, true); // compressed
|
|
const privateKey = bytesToHex(privateKeyBytes);
|
|
const publicKey = bytesToHex(publicKeyBytes);
|
|
|
|
// Verify format
|
|
if (publicKey.length !== 66 || (!publicKey.startsWith('02') && !publicKey.startsWith('03'))) {
|
|
throw new Error(`Invalid public key format: ${publicKey}`);
|
|
}
|
|
if (privateKey.length !== 64) {
|
|
throw new Error(`Invalid private key format: ${privateKey}`);
|
|
}
|
|
|
|
// Paths
|
|
const envPath = join(process.cwd(), '.env');
|
|
const envPrivatePath = join(process.cwd(), '.env.private');
|
|
|
|
// Check if .env already exists
|
|
if (existsSync(envPath)) {
|
|
console.warn('⚠️ .env already exists. Backing up to .env.backup');
|
|
const { readFileSync } = await import('fs');
|
|
const backup = readFileSync(envPath, 'utf-8');
|
|
writeFileSync(join(process.cwd(), '.env.backup'), backup);
|
|
}
|
|
|
|
// Write .env with public key
|
|
const envContent = `# Service wallet public key for website-skeleton
|
|
# Generated on ${new Date().toISOString()}
|
|
# Service UUID: 32b9095a-562d-4239-ae45-2d7ffb1a40de
|
|
VITE_SKELETON_SERVICE_PUBLIC_KEY=${publicKey}
|
|
`;
|
|
|
|
writeFileSync(envPath, envContent, { mode: 0o600 });
|
|
|
|
// Write .env.private with private key (more restrictive permissions)
|
|
const envPrivateContent = `# Service wallet private key for website-skeleton
|
|
# ⚠️ SECRET: Keep this file secure and never commit it to version control
|
|
# Generated on ${new Date().toISOString()}
|
|
# Service UUID: 32b9095a-562d-4239-ae45-2d7ffb1a40de
|
|
#
|
|
# This private key is used to sign service operations.
|
|
# Store it securely and never share it.
|
|
SKELETON_SERVICE_PRIVATE_KEY=${privateKey}
|
|
`;
|
|
|
|
writeFileSync(envPrivatePath, envPrivateContent, { mode: 0o400 });
|
|
|
|
console.log('✅ Service wallet generated successfully!');
|
|
console.log('');
|
|
console.log('📁 Files created:');
|
|
console.log(` - .env (public key, mode 600)`);
|
|
console.log(` - .env.private (private key, mode 400)`);
|
|
console.log('');
|
|
console.log('🔑 Public key (for VITE_SKELETON_SERVICE_PUBLIC_KEY):');
|
|
console.log(` ${publicKey}`);
|
|
console.log('');
|
|
console.log('🔐 Private key (stored in .env.private):');
|
|
console.log(` ${privateKey}`);
|
|
console.log('');
|
|
console.log('⚠️ Security notes:');
|
|
console.log(' - .env.private contains the private key - keep it secure');
|
|
console.log(' - Add .env.private to .gitignore if not already present');
|
|
console.log(' - The public key in .env is safe to commit');
|
|
console.log(' - Never share the private key');
|