client: Import hs-client into the project.
This commit is contained in:
parent
6314c1aa08
commit
2dc2c488d9
24 changed files with 3211 additions and 61 deletions
266
bin/hsd-cli
266
bin/hsd-cli
|
|
@ -1,5 +1,267 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
'use strict';
|
||||
|
||||
require('hs-client/bin/hsd-cli');
|
||||
const Config = require('bcfg');
|
||||
const {NodeClient} = require('../lib/client');
|
||||
|
||||
// NOTE: This is part of generated `hs-client`.
|
||||
// Don't introduce any unnecessary dependencies to this.
|
||||
// This needs to be remain as is for hs-client to be simple.
|
||||
|
||||
const ports = {
|
||||
main: 12037,
|
||||
testnet: 13037,
|
||||
regtest: 14037,
|
||||
simnet: 15037
|
||||
};
|
||||
|
||||
const HELP = `
|
||||
Commands:
|
||||
$ block [hash/height]: View block.
|
||||
$ broadcast [tx-hex]: Broadcast transaction.
|
||||
$ coin [hash+index/address]: View coins.
|
||||
$ header [hash/height]: View block header.
|
||||
$ help: Show help message.
|
||||
$ info: Get server info.
|
||||
$ mempool: Get mempool snapshot.
|
||||
$ reset [height/hash]: Reset chain to desired block.
|
||||
$ rpc [command] [args]: Execute RPC command.
|
||||
$ tx [hash/address]: View transactions.
|
||||
|
||||
For additional information and a complete list of commands
|
||||
visit https://hsd-dev.org/api-docs/
|
||||
`;
|
||||
|
||||
class CLI {
|
||||
constructor() {
|
||||
this.config = new Config('hsd', {
|
||||
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('hsd.conf');
|
||||
|
||||
this.argv = this.config.argv;
|
||||
this.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')
|
||||
|| ports[this.network]
|
||||
|| ports.main,
|
||||
timeout: this.config.uint('timeout'),
|
||||
limit: this.config.uint('limit')
|
||||
});
|
||||
}
|
||||
|
||||
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 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 getBlockHeader() {
|
||||
let hash = this.config.str(0, '');
|
||||
|
||||
if (hash.length !== 64)
|
||||
hash = parseInt(hash, 10);
|
||||
|
||||
const header = await this.client.getBlockHeader(hash);
|
||||
|
||||
if (!header) {
|
||||
this.log('Block header not found.');
|
||||
return;
|
||||
}
|
||||
|
||||
this.log(header);
|
||||
}
|
||||
|
||||
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 getMempool() {
|
||||
const txs = await this.client.getMempool();
|
||||
|
||||
this.log(txs);
|
||||
}
|
||||
|
||||
async broadcast() {
|
||||
const raw = this.config.str([0, 'tx']);
|
||||
const tx = await this.client.broadcast(raw);
|
||||
|
||||
this.log('Broadcasted:');
|
||||
this.log(tx);
|
||||
}
|
||||
|
||||
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 rpc() {
|
||||
const method = this.argv.shift();
|
||||
if (!method) {
|
||||
this.log('Missing RPC method');
|
||||
return;
|
||||
}
|
||||
|
||||
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 open() {
|
||||
switch (this.argv.shift()) {
|
||||
case 'block':
|
||||
await this.getBlock();
|
||||
break;
|
||||
case 'broadcast':
|
||||
await this.broadcast();
|
||||
break;
|
||||
case 'coin':
|
||||
await this.getCoin();
|
||||
break;
|
||||
case 'header':
|
||||
await this.getBlockHeader();
|
||||
break;
|
||||
case 'help':
|
||||
process.stdout.write(HELP + '\n');
|
||||
break;
|
||||
case 'info':
|
||||
await this.getInfo();
|
||||
break;
|
||||
case 'mempool':
|
||||
await this.getMempool();
|
||||
break;
|
||||
case 'reset':
|
||||
await this.reset();
|
||||
break;
|
||||
case 'rpc':
|
||||
await this.rpc();
|
||||
break;
|
||||
case 'tx':
|
||||
await this.getTX();
|
||||
break;
|
||||
default:
|
||||
process.stdout.write('Unrecognized command.\n');
|
||||
process.stdout.write(HELP + '\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async destroy() {
|
||||
if (this.client && this.client.opened)
|
||||
await this.client.close();
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const cli = new CLI();
|
||||
await cli.open();
|
||||
await cli.destroy();
|
||||
})().catch((err) => {
|
||||
console.error(err.stack);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
|
|||
23
bin/hsd-rpc
Executable file
23
bin/hsd-rpc
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/sh
|
||||
|
||||
# NOTE: This is part of generated `hs-client`.
|
||||
|
||||
rl=0
|
||||
|
||||
if ! type perl > /dev/null 2>& 1; then
|
||||
if uname | grep -i 'darwin' > /dev/null; then
|
||||
echo 'hsd-rpc requires perl to start on OSX.' >& 2
|
||||
exit 1
|
||||
fi
|
||||
rl=1
|
||||
fi
|
||||
|
||||
if test $rl -eq 1; then
|
||||
file=$(readlink -f "$0")
|
||||
else
|
||||
file=$(perl -MCwd -e "print Cwd::realpath('$0')")
|
||||
fi
|
||||
|
||||
dir=$(dirname "$file")
|
||||
|
||||
exec "${dir}/hsd-cli" rpc "$@"
|
||||
719
bin/hsw-cli
719
bin/hsw-cli
|
|
@ -1,5 +1,720 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
'use strict';
|
||||
|
||||
require('hs-client/bin/hsw-cli');
|
||||
const Config = require('bcfg');
|
||||
const {WalletClient} = require('../lib/client');
|
||||
const EXP = 6;
|
||||
|
||||
// NOTE: This is part of generated `hs-client`.
|
||||
// Don't introduce any unnecessary dependencies to this.
|
||||
// This needs to be remain as is for hs-client to be simple.
|
||||
|
||||
const ports = {
|
||||
main: 12039,
|
||||
testnet: 13039,
|
||||
regtest: 14039,
|
||||
simnet: 15039
|
||||
};
|
||||
|
||||
const HELP = `
|
||||
Commands:
|
||||
$ abandon [hash]: Abandon a transaction.
|
||||
$ account create [account-name]: Create account.
|
||||
$ account get [account-name]: Get account details.
|
||||
$ account list: List account names.
|
||||
$ address [account-name]: Derive new address.
|
||||
$ balance: Get wallet balance.
|
||||
$ block [height]: View wallet block.
|
||||
$ blocks: List wallet blocks.
|
||||
$ change [account-name]: Derive new change address.
|
||||
$ coins: View wallet coins.
|
||||
$ dump [address]: Get wallet key WIF by address.
|
||||
$ get: View wallet.
|
||||
$ help: Show help message.
|
||||
$ history: View TX history.
|
||||
$ import [wif|hex]: Import private or public key.
|
||||
$ key [address]: Get wallet key by address.
|
||||
$ listen: Listen for events.
|
||||
$ lock: Lock wallet.
|
||||
$ mkauctiontxs [name] [bid] [lockup] [broadcast]: Create bid and reveal TXs.
|
||||
$ mktx [address] [value]: Create transaction.
|
||||
$ mkwallet [id]: Create wallet.
|
||||
$ pending: View pending TXs.
|
||||
$ resendwallet [id]: Resend pending transactions for a single wallet.
|
||||
$ retoken: Create new api key.
|
||||
$ send [address] [value]: Send transaction.
|
||||
$ shared add [account-name] [xpubkey]: Add key to account.
|
||||
$ shared remove [account-name] [xpubkey]: Remove key from account.
|
||||
$ shared list [account-name]: List keys in account.
|
||||
$ sign [tx-hex]: Sign transaction.
|
||||
$ tx [hash]: View transaction details.
|
||||
$ unlock [passphrase] [timeout?]: Unlock wallet.
|
||||
$ view [tx-hex]: Parse and view transaction.
|
||||
$ watch [address]: Import an address.
|
||||
$ zap [age]: Zap pending wallet TXs.
|
||||
|
||||
If node is run with wallet-auth flag, then wallet commands
|
||||
require authorization token.
|
||||
Admin commands require admin permissions for provided authorization token:
|
||||
$ backup [path]: Backup the wallet db.
|
||||
$ master: View wallet master key.
|
||||
$ rescan [height]: Rescan for transactions.
|
||||
$ resend: Resend pending transactions for all wallets.
|
||||
$ rpc [command] [args]: Execute RPC command.
|
||||
$ wallets: List all wallets.
|
||||
|
||||
Other options:
|
||||
--id [wallet id]: Wallet id.
|
||||
--passphrase [passphrase]: For signing/account-creation.
|
||||
--account [account-name]: Account name.
|
||||
--token [token]: Wallet-specific or admin authorization token.
|
||||
--api-key [key]: General API authorization key.
|
||||
|
||||
For additional information and a complete list of commands
|
||||
visit https://hsd-dev.org/api-docs/
|
||||
`;
|
||||
|
||||
class CLI {
|
||||
constructor() {
|
||||
this.config = new Config('hsd', {
|
||||
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('hsw.conf');
|
||||
|
||||
this.argv = this.config.argv;
|
||||
this.network = this.config.str('network', 'main');
|
||||
|
||||
const id = this.config.str('id', 'primary');
|
||||
const token = this.config.str('token', '');
|
||||
|
||||
this.client = 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')
|
||||
|| ports[this.network]
|
||||
|| ports.main,
|
||||
timeout: this.config.uint('timeout'),
|
||||
token
|
||||
});
|
||||
|
||||
this.wallet = this.client.wallet(id, token);
|
||||
}
|
||||
|
||||
log(json) {
|
||||
if (typeof json === 'string')
|
||||
return console.log.apply(console, arguments);
|
||||
return console.log(JSON.stringify(json, null, 2));
|
||||
}
|
||||
|
||||
async getWallets() {
|
||||
const wallets = await this.client.getWallets();
|
||||
this.log(wallets);
|
||||
}
|
||||
|
||||
async createWallet() {
|
||||
const id = this.config.str([0, 'id']);
|
||||
|
||||
const options = {
|
||||
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'),
|
||||
bip39Passphrase: this.config.str('bip39Passphrase'),
|
||||
watchOnly: this.config.has('key') ? true : this.config.bool('watch'),
|
||||
accountKey: this.config.str('key'),
|
||||
lookahead: this.config.uint('lookahead'),
|
||||
language: this.config.str('language')
|
||||
};
|
||||
|
||||
const wallet = await this.client.createWallet(id, 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'),
|
||||
lookahead: this.config.uint('lookahead')
|
||||
};
|
||||
|
||||
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 getAccounts() {
|
||||
const accounts = await this.wallet.getAccounts();
|
||||
this.log(accounts);
|
||||
}
|
||||
|
||||
async getWallet() {
|
||||
const info = await this.wallet.getInfo();
|
||||
this.log(info);
|
||||
}
|
||||
|
||||
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.client.open();
|
||||
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 new Promise((resolve, reject) => {
|
||||
this.client.once('disconnect', resolve);
|
||||
});
|
||||
}
|
||||
|
||||
async getBalance() {
|
||||
const account = this.config.str('account');
|
||||
const balance = await this.wallet.getBalance(account);
|
||||
|
||||
this.log(balance);
|
||||
}
|
||||
|
||||
async getMempool() {
|
||||
const txs = await this.wallet.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'], EXP)
|
||||
});
|
||||
} else {
|
||||
outputs.push({
|
||||
address: this.config.str([0, 'address']),
|
||||
value: this.config.ufixed([1, 'value'], EXP)
|
||||
});
|
||||
}
|
||||
|
||||
const options = {
|
||||
account: this.config.str('account'),
|
||||
passphrase: this.config.str('passphrase'),
|
||||
outputs: outputs,
|
||||
smart: this.config.bool('smart'),
|
||||
rate: this.config.ufixed('rate', EXP),
|
||||
subtractFee: this.config.bool('subtract-fee')
|
||||
};
|
||||
|
||||
const tx = await this.wallet.send(options);
|
||||
|
||||
this.log(tx);
|
||||
}
|
||||
|
||||
async createAuctionTxs() {
|
||||
const options = {
|
||||
name: this.config.str([0, 'name']),
|
||||
bid: this.config.ufixed([1, 'bid'], EXP),
|
||||
lockup: this.config.ufixed([2, 'lockup'], EXP),
|
||||
broadcastBid: this.config.bool([3, 'broadcastBid']),
|
||||
passphrase: this.config.str('passphrase')
|
||||
};
|
||||
|
||||
const txs = await this.wallet.createAuctionTxs(options);
|
||||
|
||||
this.log(txs);
|
||||
}
|
||||
|
||||
async createTX() {
|
||||
let output;
|
||||
|
||||
if (this.config.has('script')) {
|
||||
output = {
|
||||
script: this.config.str('script'),
|
||||
value: this.config.ufixed([0, 'value'], EXP)
|
||||
};
|
||||
} else {
|
||||
output = {
|
||||
address: this.config.str([0, 'address']),
|
||||
value: this.config.ufixed([1, 'value'], EXP)
|
||||
};
|
||||
}
|
||||
|
||||
const options = {
|
||||
account: this.config.str('account'),
|
||||
passphrase: this.config.str('passphrase'),
|
||||
outputs: [output],
|
||||
smart: this.config.bool('smart'),
|
||||
rate: this.config.ufixed('rate', EXP),
|
||||
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 tx = this.config.str([0, 'tx']);
|
||||
const signedTx = await this.wallet.sign({tx, passphrase});
|
||||
|
||||
this.log(signedTx);
|
||||
}
|
||||
|
||||
async zapWallet() {
|
||||
const age = this.config.uint([0, 'age'], 72 * 60 * 60);
|
||||
const account = this.config.str('account');
|
||||
|
||||
await this.wallet.zap(account, age);
|
||||
|
||||
this.log('Zapped!');
|
||||
}
|
||||
|
||||
async abandonTX() {
|
||||
const hash = this.config.str(0);
|
||||
|
||||
await this.wallet.abandon(hash);
|
||||
|
||||
this.log('Abandoned tx: ' + hash);
|
||||
}
|
||||
|
||||
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.client.rescan(height);
|
||||
|
||||
this.log('Rescanning...');
|
||||
}
|
||||
|
||||
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();
|
||||
if (!method) {
|
||||
this.log('Missing RPC method');
|
||||
return;
|
||||
}
|
||||
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() {
|
||||
switch (this.argv.shift()) {
|
||||
case 'abandon':
|
||||
await this.abandonTX();
|
||||
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 'backup':
|
||||
await this.backup();
|
||||
break;
|
||||
case 'balance':
|
||||
await this.getBalance();
|
||||
break;
|
||||
case 'block':
|
||||
await this.getWalletBlock();
|
||||
break;
|
||||
case 'blocks':
|
||||
await this.getWalletBlocks();
|
||||
break;
|
||||
case 'change':
|
||||
await this.createChange();
|
||||
break;
|
||||
case 'coins':
|
||||
await this.getWalletCoins();
|
||||
break;
|
||||
case 'dump':
|
||||
await this.getWIF();
|
||||
break;
|
||||
case 'get':
|
||||
await this.getWallet();
|
||||
break;
|
||||
case 'help':
|
||||
process.stdout.write(HELP + '\n');
|
||||
break;
|
||||
case 'history':
|
||||
await this.getWalletHistory();
|
||||
break;
|
||||
case 'import':
|
||||
await this.importKey();
|
||||
break;
|
||||
case 'key':
|
||||
await this.getKey();
|
||||
break;
|
||||
case 'listen':
|
||||
await this.listenWallet();
|
||||
break;
|
||||
case 'lock':
|
||||
await this.lock();
|
||||
break;
|
||||
case 'master':
|
||||
await this.getMaster();
|
||||
break;
|
||||
case 'mkauctiontxs':
|
||||
await this.createAuctionTxs();
|
||||
break;
|
||||
case 'mktx':
|
||||
await this.createTX();
|
||||
break;
|
||||
case 'mkwallet':
|
||||
await this.createWallet();
|
||||
break;
|
||||
case 'pending':
|
||||
await this.getWalletPending();
|
||||
break;
|
||||
case 'rescan':
|
||||
await this.rescan();
|
||||
break;
|
||||
case 'resend':
|
||||
await this.resend();
|
||||
break;
|
||||
case 'resendwallet':
|
||||
await this.resendWallet();
|
||||
break;
|
||||
case 'retoken':
|
||||
await this.retoken();
|
||||
break;
|
||||
case 'rpc':
|
||||
await this.rpc();
|
||||
break;
|
||||
case 'send':
|
||||
await this.sendTX();
|
||||
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 'sign':
|
||||
await this.signTX();
|
||||
break;
|
||||
case 'tx':
|
||||
await this.getDetails();
|
||||
break;
|
||||
case 'unlock':
|
||||
await this.unlock();
|
||||
break;
|
||||
case 'view':
|
||||
await this.viewTX();
|
||||
break;
|
||||
case 'wallets':
|
||||
await this.getWallets();
|
||||
break;
|
||||
case 'watch':
|
||||
await this.importAddress();
|
||||
break;
|
||||
case 'zap':
|
||||
await this.zapWallet();
|
||||
break;
|
||||
default:
|
||||
process.stdout.write('Unrecognized command.\n');
|
||||
process.stdout.write(HELP + '\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async destroy() {
|
||||
if (this.client.opened)
|
||||
await this.client.close();
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const cli = new CLI();
|
||||
await cli.handleWallet();
|
||||
await cli.destroy();
|
||||
})().catch((err) => {
|
||||
console.error(err.stack);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
|
|||
23
bin/hsw-rpc
Executable file
23
bin/hsw-rpc
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/sh
|
||||
|
||||
# NOTE: This is part of generated `hs-client`.
|
||||
|
||||
rl=0
|
||||
|
||||
if ! type perl > /dev/null 2>& 1; then
|
||||
if uname | grep -i 'darwin' > /dev/null; then
|
||||
echo 'hsw-rpc requires perl to start on OSX.' >& 2
|
||||
exit 1
|
||||
fi
|
||||
rl=1
|
||||
fi
|
||||
|
||||
if test $rl -eq 1; then
|
||||
file=$(readlink -f "$0")
|
||||
else
|
||||
file=$(perl -MCwd -e "print Cwd::realpath('$0')")
|
||||
fi
|
||||
|
||||
dir=$(dirname "$file")
|
||||
|
||||
exec "${dir}/hsw-cli" rpc "$@"
|
||||
|
|
@ -1,29 +1,32 @@
|
|||
Releasing hsd
|
||||
=============
|
||||
Releasing hsd and hs-client
|
||||
===========================
|
||||
|
||||
This document contains information about bundling, signing and
|
||||
distributing the files.
|
||||
|
||||
`hsd` is distributed through several platforms: `github`, `npm`, `brew`.
|
||||
`hsd/hs-client` is distributed through several platforms: `github`, `npm`, `brew`.
|
||||
|
||||
<!-- markdown-toc -i release-files.md -->
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Deploying to github (tag)](#deploying-to-github-tag)
|
||||
* [Major, minor and patches](#major-minor-and-patches)
|
||||
+ [Major](#major)
|
||||
+ [Minor, Patch](#minor-patch)
|
||||
- [Deploying to npm](#deploying-to-npm)
|
||||
* [Deploying latest version, minor and patches included](#deploying-latest-version-minor-and-patches-included)
|
||||
* [Deploying support versions (previous and life-support)](#deploying-support-versions-previous-and-life-support)
|
||||
- [Deploying to homebrew](#deploying-to-homebrew)
|
||||
- [Deploying to handshake.org](#deploying-to-handshakeorg)
|
||||
* [Building tarball](#building-tarball)
|
||||
* [Signing and upload](#signing-and-upload)
|
||||
- [hsd](#hsd)
|
||||
* [Deploying to github (tag)](#deploying-to-github-tag)
|
||||
+ [Major, minor and patches](#major-minor-and-patches)
|
||||
- [Major](#major)
|
||||
- [Minor, Patch](#minor-patch)
|
||||
* [Deploying to npm](#deploying-to-npm)
|
||||
+ [Deploying latest version, minor and patches included](#deploying-latest-version-minor-and-patches-included)
|
||||
+ [Deploying support versions (previous and life-support)](#deploying-support-versions-previous-and-life-support)
|
||||
* [Deploying to homebrew](#deploying-to-homebrew)
|
||||
* [Deploying to handshake.org](#deploying-to-handshakeorg)
|
||||
+ [Building tarball](#building-tarball)
|
||||
+ [Signing and upload](#signing-and-upload)
|
||||
- [hs-client](#hs-client)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
# hsd
|
||||
## Deploying to github (tag)
|
||||
|
||||
This does not need many additional actions as we use github as our primary
|
||||
|
|
@ -119,6 +122,33 @@ and create PR with the relevant updates to the `download/index.html` and
|
|||
- Update `download/index.html` with new links.
|
||||
- Create PR to the main repository.
|
||||
|
||||
# hs-client
|
||||
Since hsd v5 `hs-client` is part of the `hsd`. Original [hs-client repo][hsclient] is now used to
|
||||
publish generated content. `hs-client` version will now be strictly tied to
|
||||
the `hsd` version. It is then generated from `hsd` code to release separately on
|
||||
`git` and `npm`. Most of the process is done by the introduced helper script
|
||||
`scripts/gen-hsclient.js`. It can help you setup `hs-client` that just needs
|
||||
publishing on `git` and `npm`. It also gives instructions how to do both.
|
||||
After `hsd` has been released we can also release `hs-client` from the same
|
||||
commit/tag, just run: `./scripts/gen-hsclient.js` which will generate `hs-client`
|
||||
package with `git` setup in `tmp` directory. You can alternatively pass
|
||||
`HS_CLIENT_DIR` env variable for custom place. If generating git failed for some
|
||||
reason, it will list commands that needs executing and you can proceed manually
|
||||
or fix the issues and rerun the script. NOTE, that the script will never try to
|
||||
publish by itself, only generate files to review locally.
|
||||
- `./scripts/gen-hsclient.js` - script will also list left commands that are
|
||||
necessary for publishing.
|
||||
- `cd /tmp/hs-client`
|
||||
- `git push -f origin master` - rewrite whole `hs-client` repo with the new content.
|
||||
- `git push -f origin vVersion` - push newly generated tag to the `hs-client`.
|
||||
- You can check the `gen-hsclient` output for the proper version or
|
||||
- `git tag -l` to list.
|
||||
- `npm publish` - this will also tag it as `latest`. If you want to tag it differently
|
||||
you can do so, same as above hsd `npm publish`.
|
||||
- NOTE: You can use `npm publish --dry-run` to see the details before actual
|
||||
release.
|
||||
|
||||
|
||||
[homebrew]: https://brew.sh/
|
||||
[homebrew-repo]: https://github.com/Homebrew/homebrew-core
|
||||
[homebrew-new-formula]: https://github.com/Homebrew/homebrew-core/pull/51014
|
||||
|
|
@ -126,3 +156,4 @@ and create PR with the relevant updates to the `download/index.html` and
|
|||
[homebrew-guidelines]: https://github.com/Homebrew/homebrew-core/blob/master/CONTRIBUTING.md
|
||||
[handshake-web]: https://github.com/handshake-org/handshake-web/
|
||||
[bpkg]: https://github.com/chjj/bpkg
|
||||
[hsclient]: https://github.com/handshake-org/hs-client
|
||||
|
|
|
|||
16
lib/client/index.js
Normal file
16
lib/client/index.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*!
|
||||
* client/index.js - http clients for hs
|
||||
* Copyright (c) 2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// NOTE: This is part of generated `hs-client`.
|
||||
|
||||
/**
|
||||
* @module client
|
||||
*/
|
||||
|
||||
exports.NodeClient = require('./node');
|
||||
exports.WalletClient = require('./wallet');
|
||||
343
lib/client/node.js
Normal file
343
lib/client/node.js
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
/*!
|
||||
* client.js - http client for wallets
|
||||
* Copyright (c) 2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// NOTE: This is part of generated `hs-client`.
|
||||
// Don't introduce any unnecessary dependencies to this.
|
||||
|
||||
const assert = require('bsert');
|
||||
const {Client} = require('bcurl');
|
||||
|
||||
/**
|
||||
* Node Client
|
||||
* @alias module:client.NodeClient
|
||||
* @extends {bcurl.Client}
|
||||
*/
|
||||
|
||||
class NodeClient extends Client {
|
||||
/**
|
||||
* Creat a node client.
|
||||
* @param {Object?} options
|
||||
*/
|
||||
|
||||
constructor(options) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Auth with server.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
async auth() {
|
||||
await this.call('auth', this.password);
|
||||
await this.watchChain();
|
||||
await this.watchMempool();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an RPC call.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
execute(name, params) {
|
||||
return super.execute('/', name, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a mempool snapshot.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getMempool() {
|
||||
return this.get('/mempool');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get some info about the server (network and version).
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getInfo() {
|
||||
return this.get('/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get coins that pertain to an address from the mempool or chain database.
|
||||
* Takes into account spent coins in the mempool.
|
||||
* @param {String} address
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getCoinsByAddress(address) {
|
||||
assert(typeof address === 'string');
|
||||
return this.get(`/coin/address/${address}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get coins that pertain to addresses from the mempool or chain database.
|
||||
* Takes into account spent coins in the mempool.
|
||||
* @param {String[]} addresses
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getCoinsByAddresses(addresses) {
|
||||
assert(Array.isArray(addresses));
|
||||
return this.post('/coin/address', { addresses });
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a coin from the mempool or chain database.
|
||||
* Takes into account spent coins in the mempool.
|
||||
* @param {Hash} hash
|
||||
* @param {Number} index
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getCoin(hash, index) {
|
||||
assert(typeof hash === 'string');
|
||||
assert((index >>> 0) === index);
|
||||
return this.get(`/coin/${hash}/${index}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve transactions pertaining to an
|
||||
* address from the mempool or chain database.
|
||||
* @param {String} address
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getTXByAddress(address) {
|
||||
assert(typeof address === 'string');
|
||||
return this.get(`/tx/address/${address}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve transactions pertaining to
|
||||
* addresses from the mempool or chain database.
|
||||
* @param {String[]} addresses
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getTXByAddresses(addresses) {
|
||||
assert(Array.isArray(addresses));
|
||||
return this.post('/tx/address', { addresses });
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a transaction from the mempool or chain database.
|
||||
* @param {Hash} hash
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getTX(hash) {
|
||||
assert(typeof hash === 'string');
|
||||
return this.get(`/tx/${hash}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a block from the chain database.
|
||||
* @param {Hash|Number} block
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getBlock(block) {
|
||||
assert(typeof block === 'string' || typeof block === 'number');
|
||||
return this.get(`/block/${block}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a block header.
|
||||
* @param {Hash|Number} block
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getBlockHeader(block) {
|
||||
assert(typeof block === 'string' || typeof block === 'number');
|
||||
return this.get(`/header/${block}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a transaction to the mempool and broadcast it.
|
||||
* @param {TX} tx
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
broadcast(tx) {
|
||||
assert(typeof tx === 'string');
|
||||
return this.post('/broadcast', { tx });
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a claim to the mempool and broadcast it.
|
||||
* @param {Claim} claim
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
broadcastClaim(claim) {
|
||||
assert(typeof claim === 'string');
|
||||
return this.post('/claim', { claim });
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the chain.
|
||||
* @param {Number} height
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
reset(height) {
|
||||
return this.post('/reset', { height });
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch the blockchain.
|
||||
* @private
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
watchChain() {
|
||||
return this.call('watch chain');
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch the blockchain.
|
||||
* @private
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
watchMempool() {
|
||||
return this.call('watch mempool');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get chain tip.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getTip() {
|
||||
return this.call('get tip');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get chain entry.
|
||||
* @param {Hash} hash
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getEntry(block) {
|
||||
return this.call('get entry', block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hashes.
|
||||
* @param {Number} [start=-1]
|
||||
* @param {Number} [end=-1]
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getHashes(start, end) {
|
||||
return this.call('get hashes', start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a transaction. Do not wait for promise.
|
||||
* @param {TX} tx
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
send(tx) {
|
||||
assert(Buffer.isBuffer(tx));
|
||||
return this.call('send', tx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a claim. Do not wait for promise.
|
||||
* @param {Claim} claim
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
sendClaim(claim) {
|
||||
assert(Buffer.isBuffer(claim));
|
||||
return this.call('send claim', claim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name state.
|
||||
* @param {Buffer} nameHash
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
getNameStatus(nameHash) {
|
||||
assert(Buffer.isBuffer(nameHash));
|
||||
return this.call('get name', nameHash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bloom filter.
|
||||
* @param {Bloom} filter
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
setFilter(filter) {
|
||||
assert(Buffer.isBuffer(filter));
|
||||
return this.call('set filter', filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data to filter.
|
||||
* @param {Buffer} data
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
addFilter(chunks) {
|
||||
if (!Array.isArray(chunks))
|
||||
chunks = [chunks];
|
||||
|
||||
return this.call('add filter', chunks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset filter.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
resetFilter() {
|
||||
return this.call('reset filter');
|
||||
}
|
||||
|
||||
/**
|
||||
* Esimate smart fee.
|
||||
* @param {Number?} blocks
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
estimateFee(blocks) {
|
||||
assert(blocks == null || typeof blocks === 'number');
|
||||
return this.call('estimate fee', blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rescan for any missed transactions.
|
||||
* @param {Number|Hash} start - Start block.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
rescan(start) {
|
||||
if (start == null)
|
||||
start = 0;
|
||||
|
||||
assert(typeof start === 'number' || Buffer.isBuffer(start));
|
||||
|
||||
return this.call('rescan', start);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = NodeClient;
|
||||
1561
lib/client/wallet.js
Normal file
1561
lib/client/wallet.js
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -56,6 +56,11 @@ hsd.define('blockchain', './blockchain');
|
|||
hsd.define('Chain', './blockchain/chain');
|
||||
hsd.define('ChainEntry', './blockchain/chainentry');
|
||||
|
||||
// Client
|
||||
hsd.define('client', './client');
|
||||
hsd.define('WalletClient', './client/wallet');
|
||||
hsd.define('NodeClient', './client/node');
|
||||
|
||||
// Coins
|
||||
hsd.define('coins', './coins');
|
||||
hsd.define('Coins', './coins/coins');
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
'use strict';
|
||||
|
||||
const assert = require('bsert');
|
||||
const {NodeClient} = require('hs-client');
|
||||
const NodeClient = require('../client/node');
|
||||
const TX = require('../primitives/tx');
|
||||
const Coin = require('../primitives/coin');
|
||||
const NameState = require('../covenants/namestate');
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ class NodeClient extends AsyncEmitter {
|
|||
// `data` is ignored because pool.spvFilter === walletDB.filter
|
||||
// and therefore is already updated.
|
||||
// Argument is kept here to be consistent with API in
|
||||
// wallet/client.js (hs-client NodeClient) and wallet/nullclient.js
|
||||
// wallet/client.js (client/node.js) and wallet/nullclient.js
|
||||
this.node.pool.queueFilterLoad();
|
||||
}
|
||||
|
||||
|
|
|
|||
31
package-lock.json
generated
31
package-lock.json
generated
|
|
@ -11,6 +11,7 @@
|
|||
"dependencies": {
|
||||
"bcfg": "~0.1.7",
|
||||
"bcrypto": "~5.4.0",
|
||||
"bcurl": "^0.2.0",
|
||||
"bdb": "~1.4.0",
|
||||
"bdns": "~0.1.5",
|
||||
"bevent": "~0.1.5",
|
||||
|
|
@ -33,7 +34,6 @@
|
|||
"bval": "~0.1.6",
|
||||
"bweb": "~0.1.11",
|
||||
"goosig": "~0.10.0",
|
||||
"hs-client": "~0.0.13",
|
||||
"n64": "~0.2.10",
|
||||
"urkel": "~1.0.2"
|
||||
},
|
||||
|
|
@ -423,25 +423,6 @@
|
|||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/hs-client": {
|
||||
"version": "0.0.13",
|
||||
"resolved": "https://registry.npmjs.org/hs-client/-/hs-client-0.0.13.tgz",
|
||||
"integrity": "sha512-3Vm/4S0TDstbOW+OfdTeP2EQ4dolPNqMulTSr31RihwX8cX1DyT4il1Fc9STXXToXTsZuFro2WD/+1m0MWi5Ag==",
|
||||
"dependencies": {
|
||||
"bcfg": "~0.1.7",
|
||||
"bcurl": "~0.2.0",
|
||||
"bsert": "~0.0.10"
|
||||
},
|
||||
"bin": {
|
||||
"hsd-cli": "bin/hsd-cli",
|
||||
"hsd-rpc": "bin/hsd-rpc",
|
||||
"hsw-cli": "bin/hsw-cli",
|
||||
"hsw-rpc": "bin/hsw-rpc"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/loady": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/loady/-/loady-0.0.5.tgz",
|
||||
|
|
@ -754,16 +735,6 @@
|
|||
"loady": "~0.0.5"
|
||||
}
|
||||
},
|
||||
"hs-client": {
|
||||
"version": "0.0.13",
|
||||
"resolved": "https://registry.npmjs.org/hs-client/-/hs-client-0.0.13.tgz",
|
||||
"integrity": "sha512-3Vm/4S0TDstbOW+OfdTeP2EQ4dolPNqMulTSr31RihwX8cX1DyT4il1Fc9STXXToXTsZuFro2WD/+1m0MWi5Ag==",
|
||||
"requires": {
|
||||
"bcfg": "~0.1.7",
|
||||
"bcurl": "~0.2.0",
|
||||
"bsert": "~0.0.10"
|
||||
}
|
||||
},
|
||||
"loady": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/loady/-/loady-0.0.5.tgz",
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
"dependencies": {
|
||||
"bcfg": "~0.1.7",
|
||||
"bcrypto": "~5.4.0",
|
||||
"bcurl": "^0.2.0",
|
||||
"bdb": "~1.4.0",
|
||||
"bdns": "~0.1.5",
|
||||
"bevent": "~0.1.5",
|
||||
|
|
@ -44,7 +45,6 @@
|
|||
"bval": "~0.1.6",
|
||||
"bweb": "~0.1.11",
|
||||
"goosig": "~0.10.0",
|
||||
"hs-client": "~0.0.13",
|
||||
"n64": "~0.2.10",
|
||||
"urkel": "~1.0.2"
|
||||
},
|
||||
|
|
|
|||
200
scripts/gen-hsclient.js
Executable file
200
scripts/gen-hsclient.js
Executable file
|
|
@ -0,0 +1,200 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
const fs = require('bfile');
|
||||
const os = require('os');
|
||||
const util = require('util');
|
||||
const cp = require('child_process');
|
||||
const exec = util.promisify(cp.exec);
|
||||
|
||||
const ROOT = path.dirname(__dirname);
|
||||
const HSD_PKG = require(path.join(ROOT, 'package.json'));
|
||||
|
||||
const REMOTE = 'git@github.com:handshake-org/hs-client.git';
|
||||
|
||||
const INIT_HS_CLIENT_PKG = {
|
||||
name: "hs-client",
|
||||
description: "HSD node and wallet client",
|
||||
keywords: [
|
||||
"http",
|
||||
"request",
|
||||
"socket.io",
|
||||
"websockets"
|
||||
],
|
||||
main: "./lib/client/index.js",
|
||||
bin: {
|
||||
"hsd-cli": "./bin/hsd-cli",
|
||||
"hsd-rpc": "./bin/hsd-rpc",
|
||||
"hsw-cli": "./bin/hsw-cli",
|
||||
"hsw-rpc": "./bin/hsw-rpc"
|
||||
},
|
||||
engines: {
|
||||
node: ">=8.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
const INHERIT_PROPERTIES = [
|
||||
"version",
|
||||
"license",
|
||||
"repository",
|
||||
"homepage",
|
||||
"bugs",
|
||||
"author"
|
||||
];
|
||||
|
||||
const DEPENDENCIES = [
|
||||
"bcfg",
|
||||
"bcurl",
|
||||
"bsert"
|
||||
];
|
||||
|
||||
const COPY_FILES = [
|
||||
".npmignore",
|
||||
".gitignore",
|
||||
"bin/hsd-cli",
|
||||
"bin/hsw-cli",
|
||||
"bin/hsd-rpc",
|
||||
"bin/hsw-rpc",
|
||||
"lib/client/index.js",
|
||||
"lib/client/wallet.js",
|
||||
"lib/client/node.js",
|
||||
];
|
||||
|
||||
const README = `
|
||||
hs-client
|
||||
=========
|
||||
|
||||
Autogenerated from https://github.com/handshake-org/hsd.
|
||||
|
||||
REST and RPC client for handshake.
|
||||
|
||||
## Usage
|
||||
|
||||
\`\`\` js
|
||||
const {NodeClient, WalletClient} = require('hs-client');
|
||||
\`\`\`
|
||||
`;
|
||||
|
||||
async function ensureDir() {
|
||||
if (!await fs.exists(ROOT))
|
||||
throw new Error(`${ROOT} does not exist.`);
|
||||
|
||||
const {HS_CLIENT_DIR} = process.env;
|
||||
|
||||
let HS_PKG = HS_CLIENT_DIR ? path.resolve(HS_CLIENT_DIR) : null;
|
||||
|
||||
if (!HS_PKG)
|
||||
HS_PKG = path.join(os.tmpdir(), `hs-client`);
|
||||
|
||||
|
||||
if (HS_PKG.startsWith(ROOT))
|
||||
throw new Error(`hs-client needs to be outside of the hsd. ${HS_PKG}`);
|
||||
|
||||
console.log('hs-client directory: ', HS_PKG);
|
||||
|
||||
if (await fs.exists(HS_PKG)) {
|
||||
throw new Error(
|
||||
`Directory ${HS_PKG} already exists.`
|
||||
+ ' Please remove to proceed or choose different directory.'
|
||||
);
|
||||
}
|
||||
|
||||
await fs.mkdir(HS_PKG);
|
||||
|
||||
return HS_PKG;
|
||||
}
|
||||
|
||||
async function setupPackageContent(dir) {
|
||||
for (const file of COPY_FILES) {
|
||||
const src = path.join(ROOT, file);
|
||||
const dst = path.join(dir, file);
|
||||
const dstDir = path.dirname(dst);
|
||||
|
||||
if (!await fs.exists(dstDir))
|
||||
await fs.mkdirp(dstDir);
|
||||
|
||||
await fs.copy(src, dst);
|
||||
}
|
||||
|
||||
const hsClientPkg = {
|
||||
...INIT_HS_CLIENT_PKG,
|
||||
};
|
||||
|
||||
for (const name of INHERIT_PROPERTIES) {
|
||||
assert(HSD_PKG[name]);
|
||||
hsClientPkg[name] = HSD_PKG[name];
|
||||
}
|
||||
|
||||
hsClientPkg.dependencies = {};
|
||||
for (const dep of DEPENDENCIES) {
|
||||
assert(HSD_PKG.dependencies[dep], `Dependency "${dep}" not found for hsd.`);
|
||||
hsClientPkg.dependencies[dep] = HSD_PKG.dependencies[dep];
|
||||
}
|
||||
|
||||
await fs.writeJSON(path.join(dir, 'package.json'), hsClientPkg);
|
||||
await fs.writeFile(path.join(dir, 'README.md'), README);
|
||||
|
||||
return hsClientPkg;
|
||||
}
|
||||
|
||||
async function setupGit(dir, version) {
|
||||
console.log('Setting up git: ', dir);
|
||||
const commands = [
|
||||
'git init -b master',
|
||||
`git remote add origin ${REMOTE}`,
|
||||
'git add .',
|
||||
`git commit --gpg-sign -m "v${version}"`,
|
||||
`git tag --sign v${version} -m "v${version}"`
|
||||
];
|
||||
|
||||
const manualCommands = [
|
||||
'git push -f origin master',
|
||||
`git push -f origin v${version}`
|
||||
];
|
||||
|
||||
for (const cmd of [...commands]) {
|
||||
console.log(`executing: ${cmd} in ${dir}.`);
|
||||
|
||||
try {
|
||||
console.log(await execCmd(cmd, dir));
|
||||
} catch (e) {
|
||||
console.log(`Failed to execute: ${cmd}.`);
|
||||
console.log(e.message);
|
||||
console.log(' You can proceed manually');
|
||||
break;
|
||||
}
|
||||
|
||||
commands.shift();
|
||||
}
|
||||
|
||||
for (const command of [...commands, ...manualCommands])
|
||||
console.log(`Needs exec: ${command}`);
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const HS_PKG = await ensureDir();
|
||||
const pkg = await setupPackageContent(HS_PKG);
|
||||
|
||||
await setupGit(HS_PKG, pkg.version);
|
||||
console.log('Needs: npm publish');
|
||||
})().catch((err) => {
|
||||
console.error(err.stack);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
async function execCmd(cmd, cwd, timeout = 2000) {
|
||||
assert(cwd, 'CWD is required.');
|
||||
|
||||
const {stdout, stderr} = await exec(cmd, {
|
||||
cwd,
|
||||
timeout
|
||||
});
|
||||
|
||||
if (stderr.length != 0)
|
||||
throw new Error(stderr);
|
||||
|
||||
return stdout;
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ const {
|
|||
Network,
|
||||
Path
|
||||
} = require('..');
|
||||
const {NodeClient, WalletClient} = require('hs-client');
|
||||
const {NodeClient, WalletClient} = require('../lib/client');
|
||||
const {forValue} = require('./util/common');
|
||||
|
||||
class TestUtil {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const node = new FullNode({
|
|||
plugins: [require('../lib/wallet/plugin')]
|
||||
});
|
||||
|
||||
const {NodeClient, WalletClient} = require('hs-client');
|
||||
const {NodeClient, WalletClient} = require('../lib/client');
|
||||
|
||||
const nclient = new NodeClient({
|
||||
port: network.rpcPort,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const Script = require('../lib/script/script');
|
|||
const rules = require('../lib/covenants/rules');
|
||||
const {types} = rules;
|
||||
const {Resource} = require('../lib/dns/resource');
|
||||
const {WalletClient} = require('hs-client');
|
||||
const WalletClient = require('../lib/client/wallet');
|
||||
|
||||
const network = Network.get('regtest');
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
const assert = require('bsert');
|
||||
const bio = require('bufio');
|
||||
const {NodeClient} = require('hs-client');
|
||||
const NodeClient = require('../lib/client/node');
|
||||
const Network = require('../lib/protocol/network');
|
||||
const FullNode = require('../lib/node/fullnode');
|
||||
const Address = require('../lib/primitives/address');
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ const Network = require('../lib/protocol/network');
|
|||
const consensus = require('../lib/protocol/consensus');
|
||||
const MemWallet = require('./util/memwallet');
|
||||
const TX = require('../lib/primitives/tx');
|
||||
const {NodeClient} = require('hs-client');
|
||||
const NodeClient = require('../lib/client/node');
|
||||
|
||||
const TIMEOUT = 15000;
|
||||
const API_KEY = 'foo';
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const FullNode = require('../lib/node/fullnode');
|
|||
const Address = require('../lib/primitives/address');
|
||||
const rules = require('../lib/covenants/rules');
|
||||
const Resource = require('../lib/dns/resource');
|
||||
const {WalletClient} = require('hs-client');
|
||||
const WalletClient = require('../lib/client/wallet');
|
||||
|
||||
const network = Network.get('regtest');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const {NodeClient, WalletClient} = require('hs-client');
|
||||
const {NodeClient, WalletClient} = require('../lib/client');
|
||||
const Network = require('../lib/protocol/network');
|
||||
const FullNode = require('../lib/node/fullnode');
|
||||
const MTX = require('../lib/primitives/mtx');
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const Network = require('../lib/protocol/network');
|
|||
const FullNode = require('../lib/node/fullnode');
|
||||
const Address = require('../lib/primitives/address');
|
||||
const rules = require('../lib/covenants/rules');
|
||||
const {WalletClient} = require('hs-client');
|
||||
const WalletClient = require('../lib/client/wallet');
|
||||
const {forValue} = require('./util/common');
|
||||
|
||||
const network = Network.get('regtest');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const {NodeClient,WalletClient} = require('hs-client');
|
||||
const assert = require('bsert');
|
||||
const {NodeClient, WalletClient} = require('../lib/client');
|
||||
const FullNode = require('../lib/node/fullnode');
|
||||
const Network = require('../lib/protocol/network');
|
||||
const Mnemonic = require('../lib/hd/mnemonic');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const assert = require('bsert');
|
||||
const {WalletClient} = require('hs-client');
|
||||
const WalletClient = require('../lib/client/wallet');
|
||||
const consensus = require('../lib/protocol/consensus');
|
||||
const Network = require('../lib/protocol/network');
|
||||
const util = require('../lib/utils/util');
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue