@vdinar/vdinar-rpc

A JavaScript RPC client for vDinar.

Usage no npm install needed!

<script type="module">
  import vdinarVdinarRpc from 'https://cdn.skypack.dev/@vdinar/vdinar-rpc';
</script>

README

vdinar-rpc

A JavaScript RPC client for vDinar to execute administrative tasks, queries about the network and blockchain.

Usage

Client(...args)

Arguments

  1. [agentOptions] (Object): Optional agent options 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('vdinar-rpc')] (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).

Examples

Using network mode

The network will automatically determine the port to connect to, just like the vdinard command.

const Client = require('vdinar-rpc');
const client = new Client({ network: 'mainnet' });
Setting a custom port
const client = new Client({ port: 9334 });

Connecting to an SSL/TLS server with strict checking enabled

By default, when ssl is enabled, strict checking is implicitly enabled.

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

Connecting to an SSL/TLS server without strict checking enabled

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

Using promises to process the response

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

Using callbacks to process the response

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

Returning headers in the response

For compatibility with other vDinar RPC clients.

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

It is 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.

const client = new Client({ version: '2.1.0' });

For instance, take the getBalance() call written using positional arguments:

const balance = await new Client().getBalance('*', 0);

It is functionally equivalent to using the named arguments account and minconf:

const balance = await new Client({ version: '2.1.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, 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.

Version Checking

By default, all methods are exposed on the client independently of the version it is connecting to. This is the most flexible option as defining methods for unavailable RPC calls does not cause any harm and the library is capable of handling a Method not found response error correctly.

const client = new Client();

client.command('foobar');
// => RpcError: -32601 Method not found

However, if you prefer to be on the safe side, you can enable strict version checking. This will validate all method calls before executing the actual RPC request:

const client = new Client({ version: '2.0.0' });

client.getHashesPerSec();
// => Method "getnetworkinfo" is not supported by version "2.0.0"

If you want to enable strict version checking for the bleeding edge version, you may set a very high version number to exclude recently deprecated calls:

const client = new Client({ version: `${Number.MAX_SAFE_INTEGER}.0.0` });

client.getWork();
// => Throws 'Method "getwork" is not supported by version "9007199254740991.0.0"'.

To avoid potential issues with prototype references, all methods are still enumerable on the library client prototype.

RPC

Start vdinard with the RPC server enabled and optionally configure a username and password:

docker run --rm -it AndreaDejanGrande/vdinar-rpc -printtoconsole -rpcuser=foo -rpcpassword=bar -server

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

By default, port 9333 is used to listen for requests in mainnet mode, or 19333 in testnet. 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 are exposed on the client interface as a camelcase'd version of those available on vdinard (see examples below).

Examples
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.

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.

const batch = [
  { method: 'foobar', params: [] },
  { method: 'getnewaddress', params: [] }
]

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

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

Logging

By default, all requests made with vdinar-rpc are logged using uphold/debugnyan with vdinar-rpc as the logging namespace.

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

Custom logger

A custom logger can be passed via the logger option and it should implement bunyan's log levels.

Tests

Currently the test suite is tailored for Docker (including docker-compose) due to the multitude of different vdinard 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. vdinard) running inside Docker:

npm run dependencies
npm test

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

npm run testdocker

Release

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

License

MIT