npm package: @genesisnetwork/genesis-core
Description: A modern Genesis Official REST and RPC client.
Author: Shelby Sowell
Latest version: 3.0.0

# Genx-Core
A modern Genesis Official REST and RPC client to execute administrative tasks, [multiwallet](https://bitcoincore.org/en/2017/09/01/release-0.15.0/#multiwallet) operations and queries about network and the blockchain.

## Installation

Install the package via `npm`:

```sh
npm install genesis-core --save
```

## Usage
### Client(...args)
#### Arguments
1. `[agentOptions]` _(Object)_: Optional `agent` [options](https://github.com/request/request#using-optionsagentoptions) to configure SSL/TLS.
2. `[headers=false]` _(boolean)_: Whether to return the response headers.
3. `[host=localhost]` _(string)_: The host to connect to.
4. `[logger=debugnyan('genesis-core')]` _(Function)_: Custom logger (by default, `debugnyan`).
5. `[network=mainnet]` _(string)_: The network
6. `[password]` _(string)_: The RPC server user password.
7. `[port=[network]]` _(string)_: The RPC server port.
8. `[ssl]` _(boolean|Object)_: Whether to use SSL/TLS with strict checking (_boolean_) or an expanded config (_Object_).
9. `[ssl.enabled]` _(boolean)_: Whether to use SSL/TLS.
10. `[ssl.strict]` _(boolean)_: Whether to do strict SSL/TLS checking (certificate must match host).
11. `[timeout=30000]` _(number)_: How long until the request times out (ms).
12. `[username]` _(number)_: The RPC server user name.
13. `[version]` _(string)_: Which version to check methods for ([read more](#versionchecking)).
14. `[wallet]` _(string)_: Which wallet to manage ([read more](#multiwallet)).

### Examples
#### Using network mode
The `network` will automatically determine the port to connect to, just like the `genesisd` and `genesis-cli` commands.

```js
const Client = require('genesis-core');
const client = new Client({ network: 'regtest' });
```

##### Setting a custom port

```js
const client = new Client({ port: 12345 });
```

#### Connecting to an SSL/TLS server with strict checking enabled
By default, when `ssl` is enabled, strict checking is implicitly enabled.

```js
const fs = require('fs');
const client = new Client({
  agentOptions: {
    ca: fs.readFileSync('/etc/ssl/genesisd/cert.pem')
  },
  ssl: true
});
```

#### Connecting to an SSL/TLS server without strict checking enabled

```js
const client = new Client({
  ssl: {
    enabled: true,
    strict: false
  }
});
```

#### Using promises to process the response

```js
client.getInfo().then((help) => console.log(help));
```

#### Using callbacks to process the response

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

#### Returning headers in the response
For compatibility with other Genesis Official clients.

```js
const client = new Client({ headers: true });

// Promise style with headers enabled:
client.getInfo().then(([body, headers]) => console.log(body, headers));

// Await style based on promises with headers enabled:
const [body, headers] = await client.getInfo();
```

## Named parameters

Genesis Official v3+ makes it possible to send commands via the JSON-RPC interface using named parameters instead of positional ones. This comes with the advantage of making the order of arguments irrelevant. It also helps improving the readability of certain function calls when leaving out arguments for their default value.

You **must** provide a version in the client arguments to enable named parameters.

```js
const client = new Client({ version: '3.0.0' });
```
For instance, take the `getBalance()` call written using positional arguments:
```js
const balance = await new Client().getBalance('*', 0);
```

It is functionally equivalent to using the named arguments `account` and `minconf`, leaving out `include_watchonly` (defaults to `false`):

```js
const balance = await new Client({ version: '3.0.0' }).getBalance({
  account: '*',
  minconf: 0
});
```

This feature is available to all JSON-RPC methods that accept arguments.

### Floating point number precision in JavaScript

Due to [JavaScript's limited floating point precision](http://floating-point-gui.de/), all big numbers (numbers with more than 15 significant digits) are returned as strings to prevent precision loss. This includes both the RPC and REST APIs.

## Multiwallet

Genesis Official v3+ makes it possible to manage multiple wallets using a single daemon. This enables use-cases such as managing a personal and a business wallet simultaneously in order to simplify accounting and accidental misuse of funds.

Historically, the _accounts_ feature was supposed to offer similar functionality, but it has now been replaced by this more powerful feature.

To enable Multi Wallet support, start by specifying the number of added wallets you would like to have available and loaded on the server using the `-wallet` argument multiple times. For convenience, the genesis-core docker image will be used, but it's not a requirement:

```sh
docker run --rm -it -p 17234:17234 genesisnetwork/genesis-core:master \
  -printtoconsole \
  -server \
  -rpcauth='foo:e1fcea9fb59df8b0388f251984fe85$26431097d48c5b6047df8dee64f387f63835c01a2a463728ad75087d0133b8e6' \
  -regtest \
  -wallet=wallet1.dat \
  -wallet=wallet2.dat \
  -rpcallowip=172.17.0.0/16
```

Notice the `rpcauth` hash which has been previously generated for the password `j1DuzF7QRUp-iSXjgewO9T_WT1Qgrtz_XWOHCMn_O-Y=`. Do **not** copy and paste this hash **ever** beyond this exercise.

Instantiate a client for each wallet and execute commands targeted at each wallet:

```js
const Client = require('genesis-core');

const wallet1 = new Client({
  network: 'regtest',
  wallet: 'wallet1.dat',
  username: 'foo',
  password: 'j1DuzF7QRUp-iSXjgewO9T_WT1Qgrtz_XWOHCMn_O-Y='
});

const wallet2 = new Client({
  network: 'regtest',
  wallet: 'wallet2.dat',
  username: 'foo',
  password: 'j1DuzF7QRUp-iSXjgewO9T_WT1Qgrtz_XWOHCMn_O-Y='
});

(async function() {
  await wallet2.generate(100);

  console.log(await wallet1.getBalance());
  // => 0
  console.log(await wallet2.getBalance());
  // => 50
}());
```

### RPC
Start the `genesisd` with the RPC server enabled and optionally configure a username and password:

```sh
docker run --rm -it genesisnetwork/genesis-core:master -printtoconsole -rpcuser=foo -rpcpassword=bar -server
```

These configuration values may also be set on the `genesis.conf` file of your platform installation.

By default, port `7234` is used to listen for requests in `mainnet` mode, or `17234` in `testnet` and and `27234` in `regtest` modes. Use the `network` property to initialize the client on the desired mode and automatically set the respective default port. You can optionally set a custom port of your choice too.

The RPC services binds to the localhost loopback network interface, so use `rpcbind` to change where to bind to and `rpcallowip` to whitelist source IP access.

#### Methods
All RPC [methods](src/methods.js) are exposed on the client interface as a camelcase'd version of those available on `genesisd` (see examples below).

##### Examples

```js
client.createRawTransaction([{ txid: '1eb590cd06127f78bf38ab4140c4cdce56ad9eb8886999eb898ddf4d3b28a91d', vout: 0 }], { 'mgnucj8nYqdrPFh2JfZSB1NmUThUGnmsqe': 0.13 });
client.sendMany('test1', { mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN: 0.1, mgnucj8nYqdrPFh2JfZSB1NmUThUGnmsqe: 0.2 }, 6, 'Example Transaction');
client.sendToAddress('mmXgiR6KAhZCyQ8ndr2BCfEq1wNG2UnyG6', 0.1,  'sendtoaddress example', 'Nemo From Example.com');
```

#### Batch requests
Batch requests are support by passing an array to the `command` method with a `method` and optionally, `parameters`. The return value will be an array with all the responses.

```js
const batch = [
  { method: 'getnewaddress', parameters: [] },
  { method: 'getnewaddress', parameters: [] }
]

new Client().command(batch).then((responses) => console.log(responses)));

// Or, using ES2015 destructuring.
new Client().command(batch).then(([firstAddress, secondAddress]) => console.log(firstAddress, secondAddress)));
```

Note that batched requests will only throw an error if the batch request itself cannot be processed. However, each individual response may contain an error akin to an individual request.

```js
const batch = [
  { method: 'foobar', parameters: [] },
  { method: 'getnewaddress', parameters: [] }
]

new Client().command(batch).then(([address, error]) => console.log(address, error)));
// => `mkteeBFmGkraJaWN5WzqHCjmbQWVrPo5X3, { [RpcError: Method not found] message: 'Method not found', name: 'RpcError', code: -32601 }`.
```

### REST
Support for the REST interface is still **experimental** and the API is still subject to change. These endpoints are also **unauthenticated** so [there are certain risks which you should be aware](https://github.com/bitcoin/bitcoin/blob/master/doc/REST-interface.md#risks), specifically of leaking sensitive data of the node if not correctly protected.

Error handling is still fragile so avoid passing user input.

Start the `genesisd` with the REST server enabled:

```sh
docker run --rm -it genesisnetwork/genesis-core:master -printtoconsole -server -rest
```

These configuration values may also be set on the `genesis.conf` file of your platform installation. Use `txindex=1` if you'd like to enable full transaction query support (note: this will take a considerable amount of time on the first run).

### Methods

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)
- [getMemoryPoolContent](#getmemorypoolcontent)
- [getMemoryPoolInformation](#getmemorypoolinformationcallback)
- [getTransactionByHash](#gettransactionbyhashhash-options-callback)
- [getUnspentTransactionOutputs](#getunspenttransactionoutputsoutpoints-options-callback)

#### getBlockByHash(hash, [options], [callback])
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])
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])
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]);
```

#### 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])
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])
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])
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

```js
client.getUnspentTransactionOutputs([{
  id: '0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206',
  index: 0
}, {
  id: '0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206',
  index: 1
}], { extension: 'json' }, [callback])
```

### SSL
This client supports SSL out of the box. Simply pass the SSL public certificate to the client and optionally disable strict SSL checking which will bypass SSL validation (the connection is still encrypted but the server it is connecting to may not be trusted). This is, of course, discouraged unless for testing purposes when using something like self-signed certificates.

#### Generating a self-signed certificates for testing purposes
Please note that the following procedure should only be used for testing purposes.

Generate an self-signed certificate together with an unprotected private key:

```sh
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3650 -nodes
```

#### Connecting via SSL
With Genesis Official you can start the `genesisd` RPC server directly with SSL:

```sh
docker run --rm -it -v $(PWD)/ssl:/etc/ssl genesisnetwork/genesis-core:master -printtoconsole -rpcuser=foo -rpcpassword=bar -rpcssl -rpcsslcertificatechainfile=/etc/ssl/genesisd/cert.pem -rpcsslprivatekeyfile=/etc/ssl/genesisd/key.pem -server
```

## Logging

By default, all requests made with `genesis-core` are logged using [uphold/debugnyan](https://github.com/uphold/debugnyan) with `genesis-core` as the logging namespace.

Please note that all sensitive data is obfuscated before calling the logger.

#### Example

Example output defining the environment variable `DEBUG=genesis-core`:

```javascript
const client = new Client();

client.getTransactionByHash('b4dd08f32be15d96b7166fd77afd18aece7480f72af6c9c7f9c5cbeb01e686fe');

// {
//   "name": "genesis-core",
//   "hostname": "localhost",
//   "pid": 57908,
//   "level": 20,
//   "request": {
//     "headers": {
//       "host": "localhost:7234",
//       "accept": "application/json"
//     },
//     "id": "82cea4e5-2c85-4284-b9ec-e5876c84e67c",
//     "method": "GET",
//     "type": "request",
//     "uri": "http://localhost:7234/rest/tx/b4dd08f32be15d96b7166fd77afd18aece7480f72af6c9c7f9c5cbeb01e686fe.json"
//   },
//   "msg": "Making request 82cea4e5-2c85-4284-b9ec-e5876c84e67c to GET http://localhost:7234/rest/tx/b4dd08f32be15d96b7166fd77afd18aece7480f72af6c9c7f9c5cbeb01e686fe.json",
//   "time": "2017-02-07T14:40:35.020Z",
//   "v": 0
// }
```

### Custom logger

A custom logger can be passed via the `logger` option and it should implement [bunyan's log levels](https://github.com/trentm/node-bunyan#levels).

## Tests
Currently the test suite is tailored for Docker (including `docker-compose`) due to the multitude of different `genesisd` configurations that are required in order to get the test suite passing.

To test using a local installation of `node.js` but with dependencies (e.g. `genesisd`) running inside Docker:

```sh
npm run dependencies
npm test
```

To test using Docker exclusively (similarly to what is done in Travis CI):

```sh
npm run testdocker
```

## Release

```sh
npm version [<newversion> | major | minor | patch] -m "Release %s"
```

## License
MIT

[npm-image]: https://img.shields.io/npm/v/genesis-core.svg?style=flat-square
[npm-url]: https://npmjs.org/package/genesis-core