Skip to content

Commit

Permalink
Remove bluebird dependency and callbacks support
Browse files Browse the repository at this point in the history
  • Loading branch information
pedrobranco committed Feb 11, 2019
1 parent aad875c commit cc2d271
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 175 deletions.
45 changes: 17 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,10 @@ client.getInfo().then((help) => console.log(help));

#### Using callbacks to process the response

Callback support was removed. Since every method returns a `Promise`, [callbackify()](https://nodejs.org/api/util.html#util_util_callbackify_original) (`>node@v8.2.0`) can be used, or for older `node` versions you can use the npm package [callbackify](https://www.npmjs.com/package/callbackify).

```js
client.getInfo((error, help) => console.log(help));
util.callbackify(() => client.getInfo())((error, help) => console.log(help));
```

#### Returning headers in the response
Expand Down Expand Up @@ -282,108 +284,95 @@ These configuration values may also be set on the `bitcoin.conf` file of your pl

Unlike RPC methods which are automatically exposed on the client, REST ones are handled individually as each method has its own specificity. The following methods are supported:

- [getBlockByHash](#getblockbyhashhash-options-callback)
- [getBlockHeadersByHash](#getblockheadersbyhashhash-count-options-callback)
- [getBlockchainInformation](#getblockchaininformationcallback)
- [getBlockByHash](#getblockbyhashhash-options)
- [getBlockHeadersByHash](#getblockheadersbyhashhash-count-options)
- [getBlockchainInformation](#getblockchaininformation)
- [getMemoryPoolContent](#getmemorypoolcontent)
- [getMemoryPoolInformation](#getmemorypoolinformationcallback)
- [getTransactionByHash](#gettransactionbyhashhash-options-callback)
- [getUnspentTransactionOutputs](#getunspenttransactionoutputsoutpoints-options-callback)
- [getMemoryPoolInformation](#getmemorypoolinformation)
- [getTransactionByHash](#gettransactionbyhashhash-options)
- [getUnspentTransactionOutputs](#getunspenttransactionoutputsoutpoints-options)

#### getBlockByHash(hash, [options], [callback])
#### getBlockByHash(hash, [options])
Given a block hash, returns a block, in binary, hex-encoded binary or JSON formats.

##### Arguments
1. `hash` _(string)_: The block hash.
2. `[options]` _(Object)_: The options object.
3. `[options.extension=json]` _(string)_: Return in binary (`bin`), hex-encoded binary (`hex`) or JSON (`json`) format.
4. `[callback]` _(Function)_: An optional callback, otherwise a Promise is returned.

##### Example

```js
client.getBlockByHash('0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206', { extension: 'json' });
```

#### getBlockHeadersByHash(hash, count, [options][, callback])
#### getBlockHeadersByHash(hash, count, [options])
Given a block hash, returns amount of block headers in upward direction.

##### Arguments
1. `hash` _(string)_: The block hash.
2. `count` _(number)_: The number of blocks to count in upward direction.
3. `[options]` _(Object)_: The options object.
4. `[options.extension=json]` _(string)_: Return in binary (`bin`), hex-encoded binary (`hex`) or JSON (`json`) format.
5. `[callback]` _(Function)_: An optional callback, otherwise a Promise is returned.

##### Example

```js
client.getBlockHeadersByHash('0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206', 1, { extension: 'json' });
```

#### getBlockchainInformation([callback])
#### getBlockchainInformation()
Returns various state info regarding block chain processing.

#### Arguments
1. `[callback]` _(Function)_: An optional callback, otherwise a Promise is returned.

##### Example

```js
client.getBlockchainInformation([callback]);
client.getBlockchainInformation();
```

#### getMemoryPoolContent()
Returns transactions in the transaction memory pool.

#### Arguments
1. `[callback]` _(Function)_: An optional callback, otherwise a Promise is returned.

##### Example

```js
client.getMemoryPoolContent();
```

#### getMemoryPoolInformation([callback])
#### getMemoryPoolInformation()
Returns various information about the transaction memory pool. Only supports JSON as output format.
- size: the number of transactions in the transaction memory pool.
- bytes: size of the transaction memory pool in bytes.
- usage: total transaction memory pool memory usage.

#### Arguments
1. `[callback]` _(Function)_: An optional callback, otherwise a Promise is returned.

##### Example

```js
client.getMemoryPoolInformation();
```

#### getTransactionByHash(hash, [options], [callback])
#### getTransactionByHash(hash, [options])
Given a transaction hash, returns a transaction in binary, hex-encoded binary, or JSON formats.

#### Arguments
1. `hash` _(string)_: The transaction hash.
2. `[options]` _(Object)_: The options object.
3. `[options.summary=false]` _(boolean)_: Whether to return just the transaction hash, thus saving memory.
4. `[options.extension=json]` _(string)_: Return in binary (`bin`), hex-encoded binary (`hex`) or JSON (`json`) format.
5. `[callback]` _(Function)_: An optional callback, otherwise a Promise is returned.

##### Example

```js
client.getTransactionByHash('b4dd08f32be15d96b7166fd77afd18aece7480f72af6c9c7f9c5cbeb01e686fe', { extension: 'json', summary: false });
```

#### getUnspentTransactionOutputs(outpoints, [options], [callback])
#### getUnspentTransactionOutputs(outpoints, [options])
Query unspent transaction outputs (UTXO) for a given set of outpoints. See [BIP64](https://github.com/bitcoin/bips/blob/master/bip-0064.mediawiki) for input and output serialisation.

#### Arguments
1. `outpoints` _(array\<Object\>|Object)_: The outpoint to query in the format `{ id: '<txid>', index: '<index>' }`.
2. `[options]` _(Object)_: The options object.
3. `[options.extension=json]` _(string)_: Return in binary (`bin`), hex-encoded binary (`hex`) or JSON (`json`) format.
4. `[callback]` _(Function)_: An optional callback, otherwise a Promise is returned.

##### Example

Expand All @@ -394,7 +383,7 @@ client.getUnspentTransactionOutputs([{
}, {
id: '0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206',
index: 1
}], { extension: 'json' }, [callback])
}], { extension: 'json' })
```

### SSL
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
},
"dependencies": {
"@uphold/request-logger": "^2.0.0",
"bluebird": "^3.4.1",
"debugnyan": "^1.0.0",
"json-bigint": "^0.2.0",
"lodash": "^4.0.0",
Expand Down
143 changes: 49 additions & 94 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,13 @@
*/

import Parser from './parser';
import Promise from 'bluebird';
import Requester from './requester';
import _ from 'lodash';
import debugnyan from 'debugnyan';
import methods from './methods';
import requestLogger from './logging/request-logger';
import semver from 'semver';

/**
* Source arguments to find out if a callback has been passed.
*/

function source(...args) {
const last = _.last(args);

let callback;

if (_.isFunction(last)) {
callback = last;
args = _.dropRight(args);
}

return [args, callback];
}

/**
* List of networks and their default port mapping.
*/
Expand All @@ -39,6 +21,22 @@ const networks = {
testnet: 18332
};

/**
* Promisify helper.
*/

const promisify = fn => (...args) => new Promise((resolve, reject) => {
fn(...args, (error, value) => {
if (error) {
reject(error);

return;
}

resolve(value);
});
});

/**
* Constructor.
*/
Expand Down Expand Up @@ -105,12 +103,14 @@ class Client {

const request = requestLogger(logger);

this.request = Promise.promisifyAll(request.defaults({
this.request = request.defaults({
agentOptions: this.agentOptions,
baseUrl: `${this.ssl.enabled ? 'https' : 'http'}://${this.host}:${this.port}`,
strictSSL: this.ssl.strict,
timeout: this.timeout
}), { multiArgs: true });
});
this.request.getAsync = promisify(this.request.get);
this.request.postAsync = promisify(this.request.post);
this.requester = new Requester({ methods: this.methods, version });
this.parser = new Parser({ headers: this.headers });
}
Expand All @@ -119,19 +119,12 @@ class Client {
* Execute `rpc` command.
*/

command(...args) {
async command(...args) {
let body;
let callback;
let multiwallet;
let [input, ...parameters] = args; // eslint-disable-line prefer-const
const lastArg = _.last(parameters);
const isBatch = Array.isArray(input);

if (_.isFunction(lastArg)) {
callback = lastArg;
parameters = _.dropRight(parameters);
}

if (isBatch) {
multiwallet = _.some(input, command => {
return _.get(this.methods[command.method], 'features.multiwallet.supported', false) === true;
Expand All @@ -151,30 +144,22 @@ class Client {
body = this.requester.prepare({ method: input, parameters });
}

return Promise.try(() => {
return this.request.postAsync({
auth: _.pickBy(this.auth, _.identity),
body: JSON.stringify(body),
uri: `${multiwallet && this.wallet ? `/wallet/${this.wallet}` : '/'}`
}).bind(this)
.then(this.parser.rpc);
}).asCallback(callback);
return this.parser.rpc(await this.request.postAsync({
auth: _.pickBy(this.auth, _.identity),
body: JSON.stringify(body),
uri: `${multiwallet && this.wallet ? `/wallet/${this.wallet}` : '/'}`
}));
}

/**
* Given a transaction hash, returns a transaction in binary, hex-encoded binary, or JSON formats.
*/

getTransactionByHash(...args) {
const [[hash, { extension = 'json' } = {}], callback] = source(...args);

return Promise.try(() => {
return this.request.getAsync({
encoding: extension === 'bin' ? null : undefined,
url: `/rest/tx/${hash}.${extension}`
}).bind(this)
.then(_.partial(this.parser.rest, extension));
}).asCallback(callback);
async getTransactionByHash(hash, { extension = 'json' } = {}) {
return this.parser.rest(extension, await this.request.getAsync({
encoding: extension === 'bin' ? null : undefined,
url: `/rest/tx/${hash}.${extension}`
}));
}

/**
Expand All @@ -183,46 +168,31 @@ class Client {
* hash instead of the complete transaction details. The option only affects the JSON response.
*/

getBlockByHash(...args) {
const [[hash, { summary = false, extension = 'json' } = {}], callback] = source(...args);
async getBlockByHash(hash, { summary = false, extension = 'json' } = {}) {
const encoding = extension === 'bin' ? null : undefined;
const url = `/rest/block${summary ? '/notxdetails/' : '/'}${hash}.${extension}`;

return Promise.try(() => {
return this.request.getAsync({
encoding: extension === 'bin' ? null : undefined,
url: `/rest/block${summary ? '/notxdetails/' : '/'}${hash}.${extension}`
}).bind(this)
.then(_.partial(this.parser.rest, extension));
}).asCallback(callback);
return this.parser.rest(extension, await this.request.getAsync({ encoding, url }));
}

/**
* Given a block hash, returns amount of blockheaders in upward direction.
*/

getBlockHeadersByHash(...args) {
const [[hash, count, { extension = 'json' } = {}], callback] = source(...args);
async getBlockHeadersByHash(hash, count, { extension = 'json' } = {}) {
const encoding = extension === 'bin' ? null : undefined;
const url = `/rest/headers/${count}/${hash}.${extension}`;

return Promise.try(() => {
return this.request.getAsync({
encoding: extension === 'bin' ? null : undefined,
url: `/rest/headers/${count}/${hash}.${extension}`
}).bind(this)
.then(_.partial(this.parser.rest, extension));
}).asCallback(callback);
return this.parser.rest(extension, await this.request.getAsync({ encoding, url }));
}

/**
* Returns various state info regarding block chain processing.
* Only supports JSON as output format.
*/

getBlockchainInformation(...args) {
const [, callback] = source(...args);

return this.request.getAsync(`/rest/chaininfo.json`)
.bind(this)
.then(_.partial(this.parser.rest, 'json'))
.asCallback(callback);
async getBlockchainInformation() {
return this.parser.rest('json', await this.request.getAsync(`/rest/chaininfo.json`));
}

/**
Expand All @@ -231,33 +201,23 @@ class Client {
* - https://github.com/bitcoin/bips/blob/master/bip-0064.mediawiki
*/

getUnspentTransactionOutputs(...args) {
const [[outpoints, { extension = 'json' } = {}], callback] = source(...args);

async getUnspentTransactionOutputs(outpoints, { extension = 'json' } = {}) {
const encoding = extension === 'bin' ? null : undefined;
const sets = _.flatten([outpoints]).map(outpoint => {
return `${outpoint.id}-${outpoint.index}`;
}).join('/');
const url = `/rest/getutxos/checkmempool/${sets}.${extension}`;

return this.request.getAsync({
encoding: extension === 'bin' ? null : undefined,
url: `/rest/getutxos/checkmempool/${sets}.${extension}`
}).bind(this)
.then(_.partial(this.parser.rest, extension))
.asCallback(callback);
return this.parser.rest(extension, await this.request.getAsync({ encoding, url }));
}

/**
* Returns transactions in the transaction memory pool.
* Only supports JSON as output format.
*/

getMemoryPoolContent(...args) {
const [, callback] = source(...args);

return this.request.getAsync('/rest/mempool/contents.json')
.bind(this)
.then(_.partial(this.parser.rest, 'json'))
.asCallback(callback);
async getMemoryPoolContent() {
return this.parser.rest('json', await this.request.getAsync('/rest/mempool/contents.json'));
}

/**
Expand All @@ -269,13 +229,8 @@ class Client {
* - usage: total transaction memory pool memory usage.
*/

getMemoryPoolInformation(...args) {
const [, callback] = source(...args);

return this.request.getAsync('/rest/mempool/info.json')
.bind(this)
.then(_.partial(this.parser.rest, 'json'))
.asCallback(callback);
async getMemoryPoolInformation() {
return this.parser.rest('json', await this.request.getAsync('/rest/mempool/info.json'));
}
}

Expand Down
Loading

0 comments on commit cc2d271

Please sign in to comment.