beeline-cli
Version:
A terminal wallet for the Hive blockchain - type, sign, rule the chain
220 lines • 11.6 kB
JavaScript
;
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 Withdraw extends core_1.Command {
async run() {
const { args, flags } = await this.parse(Withdraw);
const keyManager = new crypto_js_1.KeyManager();
await keyManager.initialize();
let fromAccount = flags.from;
let toAccount = args.to;
// Clean @ prefix if provided
if (fromAccount?.startsWith('@')) {
fromAccount = fromAccount.substring(1);
}
if (toAccount?.startsWith('@')) {
toAccount = toAccount.substring(1);
}
// Use default account if no from account specified
if (!fromAccount) {
fromAccount = keyManager.getDefaultAccount();
if (!fromAccount) {
console.log(neon_js_1.neonChalk.warning(`${neon_js_1.neonSymbols.cross} No account specified and no default account set`));
console.log(neon_js_1.neonChalk.info('Import a key first with: ') + neon_js_1.neonChalk.highlight('beeline keys import <account> active'));
return;
}
}
// If no to account specified, withdraw to self
if (!toAccount) {
toAccount = fromAccount;
}
// Validate amount format
const amount = parseFloat(args.amount);
if (isNaN(amount) || amount <= 0) {
console.log(neon_js_1.neonChalk.error(`${neon_js_1.neonSymbols.cross} Invalid amount: ${args.amount}`));
return;
}
const currency = args.currency;
const memo = args.memo || '';
// Generate unique request ID (timestamp-based)
const requestId = Date.now() % 1000000; // Keep it reasonable length
console.log(neon_js_1.neonChalk.glow(`${neon_js_1.neonSymbols.diamond} Preparing savings withdrawal...`));
console.log('');
// Display withdrawal details
const withdrawalDetails = [
`${neon_js_1.neonChalk.cyan('FROM')} ${neon_js_1.neonSymbols.arrow} ${neon_js_1.neonChalk.highlight('@' + fromAccount)} ${neon_js_1.neonChalk.darkCyan('(savings)')}`,
`${neon_js_1.neonChalk.magenta('TO')} ${neon_js_1.neonSymbols.arrow} ${neon_js_1.neonChalk.highlight('@' + toAccount)}`,
`${neon_js_1.neonChalk.electric('AMOUNT')} ${neon_js_1.neonSymbols.arrow} ${neon_js_1.neonChalk.white(amount.toFixed(3))} ${neon_js_1.neonChalk.yellow(currency)}`,
`${neon_js_1.neonChalk.orange('REQ ID')} ${neon_js_1.neonSymbols.arrow} ${neon_js_1.neonChalk.white(requestId.toString())}`,
memo ? `${neon_js_1.neonChalk.pink('MEMO')} ${neon_js_1.neonSymbols.arrow} ${neon_js_1.neonChalk.white('"' + memo + '"')}` : '',
``,
`${neon_js_1.neonChalk.warning('⚠️ Withdrawal takes 3 DAYS to process')}`,
`${neon_js_1.neonChalk.info('💡 You can cancel during the 3-day waiting period')}`,
`${neon_js_1.neonChalk.info('💡 Use the request ID above to track/cancel')}`,
`${neon_js_1.neonChalk.darkCyan('Transaction will be signed with your active key')}`
].filter(Boolean).join('\n');
console.log((0, neon_js_1.createNeonBox)(withdrawalDetails, `${neon_js_1.neonSymbols.star} SAVINGS WITHDRAWAL PREVIEW ${neon_js_1.neonSymbols.star}`));
console.log('');
if (flags.mock) {
console.log(neon_js_1.neonChalk.warning(`${neon_js_1.neonSymbols.star} Mock mode - transaction will NOT be broadcast`));
console.log('');
}
// Confirmation prompt
if (!flags.confirm) {
const confirmPrompt = await inquirer_1.default.prompt([{
type: 'confirm',
name: 'confirm',
message: flags.mock ?
neon_js_1.neonChalk.cyan('Simulate this savings withdrawal?') :
neon_js_1.neonChalk.warning('Execute this savings withdrawal? It will take 3 days to process.'),
default: false
}]);
if (!confirmPrompt.confirm) {
console.log(neon_js_1.neonChalk.info('Savings withdrawal cancelled'));
return;
}
}
if (flags.mock) {
return this.simulateWithdrawal(fromAccount, toAccount, amount, currency, requestId, memo);
}
// Get PIN for key decryption
const keys = await keyManager.listKeys(fromAccount);
const activeKey = keys.find(k => k.role === 'active');
if (!activeKey) {
console.log(neon_js_1.neonChalk.error(`${neon_js_1.neonSymbols.cross} Active key not found for account @${fromAccount}`));
console.log(neon_js_1.neonChalk.info('Import active key with: ') + neon_js_1.neonChalk.highlight(`beeline keys import ${fromAccount} active`));
return;
}
let pin;
if (activeKey.encrypted) {
const pinPrompt = await inquirer_1.default.prompt([{
type: 'password',
name: 'pin',
message: neon_js_1.neonChalk.cyan('Enter PIN to unlock active key:'),
validate: (input) => input.length > 0 || 'PIN required'
}]);
pin = pinPrompt.pin;
}
const spinner = (0, neon_js_1.neonSpinner)('Broadcasting to Hive blockchain');
try {
const hiveClient = new hive_js_1.HiveClient(keyManager, flags.node);
// Execute savings withdrawal
const txId = await hiveClient.transferFromSavings(fromAccount, requestId, toAccount, amount.toFixed(3), currency, memo, pin);
clearInterval(spinner);
process.stdout.write('\r' + ' '.repeat(80) + '\r');
console.log(neon_js_1.neonChalk.success(`${neon_js_1.neonSymbols.check} Savings withdrawal initiated!`));
console.log('');
const successMessage = [
`${neon_js_1.neonChalk.glow('Savings withdrawal transaction broadcast successfully')}`,
``,
`${neon_js_1.neonChalk.cyan('Transaction ID:')} ${neon_js_1.neonChalk.highlight(txId)}`,
`${neon_js_1.neonChalk.magenta('From:')} @${fromAccount} (savings)`,
`${neon_js_1.neonChalk.electric('To:')} @${toAccount}`,
`${neon_js_1.neonChalk.orange('Amount:')} ${amount.toFixed(3)} ${currency}`,
`${neon_js_1.neonChalk.pink('Request ID:')} ${requestId}`,
memo ? `${neon_js_1.neonChalk.white('Memo:')} "${memo}"` : '',
`${neon_js_1.neonChalk.yellow('Status:')} Withdrawal initiated - processing for 3 days`,
``,
`${neon_js_1.neonChalk.info('Funds will be available in 3 days')}`,
`${neon_js_1.neonChalk.info('You can cancel before completion if needed')}`
].filter(Boolean).join('\n');
console.log((0, neon_js_1.createNeonBox)(successMessage, `${neon_js_1.neonSymbols.star} SAVINGS WITHDRAWAL INITIATED ${neon_js_1.neonSymbols.star}`));
// Memory scrubbing
if (pin)
keyManager.scrubMemory(pin);
}
catch (error) {
clearInterval(spinner);
process.stdout.write('\r' + ' '.repeat(80) + '\r');
console.log(neon_js_1.neonChalk.error(`${neon_js_1.neonSymbols.cross} Savings withdrawal 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('• Insufficient savings balance'));
console.log(neon_js_1.neonChalk.darkCyan('• Invalid recipient account'));
console.log(neon_js_1.neonChalk.darkCyan('• Network connectivity issues'));
console.log(neon_js_1.neonChalk.darkCyan('• Incorrect PIN'));
console.log(neon_js_1.neonChalk.darkCyan('• Duplicate request ID (try again)'));
// Memory scrubbing on error too
if (pin)
keyManager.scrubMemory(pin);
}
}
simulateWithdrawal(from, to, amount, currency, requestId, memo) {
console.log(neon_js_1.neonChalk.glow(`${neon_js_1.neonSymbols.diamond} Simulating savings withdrawal...`));
console.log('');
// Simulate some processing time
setTimeout(() => {
const mockTxId = '0x' + Math.random().toString(16).substring(2, 18);
console.log(neon_js_1.neonChalk.success(`${neon_js_1.neonSymbols.check} Savings withdrawal simulation complete!`));
console.log('');
const simulationMessage = [
`${neon_js_1.neonChalk.warning('SIMULATION ONLY - NO REAL WITHDRAWAL')}`,
``,
`${neon_js_1.neonChalk.cyan('Mock Transaction ID:')} ${neon_js_1.neonChalk.highlight(mockTxId)}`,
`${neon_js_1.neonChalk.magenta('From:')} @${from} (savings)`,
`${neon_js_1.neonChalk.electric('To:')} @${to}`,
`${neon_js_1.neonChalk.orange('Amount:')} ${amount.toFixed(3)} ${currency}`,
`${neon_js_1.neonChalk.pink('Mock Request ID:')} ${requestId}`,
memo ? `${neon_js_1.neonChalk.white('Memo:')} "${memo}"` : '',
`${neon_js_1.neonChalk.yellow('Mock Status:')} Would process for 3 days`,
``,
`${neon_js_1.neonChalk.info('Remove --mock flag to execute real withdrawal')}`
].filter(Boolean).join('\n');
console.log((0, neon_js_1.createNeonBox)(simulationMessage, `${neon_js_1.neonSymbols.star} SIMULATION RESULT ${neon_js_1.neonSymbols.star}`));
}, 1500);
}
}
Withdraw.description = 'Withdraw HIVE or HBD from savings (3-day processing time) with cyberpunk style';
Withdraw.examples = [
`$ beeline withdraw 100 HIVE`,
`$ beeline withdraw 50.000 HBD @alice`,
`$ beeline withdraw 1000 HIVE @alice --from @business "Emergency withdrawal"`
];
Withdraw.flags = {
from: core_1.Flags.string({
char: 'f',
description: 'account to withdraw from (defaults to default account)'
}),
node: core_1.Flags.string({
char: 'n',
description: 'RPC node to use'
}),
confirm: core_1.Flags.boolean({
char: 'y',
description: 'skip confirmation prompt',
default: false
}),
mock: core_1.Flags.boolean({
char: 'm',
description: 'simulate withdrawal without broadcasting',
default: false
})
};
Withdraw.args = {
amount: core_1.Args.string({
description: 'amount to withdraw from savings',
required: true
}),
currency: core_1.Args.string({
description: 'currency (HIVE or HBD)',
required: true,
options: ['HIVE', 'HBD']
}),
to: core_1.Args.string({
description: 'account to withdraw to (defaults to from account)',
required: false
}),
memo: core_1.Args.string({
description: 'withdrawal memo',
required: false
})
};
exports.default = Withdraw;
//# sourceMappingURL=withdraw.js.map