#!/usr/bin/env node var bcoin = require('bcoin'); var utils = bcoin.utils; var assert = utils.assert; var Client = bcoin.http.client; var argv = parseArg(process.argv); if (argv.network) bcoin.protocol.network.set(argv.network); var client = new Client(argv.url || 'localhost:8080', { setNetwork: argv.network == null }); function getID() { if (process.env.BCOIN_WALLET_ID) return process.env.BCOIN_WALLET_ID; if (argv.id) return argv.id; return argv.args.shift(); } function createWallet(callback) { var options = { id: getID() }; if (argv.type) options.type = argv.type; if (argv.master) options.master = argv.master; if (argv.keys) options.keys = argv.keys.split(/[,:]/); if (argv.lookahead) options.lookahead = argv.lookahead >>> 0; if (argv.derivation) options.derivation = argv.derivation; if (argv.m) options.m = argv.m >>> 0; if (argv.n) options.n = argv.n >>> 0; if (argv.copay != null) options.copayBIP45 = !!argv.copay; if (argv.witness != null) options.witness = !!argv.witness; if (argv.passphrase) options.passphrase = argv.passphrase; client.createWallet(options, function(err, wallet) { if (err) return callback(err); utils.print(wallet); wallet.destroy(); callback(); }); } function addKey(callback) { var id = getID(); var keys = argv.keys || argv.key; if (keys) keys = keys.split(','); else keys = argv.args; client.addKey(id, keys, function(err, wallet) { if (err) return callback(err); utils.print('added'); callback(); }); } function removeKey(callback) { var id = getID(); var keys = argv.keys || argv.key; if (keys) keys = keys.split(','); else keys = argv.args; client.removeKey(id, keys, function(err) { if (err) return callback(err); utils.print('removed'); callback(); }); } function getWallet(callback) { var id = getID(); var passphrase = argv.args[0]; client.getWallet(id, passphrase, function(err, wallet) { if (err) return callback(err); utils.print(wallet); wallet.destroy(); callback(); }); } function getTX(callback) { var hash = argv.args[0]; if (bcoin.address.validate(hash)) { return client.getTXByAddress(hash, function(err, txs) { if (err) return callback(err); utils.print(txs); callback(); }); } hash = utils.revHex(hash); client.getTX(hash, function(err, tx) { if (err) return callback(err); utils.print(tx); callback(); }); } function getBlock(callback) { var hash = argv.args[0]; hash = utils.revHex(hash); client.getBlock(hash, function(err, block) { if (err) return callback(err); utils.print(block); callback(); }); } function getCoin(callback) { var hash = argv.args[0]; var index = argv.args[1]; if (bcoin.address.validate(hash)) { return client.getCoinsByAddress(hash, function(err, coins) { if (err) return callback(err); utils.print(coins); callback(); }); } hash = utils.revHex(hash); client.getCoin(hash, index, function(err, coin) { if (err) return callback(err); utils.print(coin); callback(); }); } function getWalletAll(callback) { var id = getID(); client.getWalletAll(id, function(err, txs) { if (err) return callback(err); utils.print(txs); callback(); }); } function getBalance(callback) { var id = getID(); client.getWalletBalance(id, function(err, balance) { if (err) return callback(err); utils.print('Confirmed: %s', utils.btc(balance.confirmed)); utils.print('Unconfirmed: %s', utils.btc(balance.unconfirmed)); callback(); }); } function getMempool(callback) { client.getMempool(function(err, txs) { if (err) return callback(err); utils.print(txs); callback(); }); } function send(callback) { var id = getID(); var options = {}; if (argv.script) { options.script = new bcoin.script(new Buffer(argv.script, 'hex')); options.value = utils.satoshi(argv.value || argv.args[0]); } else { options.address = argv.address || argv.args[0]; options.value = utils.satoshi(argv.value || argv.args[1]); } client.walletSend(id, options, function(err, tx) { if (err) return callback(err); utils.print(tx); callback(); }); } function zap(callback) { var id = getID(); var now = (argv.now >>> 0) || utils.now(); var age = (argv.age >>> 0) || 72 * 60 * 60; client.walletZap(id, now, age, function(err) { if (err) return callback(err); utils.print('zapped'); callback(); }); } function main(callback) { switch (argv.args.shift()) { case 'wallet': return createWallet(callback); case 'getwallet': return getWallet(callback); case 'addkey': return addKey(callback); case 'rmkey': return removeKey(callback); case 'balance': return getBalance(callback); case 'history': return getWalletAll(callback); case 'send': return send(callback); case 'zap': return zap(callback); case 'mempool': return getMempool(callback); case 'tx': return getTX(callback); case 'coin': return getCoin(callback); case 'block': return getBlock(callback); default: utils.print('Unrecognized command.'); utils.print('Commands:'); utils.print(' $ wallet [id] --keys [hdkeys]' + ' --type [pubkeyhash/multisig] -m [m-value]' + ' -n [n-value] --witness: View or create wallet by ID.'); utils.print(' $ getwallet [id]: View wallet by ID.'); utils.print(' $ addkey [id] --keys [hdkeys]: Add keys to wallet.'); utils.print(' $ rmkey [id] --keys [hdkeys]: Remove keys from wallet.'); utils.print(' $ balance [id]: Get wallet balance.'); utils.print(' $ history [id]: View wallet TX history.'); utils.print(' $ send [id] [address] [value] --script [code]: Send transaction.'); utils.print(' $ zap [id] --now [now] --age [age]: Zap pending wallet TXs.'); utils.print(' $ mempool: Get mempool snapshot.'); utils.print(' $ tx [hash/address]: View transactions.'); utils.print(' $ coin [hash+index/address]: View coins.'); utils.print(' $ block [hash/height]: View block.'); return callback(); } } function parseArg(argv) { var args = []; var options = {}; var arg, negate; argv = argv.slice(); function getarg() { var arg = argv.shift(); if (arg.indexOf('--') === 0) { // e.g. --opt arg = arg.split('='); if (arg.length > 1) { // e.g. --opt=val argv.unshift(arg.slice(1).join('=')); } arg = arg[0]; } else if (arg[0] === '-') { if (arg.length > 2) { // e.g. -abc argv = arg.substring(1).split('').map(function(ch) { return '-' + ch; }).concat(argv); arg = argv.shift(); } else { // e.g. -a } } else { // e.g. foo } return arg; } while (argv.length) { arg = getarg(); if (arg.indexOf('--') === 0) { negate = arg.indexOf('--no-') === 0; opt = arg.replace(/^--(no-)?/, ''); options[opt] = !argv[0] || argv[0][0] === '-' ? (negate ? false : true) : argv.shift(); } else { args.push(arg); } } options.args = args.slice(2); return options; } client.getInfo(function(err, info) { if (err) { console.error(err.stack + ''); return process.exit(1); } if (!argv.args[0]) utils.print(info); main(function(err) { if (err) { console.error(err.stack + ''); return process.exit(1); } client.destroy(); }); });