UNPKG

beeline-cli

Version:

A terminal wallet for the Hive blockchain - type, sign, rule the chain

229 lines โ€ข 12.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("@oclif/core"); const neon_js_1 = require("../utils/neon.js"); const crypto_js_1 = require("../utils/crypto.js"); const hive_js_1 = require("../utils/hive.js"); const inquirer_1 = __importDefault(require("inquirer")); class Login extends core_1.Command { async run() { const { args, flags } = await this.parse(Login); let account = args.account; // Clean @ prefix if provided if (account.startsWith('@')) { account = account.substring(1); } const keyManager = new crypto_js_1.KeyManager(); await keyManager.initialize(); // Check if this is the first time using beeline const existingAccounts = await keyManager.listAccounts(); const isFirstTime = existingAccounts.length === 0; if (isFirstTime) { await this.showWelcomeSequence(); } console.log(neon_js_1.neonChalk.glow(`${neon_js_1.neonSymbols.diamond} Initiating secure login for ${neon_js_1.neonChalk.highlight('@' + account)}...`)); console.log(''); // Check if account already exists const hasAccount = await keyManager.hasAccount(account); if (hasAccount && !flags.force) { const confirmPrompt = await inquirer_1.default.prompt([{ type: 'confirm', name: 'confirm', message: neon_js_1.neonChalk.warning(`Account @${account} already exists in vault. Overwrite keys?`), default: false }]); if (!confirmPrompt.confirm) { console.log(neon_js_1.neonChalk.info('Login cancelled')); return; } } // Parse roles const requestedRoles = flags.roles.split(',').map(r => r.trim()); const validRoles = ['owner', 'active', 'posting', 'memo']; const roles = requestedRoles.filter(role => validRoles.includes(role)); if (roles.length === 0) { console.log(neon_js_1.neonChalk.error(`${neon_js_1.neonSymbols.cross} Invalid roles specified. Valid roles: owner, active, posting, memo`)); return; } // Verify account exists on blockchain if (flags.verify) { const verifySpinner = (0, neon_js_1.neonSpinner)('Verifying account on Hive blockchain'); try { const hiveClient = new hive_js_1.HiveClient(keyManager); const accountData = await hiveClient.getAccount(account); clearInterval(verifySpinner); process.stdout.write('\r' + ' '.repeat(80) + '\r'); if (!accountData) { console.log(neon_js_1.neonChalk.error(`${neon_js_1.neonSymbols.cross} Account @${account} not found on Hive blockchain`)); console.log(neon_js_1.neonChalk.info('Use --no-verify to skip this check')); return; } console.log(neon_js_1.neonChalk.success(`${neon_js_1.neonSymbols.check} Account verified on blockchain`)); console.log(''); } catch (error) { clearInterval(verifySpinner); process.stdout.write('\r' + ' '.repeat(80) + '\r'); console.log(neon_js_1.neonChalk.warning(`${neon_js_1.neonSymbols.warning} Could not verify account: ${error instanceof Error ? error.message : 'Unknown error'}`)); console.log(neon_js_1.neonChalk.info('Proceeding anyway...')); console.log(''); } } // Get master password const passwordPrompt = await inquirer_1.default.prompt([{ type: 'password', name: 'password', message: neon_js_1.neonChalk.cyan('Master password:'), validate: (input) => input.length > 0 || 'Password required' }]); // Get PIN if enabled let pin; if (flags.pin) { const pinPrompt = await inquirer_1.default.prompt([{ type: 'password', name: 'pin', message: neon_js_1.neonChalk.cyan('Set encryption PIN (4+ characters):'), validate: (input) => input.length >= 4 || 'PIN must be at least 4 characters' }]); pin = pinPrompt.pin; } // Display login details const loginDetails = [ `${neon_js_1.neonChalk.cyan('ACCOUNT')} ${neon_js_1.neonSymbols.arrow} ${neon_js_1.neonChalk.highlight('@' + account)}`, `${neon_js_1.neonChalk.magenta('ROLES')} ${neon_js_1.neonSymbols.arrow} ${neon_js_1.neonChalk.white(roles.join(', '))}`, `${neon_js_1.neonChalk.electric('SECURITY')} ${neon_js_1.neonSymbols.arrow} ${flags.pin ? neon_js_1.neonChalk.success('PIN protected') : neon_js_1.neonChalk.warning('OS keychain only')}`, ``, `${neon_js_1.neonChalk.darkCyan('Keys will be derived from your master password')}` ].join('\n'); console.log((0, neon_js_1.createNeonBox)(loginDetails, `${neon_js_1.neonSymbols.star} LOGIN CONFIGURATION ${neon_js_1.neonSymbols.star}`)); console.log(''); const loginSpinner = (0, neon_js_1.neonSpinner)('Deriving keys from master password'); try { // Perform login with password derivation await keyManager.loginWithPassword(account, passwordPrompt.password, pin, roles); clearInterval(loginSpinner); process.stdout.write('\r' + ' '.repeat(80) + '\r'); console.log(neon_js_1.neonChalk.success(`${neon_js_1.neonSymbols.check} Login successful!`)); console.log(''); // Get account summary const summary = await keyManager.getAccountSummary(account); const successMessage = [ `${neon_js_1.neonChalk.glow('Welcome to the neon grid, runner')}`, ``, `${neon_js_1.neonChalk.cyan('Account:')} @${account}`, `${neon_js_1.neonChalk.magenta('Keys imported:')} ${summary?.roles.join(', ')}`, `${neon_js_1.neonChalk.electric('Security level:')} ${flags.pin ? 'Maximum (PIN + OS keychain)' : 'Standard (OS keychain)'}`, summary?.isDefault ? `${neon_js_1.neonChalk.success('Set as default account')}` : '', ``, `${neon_js_1.neonChalk.info('Your wallet is ready for blockchain operations')}` ].filter(Boolean).join('\n'); console.log((0, neon_js_1.createNeonBox)(successMessage, `${neon_js_1.neonSymbols.star} LOGIN COMPLETE ${neon_js_1.neonSymbols.star}`)); console.log(''); // Next steps if (isFirstTime) { console.log(neon_js_1.neonChalk.pulse('๐ŸŽ‰ Your wallet is now ready! Next steps:')); console.log(neon_js_1.neonChalk.darkCyan(`${neon_js_1.neonSymbols.bullet} Check balance: ${neon_js_1.neonChalk.highlight('beeline balance')}`)); console.log(neon_js_1.neonChalk.darkCyan(`${neon_js_1.neonSymbols.bullet} Test safely: ${neon_js_1.neonChalk.highlight('beeline balance --mock')}`)); console.log(neon_js_1.neonChalk.darkCyan(`${neon_js_1.neonSymbols.bullet} Send transfer: ${neon_js_1.neonChalk.highlight('beeline transfer @recipient 1 HIVE')}`)); console.log(neon_js_1.neonChalk.darkCyan(`${neon_js_1.neonSymbols.bullet} Add more accounts: ${neon_js_1.neonChalk.highlight('beeline login <account>')}`)); console.log(neon_js_1.neonChalk.darkCyan(`${neon_js_1.neonSymbols.bullet} View help: ${neon_js_1.neonChalk.highlight('beeline --help')}`)); } else { console.log(neon_js_1.neonChalk.pulse('Next steps:')); console.log(neon_js_1.neonChalk.darkCyan(`${neon_js_1.neonSymbols.bullet} Check balance: ${neon_js_1.neonChalk.highlight('beeline balance')}`)); console.log(neon_js_1.neonChalk.darkCyan(`${neon_js_1.neonSymbols.bullet} Send transfer: ${neon_js_1.neonChalk.highlight('beeline transfer @recipient 1 HIVE')}`)); console.log(neon_js_1.neonChalk.darkCyan(`${neon_js_1.neonSymbols.bullet} Manage accounts: ${neon_js_1.neonChalk.highlight('beeline accounts list')}`)); } // Memory scrubbing keyManager.scrubMemory(passwordPrompt.password); if (pin) keyManager.scrubMemory(pin); } catch (error) { clearInterval(loginSpinner); process.stdout.write('\r' + ' '.repeat(80) + '\r'); console.log(neon_js_1.neonChalk.error(`${neon_js_1.neonSymbols.cross} Login failed: ${error instanceof Error ? error.message : 'Unknown error'}`)); console.log(''); console.log(neon_js_1.neonChalk.info('Possible causes:')); console.log(neon_js_1.neonChalk.darkCyan('โ€ข Incorrect master password')); console.log(neon_js_1.neonChalk.darkCyan('โ€ข Invalid account name')); console.log(neon_js_1.neonChalk.darkCyan('โ€ข Network connectivity issues')); // Memory scrubbing on error keyManager.scrubMemory(passwordPrompt.password); if (pin) keyManager.scrubMemory(pin); } } async showWelcomeSequence() { console.clear(); // Display cyberpunk grid console.log((0, neon_js_1.createNeonGrid)(80)); // Main banner const banner = await (0, neon_js_1.createNeonBanner)('BEELINE'); console.log(banner); // Tagline console.log(neon_js_1.neonChalk.accent(' โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—')); console.log(neon_js_1.neonChalk.accent(' โ•‘ ') + neon_js_1.neonChalk.glow('H I V E T E R M I N A L W A L L E T') + neon_js_1.neonChalk.accent(' ยท ') + neon_js_1.neonChalk.pulse('N E O N G R I D') + neon_js_1.neonChalk.accent(' โ•‘')); console.log(neon_js_1.neonChalk.accent(' โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•')); console.log(''); // Welcome message const welcomeMessage = [ `${neon_js_1.neonChalk.glow('Welcome to the neon grid, runner.')}`, ``, `${neon_js_1.neonChalk.cyan('Your cyberpunk terminal wallet is initializing...')}`, ``, `${neon_js_1.neonChalk.info('Security features:')}`, `${neon_js_1.neonChalk.darkCyan('โ”œโ”€')} ${neon_js_1.neonChalk.success('PIN encryption')} for maximum security`, `${neon_js_1.neonChalk.darkCyan('โ”œโ”€')} ${neon_js_1.neonChalk.success('OS keychain')} integration`, `${neon_js_1.neonChalk.darkCyan('โ”œโ”€')} ${neon_js_1.neonChalk.success('Memory scrubbing')} prevents key recovery`, `${neon_js_1.neonChalk.darkCyan('โ””โ”€')} ${neon_js_1.neonChalk.success('Mock mode')} for safe testing`, ``, `${neon_js_1.neonChalk.pulse('Type, sign, rule the chain.')}` ].join('\n'); console.log((0, neon_js_1.createNeonBox)(welcomeMessage, `${neon_js_1.neonSymbols.star} WALLET INITIALIZATION ${neon_js_1.neonSymbols.star}`)); console.log(''); // Brief pause for effect await new Promise(resolve => setTimeout(resolve, 2000)); } } Login.description = 'Login to your Hive account with master password'; Login.examples = [ `$ beeline login alice`, `$ beeline login alice --roles posting,active`, `$ beeline login alice --no-pin` ]; Login.flags = { roles: core_1.Flags.string({ char: 'r', description: 'key roles to import (comma-separated)', default: 'posting,active,memo' }), pin: core_1.Flags.boolean({ char: 'p', description: 'use PIN encryption for key storage', default: true, allowNo: true }), verify: core_1.Flags.boolean({ char: 'v', description: 'verify account exists on blockchain', default: true, allowNo: true }), force: core_1.Flags.boolean({ char: 'f', description: 'overwrite existing keys without confirmation', default: false }) }; Login.args = { account: core_1.Args.string({ description: 'Hive account name', required: true }) }; exports.default = Login; //# sourceMappingURL=login.js.map