#!/usr/bin/env node // plan.js, migration-plan CLI. Demonstrates the migration SDK (lib/migrate.js): // derive a counterfactual PQC account address and print a step-by-step, // honestly-caveated migration plan. Signs and broadcasts NOTHING. // // node plan.js demo (uses the sample Falcon key) // node plan.js --mode pqc --falcon 0x09.. --salt 0 // node plan.js --mode hybrid --falcon 0x09.. --ecdsa 0xYourEoa // node plan.js --json import { readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; import { buildMigrationPlan, predictPqcAccountAddress, ADDRESSES } from './lib/migrate.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); function loadSampleKey() { // The real Falcon-512 public key of the live sample account. // [CITED: aerenew/contracts/deployments/pqc-account.json sampleAccount.falconPubKey] const p = join(__dirname, '..', 'contracts', 'deployments', 'pqc-account.json'); return JSON.parse(readFileSync(p, 'utf8')).sampleAccount.falconPubKey; } function parseArgs(argv) { const a = { mode: 'pqc', salt: 0 }; for (let i = 0; i < argv.length; i++) { const t = argv[i]; if (t === '--mode') a.mode = argv[++i]; else if (t === '--falcon') a.falcon = argv[++i]; else if (t === '--ecdsa') a.ecdsa = argv[++i]; else if (t === '--salt') a.salt = parseInt(argv[++i], 10); else if (t === '--json') a.json = true; else if (t === '--help' || t === '-h') a.help = true; } return a; } function main() { const args = parseArgs(process.argv.slice(2)); if (args.help) { console.log('node plan.js [--mode pqc|hybrid] [--falcon 0x09..] [--ecdsa 0x..] [--salt N] [--json]'); return; } const falcon = args.falcon || loadSampleKey(); const usingSample = !args.falcon; const plan = buildMigrationPlan({ mode: args.mode, falconPubKey: falcon, ecdsaSigner: args.ecdsa, salt: args.salt, }); if (args.json) { console.log(JSON.stringify(plan, null, 2)); return; } console.log(''); console.log(`Aere post-quantum migration plan (mode: ${plan.mode})`); if (usingSample) console.log(' (demo: using the live sample account\'s real Falcon-512 key)'); console.log(''); if (args.mode === 'pqc') { const predicted = predictPqcAccountAddress({ falconPubKey: falcon, salt: args.salt }); console.log(` factory: ${ADDRESSES.AerePQCAccountFactory.address} (live)`); console.log(` derived account: ${predicted}`); console.log(''); } for (const step of plan.steps) { console.log(` Step ${step.n}. ${step.title}`); console.log(` how: ${step.how}`); if (step.result) console.log(` result: ${step.result}`); if (step.identityId) console.log(` identityId: ${step.identityId}`); if (step.calldata) console.log(` calldata: ${step.calldata.slice(0, 42)}... (${(step.calldata.length - 2) / 2} bytes)`); if (step.note) console.log(` note: ${step.note}`); console.log(''); } console.log(' Honest caveats:'); for (const c of plan.caveats) console.log(` - ${c}`); console.log(''); } main();