diff --git a/bin/cli b/bin/cli index 91c1d40d..35a33866 100755 --- a/bin/cli +++ b/bin/cli @@ -2,817 +2,13 @@ 'use strict'; -const Config = require('bcfg'); -const {NodeClient, WalletClient} = require('bclient'); - -const nports = { - main: 8332, - testnet: 18332, - regtest: 48332, - simnet: 18556 -}; - -const wports = { - main: 8334, - testnet: 18334, - regtest: 48334, - simnet: 18558 -}; - -class CLI { - constructor() { - this.config = new Config('bcoin', { - suffix: 'network', - fallback: 'main', - alias: { - 'n': 'network', - 'u': 'url', - 'uri': 'url', - 'k': 'api-key', - 's': 'ssl', - 'h': 'httphost', - 'p': 'httpport' - } - }); - - this.config.load({ - argv: true, - env: true - }); - - this.config.open('bcoin.conf'); - - this.argv = this.config.argv; - this.client = null; - this.wallet = null; - } - - log(json) { - if (typeof json === 'string') - return console.log.apply(console, arguments); - return console.log(JSON.stringify(json, null, 2)); - } - - async getInfo() { - const info = await this.client.getInfo(); - this.log(info); - } - - async getWallets() { - const wallets = await this.client.getWallets(); - this.log(wallets); - } - - async createWallet() { - const options = { - id: this.config.str([0, 'id']), - type: this.config.str('type'), - master: this.config.str('master'), - mnemonic: this.config.str('mnemonic'), - m: this.config.uint('m'), - n: this.config.uint('n'), - witness: this.config.bool('witness'), - passphrase: this.config.str('passphrase'), - watchOnly: this.config.has('key') ? true : this.config.bool('watch'), - accountKey: this.config.str('key') - }; - - const wallet = await this.client.createWallet(options); - - this.log(wallet); - } - - async getMaster() { - const master = await this.wallet.getMaster(); - - this.log(master); - } - - async getKey() { - const address = this.config.str(0); - const key = await this.wallet.getKey(address); - - this.log(key); - } - - async getWIF() { - const address = this.config.str(0); - const passphrase = this.config.str('passphrase'); - const key = await this.wallet.getWIF(address, passphrase); - - if (!key) { - this.log('Key not found.'); - return; - } - - this.log(key.privateKey); - } - - async addSharedKey() { - const key = this.config.str(0); - const account = this.config.str('account'); - - await this.wallet.addSharedKey(account, key); - - this.log('Added key.'); - } - - async removeSharedKey() { - const key = this.config.str(0); - const account = this.config.str('account'); - - await this.wallet.removeSharedKey(account, key); - - this.log('Removed key.'); - } - - async getSharedKeys() { - const acct = this.config.str([0, 'account']); - const account = await this.wallet.getAccount(acct); - - if (!account) { - this.log('Account not found.'); - return; - } - - this.log(account.keys); - } - - async getAccount() { - const acct = this.config.str([0, 'account']); - const account = await this.wallet.getAccount(acct); - - this.log(account); - } - - async createAccount() { - const name = this.config.str([0, 'name']); - - const options = { - type: this.config.str('type'), - m: this.config.uint('m'), - n: this.config.uint('n'), - witness: this.config.bool('witness'), - accountKey: this.config.str('key') - }; - - const account = await this.wallet.createAccount(name, options); - - this.log(account); - } - - async createAddress() { - const account = this.config.str([0, 'account']); - const addr = await this.wallet.createAddress(account); - - this.log(addr); - } - - async createChange() { - const account = this.config.str([0, 'account']); - const addr = await this.wallet.createChange(account); - - this.log(addr); - } - - async createNested() { - const account = this.config.str([0, 'account']); - const addr = await this.wallet.createNested(account); - - this.log(addr); - } - - async getAccounts() { - const accounts = await this.wallet.getAccounts(); - this.log(accounts); - } - - async getWallet() { - const info = await this.wallet.getInfo(); - this.log(info); - } - - async getTX() { - const hash = this.config.str(0, ''); - - if (hash.length !== 64) { - const txs = await this.client.getTXByAddress(hash); - this.log(txs); - return; - } - - const tx = await this.client.getTX(hash); - - if (!tx) { - this.log('TX not found.'); - return; - } - - this.log(tx); - } - - async getBlock() { - let hash = this.config.str(0, ''); - - if (hash.length !== 64) - hash = parseInt(hash, 10); - - const block = await this.client.getBlock(hash); - - if (!block) { - this.log('Block not found.'); - return; - } - - this.log(block); - } - - async getCoin() { - const hash = this.config.str(0, ''); - const index = this.config.uint(1); - - if (hash.length !== 64) { - const coins = await this.client.getCoinsByAddress(hash); - this.log(coins); - return; - } - - const coin = await this.client.getCoin(hash, index); - - if (!coin) { - this.log('Coin not found.'); - return; - } - - this.log(coin); - } - - async getWalletHistory() { - const account = this.config.str('account'); - const txs = await this.wallet.getHistory(account); - - this.log(txs); - } - - async getWalletPending() { - const account = this.config.str('account'); - const txs = await this.wallet.getPending(account); - - this.log(txs); - } - - async getWalletCoins() { - const account = this.config.str('account'); - const coins = await this.wallet.getCoins(account); - - this.log(coins); - } - - async listenWallet() { - await this.wallet.open(); - - this.wallet.on('tx', (details) => { - this.log('TX:'); - this.log(details); - }); - - this.wallet.on('confirmed', (details) => { - this.log('TX confirmed:'); - this.log(details); - }); - - this.wallet.on('unconfirmed', (details) => { - this.log('TX unconfirmed:'); - this.log(details); - }); - - this.wallet.on('conflict', (details) => { - this.log('TX conflict:'); - this.log(details); - }); - - this.wallet.on('address', (receive) => { - this.log('New addresses allocated:'); - this.log(receive); - }); - - this.wallet.on('balance', (balance) => { - this.log('Balance:'); - this.log(balance); - }); - - return await this.wallet.onDisconnect(); - } - - async getBalance() { - const account = this.config.str('account'); - const balance = await this.wallet.getBalance(account); - - this.log(balance); - } - - async getMempool() { - const txs = await this.client.getMempool(); - - this.log(txs); - } - - async sendTX() { - const outputs = []; - - if (this.config.has('script')) { - outputs.push({ - script: this.config.str('script'), - value: this.config.ufixed([0, 'value'], 8) - }); - } else { - outputs.push({ - address: this.config.str([0, 'address']), - value: this.config.ufixed([1, 'value'], 8) - }); - } - - const options = { - account: this.config.str('account'), - passphrase: this.config.str('passphrase'), - outputs: outputs, - smart: this.config.bool('smart'), - rate: this.config.ufixed('rate', 8), - subtractFee: this.config.bool('subtract-fee') - }; - - const tx = await this.wallet.send(options); - - this.log(tx); - } - - async createTX() { - let output; - - if (this.config.has('script')) { - output = { - script: this.config.str('script'), - value: this.config.ufixed([0, 'value'], 8) - }; - } else { - output = { - address: this.config.str([0, 'address']), - value: this.config.ufixed([1, 'value'], 8) - }; - } - - const options = { - account: this.config.str('account'), - passphrase: this.config.str('passphrase'), - outputs: [output], - smart: this.config.bool('smart'), - rate: this.config.ufixed('rate', 8), - subtractFee: this.config.bool('subtract-fee') - }; - - const tx = await this.wallet.createTX(options); - - this.log(tx); - } - - async signTX() { - const passphrase = this.config.str('passphrase'); - const raw = this.config.str([0, 'tx']); - const tx = await this.wallet.sign(raw, { passphrase }); - - this.log(tx); - } - - async zapWallet() { - const age = this.config.uint([0, 'age'], 72 * 60 * 60); - - await this.wallet.zap(this.config.str('account'), age); - - this.log('Zapped!'); - } - - async broadcast() { - const raw = this.config.str([0, 'tx']); - const tx = await this.client.broadcast(raw); - - this.log('Broadcasted:'); - this.log(tx); - } - - async viewTX() { - const raw = this.config.str([0, 'tx']); - const tx = await this.wallet.fill(raw); - - this.log(tx); - } - - async getDetails() { - const hash = this.config.str(0); - const details = await this.wallet.getTX(hash); - - this.log(details); - } - - async getWalletBlocks() { - const blocks = await this.wallet.getBlocks(); - this.log(blocks); - } - - async getWalletBlock() { - const height = this.config.uint(0); - const block = await this.wallet.getBlock(height); - - this.log(block); - } - - async retoken() { - const passphrase = this.config.str('passphrase'); - const result = await this.wallet.retoken(passphrase); - - this.log(result); - } - - async rescan() { - const height = this.config.uint(0); - - await this.wallet.rescan(height); - - this.log('Rescanning...'); - } - - async reset() { - let hash = this.config.str(0); - - if (hash.length !== 64) - hash = parseInt(hash, 10); - - await this.client.reset(hash); - - this.log('Chain has been reset.'); - } - - async resend() { - await this.client.resend(); - - this.log('Resending...'); - } - - async resendWallet() { - await this.wallet.resend(); - - this.log('Resending...'); - } - - async backup() { - const path = this.config.str(0); - - await this.client.backup(path); - - this.log('Backup complete.'); - } - - async importKey() { - const key = this.config.str(0); - const account = this.config.str('account'); - const passphrase = this.config.str('passphrase'); - - if (!key) - throw new Error('No key for import.'); - - if (key.length === 66 || key.length === 130) { - await this.wallet.importPublic(account, key); - this.log('Imported public key.'); - return; - } - - await this.wallet.importPrivate(account, key, passphrase); - - this.log('Imported private key.'); - } - - async importAddress() { - const address = this.config.str(0); - const account = this.config.str('account'); - - await this.wallet.importAddress(account, address); - - this.log('Imported address.'); - } - - async lock() { - await this.wallet.lock(); - - this.log('Locked.'); - } - - async unlock() { - const passphrase = this.config.str(0); - const timeout = this.config.uint(1); - - await this.wallet.unlock(passphrase, timeout); - - this.log('Unlocked.'); - } - - async rpc() { - const method = this.argv.shift(); - const params = []; - - for (const arg of this.argv) { - let param; - try { - param = JSON.parse(arg); - } catch (e) { - param = arg; - } - params.push(param); - } - - let result; - try { - result = await this.client.execute(method, params); - } catch (e) { - if (e.type === 'RPCError') { - this.log(e.message); - return; - } - throw e; - } - - this.log(result); - } - - async handleWallet() { - const network = this.config.str('network', 'main'); - - this.wallet = new WalletClient({ - url: this.config.str('url'), - apiKey: this.config.str('api-key'), - ssl: this.config.bool('ssl'), - host: this.config.str('http-host'), - port: this.config.uint('http-port') - || wports[network] - || wports.main, - id: this.config.str('id', 'primary'), - token: this.config.str('token') - }); - - switch (this.argv.shift()) { - case 'listen': - await this.listenWallet(); - break; - case 'get': - await this.getWallet(); - break; - case 'master': - await this.getMaster(); - break; - case 'shared': - if (this.argv[0] === 'add') { - this.argv.shift(); - await this.addSharedKey(); - break; - } - if (this.argv[0] === 'remove') { - this.argv.shift(); - await this.removeSharedKey(); - break; - } - if (this.argv[0] === 'list') - this.argv.shift(); - await this.getSharedKeys(); - break; - case 'balance': - await this.getBalance(); - break; - case 'history': - await this.getWalletHistory(); - break; - case 'pending': - await this.getWalletPending(); - break; - case 'coins': - await this.getWalletCoins(); - break; - case 'account': - if (this.argv[0] === 'list') { - this.argv.shift(); - await this.getAccounts(); - break; - } - if (this.argv[0] === 'create') { - this.argv.shift(); - await this.createAccount(); - break; - } - if (this.argv[0] === 'get') - this.argv.shift(); - await this.getAccount(); - break; - case 'address': - await this.createAddress(); - break; - case 'change': - await this.createChange(); - break; - case 'nested': - await this.createNested(); - break; - case 'retoken': - await this.retoken(); - break; - case 'sign': - await this.signTX(); - break; - case 'mktx': - await this.createTX(); - break; - case 'send': - await this.sendTX(); - break; - case 'zap': - await this.zapWallet(); - break; - case 'tx': - await this.getDetails(); - break; - case 'blocks': - await this.getWalletBlocks(); - break; - case 'block': - await this.getWalletBlock(); - break; - case 'view': - await this.viewTX(); - break; - case 'import': - await this.importKey(); - break; - case 'watch': - await this.importAddress(); - break; - case 'key': - await this.getKey(); - break; - case 'dump': - await this.getWIF(); - break; - case 'lock': - await this.lock(); - break; - case 'unlock': - await this.unlock(); - break; - case 'resend': - await this.resendWallet(); - break; - case 'rescan': - await this.rescan(); - break; - default: - this.log('Unrecognized command.'); - this.log('Commands:'); - this.log(' $ listen: Listen for events.'); - this.log(' $ get: View wallet.'); - this.log(' $ master: View wallet master key.'); - this.log(' $ shared add [xpubkey]: Add key to wallet.'); - this.log(' $ shared remove [xpubkey]: Remove key from wallet.'); - this.log(' $ balance: Get wallet balance.'); - this.log(' $ history: View TX history.'); - this.log(' $ pending: View pending TXs.'); - this.log(' $ coins: View wallet coins.'); - this.log(' $ account list: List account names.'); - this.log(' $ account create [account-name]: Create account.'); - this.log(' $ account get [account-name]: Get account details.'); - this.log(' $ address: Derive new address.'); - this.log(' $ change: Derive new change address.'); - this.log(' $ nested: Derive new nested address.'); - this.log(' $ retoken: Create new api key.'); - this.log(' $ send [address] [value]: Send transaction.'); - this.log(' $ mktx [address] [value]: Create transaction.'); - this.log(' $ sign [tx-hex]: Sign transaction.'); - this.log(' $ zap [age?]: Zap pending wallet TXs.'); - this.log(' $ tx [hash]: View transaction details.'); - this.log(' $ blocks: List wallet blocks.'); - this.log(' $ block [height]: View wallet block.'); - this.log(' $ view [tx-hex]: Parse and view transaction.'); - this.log(' $ import [wif|hex]: Import private or public key.'); - this.log(' $ watch [address]: Import an address.'); - this.log(' $ key [address]: Get wallet key by address.'); - this.log(' $ dump [address]: Get wallet key WIF by address.'); - this.log(' $ lock: Lock wallet.'); - this.log(' $ unlock [passphrase] [timeout?]: Unlock wallet.'); - this.log(' $ resend: Resend pending transactions.'); - this.log(' $ rescan [height]: Rescan for transactions.'); - this.log('Other Options:'); - this.log(' --passphrase [passphrase]: For signing/account-creation.'); - this.log(' --account [account-name]: Account name.'); - break; - } - } - - async handleNode() { - const network = this.config.str('network', 'main'); - - this.client = new NodeClient({ - url: this.config.str('url'), - apiKey: this.config.str('api-key'), - ssl: this.config.bool('ssl'), - host: this.config.str('http-host'), - port: this.config.uint('http-port') - || nports[network] - || nports.main - }); - - switch (this.argv.shift()) { - case 'info': - await this.getInfo(); - break; - case 'wallets': - await this.getWallets(); - break; - case 'mkwallet': - await this.createWallet(); - break; - case 'broadcast': - await this.broadcast(); - break; - case 'mempool': - await this.getMempool(); - break; - case 'tx': - await this.getTX(); - break; - case 'coin': - await this.getCoin(); - break; - case 'block': - await this.getBlock(); - break; - case 'reset': - await this.reset(); - break; - case 'resend': - await this.resend(); - break; - case 'backup': - await this.backup(); - break; - case 'rpc': - await this.rpc(); - break; - default: - this.log('Unrecognized command.'); - this.log('Commands:'); - this.log(' $ info: Get server info.'); - this.log(' $ wallets: List all wallets.'); - this.log(' $ wallet create [id]: Create wallet.'); - this.log(' $ broadcast [tx-hex]: Broadcast transaction.'); - this.log(' $ mempool: Get mempool snapshot.'); - this.log(' $ tx [hash/address]: View transactions.'); - this.log(' $ coin [hash+index/address]: View coins.'); - this.log(' $ block [hash/height]: View block.'); - this.log(' $ reset [height/hash]: Reset chain to desired block.'); - this.log(' $ resend: Resend pending transactions.'); - this.log(' $ backup [path]: Backup the wallet db.'); - this.log(' $ rpc [command] [args]: Execute RPC command.'); - break; - } - } - - async open() { - switch (this.argv[0]) { - case 'w': - case 'wallet': - this.argv.shift(); - if (this.argv[0] === 'create') { - this.argv[0] = 'mkwallet'; - await this.handleNode(); - break; - } - await this.handleWallet(); - break; - default: - await this.handleNode(); - break; - } - } - - async destroy() { - if (this.wallet && this.wallet.opened) - await this.wallet.close(); - - if (this.client && this.client.opened) - await this.client.close(); - } +console.error('%s%s', + 'Warning: The `bcoin cli` interface is deprecated.\n', + 'Please use `bcoin-cli` ($ npm install bclient).'); + +if (process.argv.length > 2 && process.argv[2] === 'wallet') { + process.argv.splice(2, 1); // Evil hack. + require('bclient/bin/bwallet-cli'); +} else { + require('bclient/bin/bcoin-cli'); } - -(async () => { - const cli = new CLI(); - await cli.open(); - await cli.destroy(); - process.exit(0); -})().catch((err) => { - console.error(err.stack); - process.exit(1); -}); diff --git a/lib/primitives/block.js b/lib/primitives/block.js index 66bc40ed..2749a77e 100644 --- a/lib/primitives/block.js +++ b/lib/primitives/block.js @@ -379,7 +379,8 @@ class Block extends AbstractBlock { return null; const coinbase = this.txs[0]; - let hash; + + let hash = null; for (let i = coinbase.outputs.length - 1; i >= 0; i--) { const output = coinbase.outputs[i]; @@ -439,6 +440,7 @@ class Block extends AbstractBlock { // Test all transactions. const scale = consensus.WITNESS_SCALE_FACTOR; + let sigops = 0; for (let i = 0; i < this.txs.length; i++) { diff --git a/lib/wallet/walletdb.js b/lib/wallet/walletdb.js index 4f29a09d..0f31b99a 100644 --- a/lib/wallet/walletdb.js +++ b/lib/wallet/walletdb.js @@ -1199,7 +1199,7 @@ class WalletDB extends EventEmitter { * @returns {Promise} - Returns Boolean. */ - hasAccount(wid, index) { + async hasAccount(wid, index) { return this.db.has(layout.a.build(wid, index)); } @@ -1210,7 +1210,7 @@ class WalletDB extends EventEmitter { * @returns {Promise} */ - saveKey(b, wid, ring) { + async saveKey(b, wid, ring) { return this.savePath(b, wid, ring.toPath()); } @@ -1283,7 +1283,7 @@ class WalletDB extends EventEmitter { * @returns {Promise} */ - hasPath(wid, hash) { + async hasPath(wid, hash) { return this.db.has(layout.P.build(wid, hash)); } diff --git a/package.json b/package.json index 8af4e944..5c27e3e4 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,6 @@ "main": "./lib/bcoin.js", "bin": { "bcoin": "./bin/bcoin", - "bcoin-cli": "./bin/cli", "bcoin-node": "./bin/node", "bcoin-spvnode": "./bin/spvnode" },