0.0.3 • Published 5 years ago

@carnesen/bitcoin-config v0.0.3

Weekly downloads
-
License
MIT
Repository
github
Last release
5 years ago

@carnesen/bitcoin-config Build Status

A Node.js library for bitcoin server software configuration

Install

$ npm install @carnesen/bitcoin-config

The package includes runtime JavaScript files suitable for Node.js >=8 as well as the corresponding TypeScript type declarations.

Usage

Here's an example that reads and parses the default configuration file (e.g. ~/.bitcoin/bitcoin.conf on Linux):

const { readConfigFiles, DEFAULT_CONFIG_FILE_PATH } = require('@carnesen/bitcoin-config');

const config = readConfigFiles(DEFAULT_CONFIG_FILE_PATH);

console.log(config);
/*
{ regtest: true,
  daemon: true,
  rpcconnect: '1.2.3.4',
  rpcport: 33333 }
*/

In TypeScript, the returned config object is intelligently typed, e.g. regtest has type boolean.

Here's an example of writing a configuration file:

const { writeConfigFile, DEFAULT_CONFIG_FILE_PATH } = require('@carnesen/bitcoin-config');

const { changed } = writeConfigFile(DEFAULT_CONFIG_FILE_PATH, {
  regtest: true,
  rpcconnect: '1.2.3.4',
  sections: {
    regtest: {
      rpcport: 33333,
    },
  },
});

const message = changed
  ? `Wrote "${DEFAULT_CONFIG_FILE_PATH}"`
  : `File "${DEFAULT_CONFIG_FILE_PATH}" has not changed`;

console.log(message);

Now the file at DEFAULT_CONFIG_FILE_PATH has contents:

# This is a bitcoin configuration file written using @carnesen/bitcoin-config

# Run this node on its own independent test network.
regtest=1

# Send commands to node running on <ip>
rpcconnect=1.2.3.4

[regtest]

# Listen for JSON-RPC connections on this port.
rpcport=33333

Suppose now we want to update the configuration file:

const { updateConfigFile, DEFAULT_CONFIG_FILE_PATH } = require('@carnesen/bitcoin-config');

updateConfigFile(DEFAULT_CONFIG_FILE_PATH, {
  daemon: true,
  rpcconnect: null,
});

This update means "set the daemon property to true and unset (delete) the rpcconnect property".

API

DEFAULT_CONFIG_FILE_PATH

string. The (platform-dependent) default path of the bitcoin configuration file, e.g. ~/.bitcoin/bitcoin.conf on Linux.

BITCOIN_CONFIG_OPTIONS

{[optionName: string]: {longName, typeName, description, defaultValue}}. An object containing all available bitcoin configuration options. The keys are the option names (e.g. rpcuser) and the values are objects containing typeName etc. Currently there are 147 items in BITCOIN_CONFIG_OPTIONS. If an option is missing, please file an issue or submit a pull request on this project's repository on GitHub.

BitcoinConfig

A TypeScript type derived from BITCOIN_CONFIG_OPTIONS. The type's keys are the option names (e.g. rpcuser) and the values are TypeScript analogs of the typeNames. Effectively,

type BitcoinConfig = {
  testnet: boolean;
  timeout: number;
  rpcuser: string;
  rpcauth: string[];
  ...
}

SectionedConfig

A TypeScript interface that extends BitcoinConfig with an additional property sections. As of Bitcoin Core v0.17.0, configuration files can have INI "sections", for example:

# bitcoin.conf
rpcuser=carnesen
[main]
rpcpassword=abcd1234
[regtest]
rpcpassword=password

This means that when the node is running on the "main" chain rpcpassword is "abcd1234", but when it's running in "regtest" mode, rpcpassword is simply "password". The sections property of a SectionedConfig represents those chain-specific configuration options. Not all options are allowed in all sections. For example, the chain selection options regtest and testnet are only allowed at the top of the file above the sections. Other options such as acceptnonstdtxn are not allowed in the "main" section. The config argument of writeConfigFile described below has type SectionedConfig.

readConfigFile(filePath): sectionedConfig

Reads and parses a bitcoin configuration file from disk

filePath

string. Absolute path of a bitcoin configuration file.

sectionedConfig

SectionedConfig. As described above. The return value represents the full contents of a single bitcoin configuration file.

readConfigFiles(filePath): bitcoinConfig

Reads, parses, and merges a bitcoin configuration file together with all its includeconf files.

filePath

string. Absolute path of a bitcoin configuration file.

bitcoinConfig

BitcoinConfig. Whereas readConfigFile returns the full contents of a single file, readConfigFiles returns the merged content of (potentially) several files. If the configuration file at filePath specifies any includeconfs, those are read and merged into the original. What makes the result a BitcoinConfig not a SectionedConfig is that if there is a configuration section for the currently-active chain, that gets merged into the any-chain values from the top part of the config files above the sections. The logic for casting and merging values is meant to reproduce as closely as possible that of Bitcoin Core. So you're getting as a return value the effective "active" configuration.

writeConfigFile(filePath, sectionedConfig): {changed, serializedConfig, backupFilePath}

Serializes a configuration object and writes it to disk

filePath

string. Absolute path of a bitcoin configuration file.

sectionedConfig

SectionedConfig. A configuration object to serialize and write to disk

changed

boolean. The writeConfigFile function is idempotent in the sense that if an existing file at filePath has contents identical to what it's about to write, it does not re-write the file. Instead it just returns changed as false and leaves the file alone.

serializedConfig

string. The serialized representation of the passed configuration object

backupFilePath

string. When writeConfigFile writes a file to disk, it first move an existing file at that location to ${filePath}.bak. backupFilePath is the absolute path of the backup file.

getChainName(config): chainName

Extracts a "chain name" ('main' | 'test' | 'regtest') from boolean properties regtest and testnet.

config

{
  regtest?: boolean;
  testnet?: boolean;
}

chainName

'main' | 'test' | 'regtest'

setChainName(config, chainName): nextConfig

Returns a new configuration object with the boolean properties regtest and testnet set appropriately based on the provided "chain name" ('main' | 'test' | 'regtest').

getDefaultConfig(chainName): defaultConfig

Returns an object containing the default configuration for the specified chain

chainName

'main' | 'test' | 'regtest'

defaultConfig

DefaultConfig. A literal-specific object type with default values for the specified chain. For example, the expression getDefaultConfig('main').rpcport has value 8332 and a numeric literal type 8332.

parseConfig(serializedConfig): sectionedConfig

serializedConfig

string. A serialized SectionConfig.

sectionedConfig

SectionedConfig. A configuration object parsed from serializedConfig.

serializeConfig(sectionedConfig): serializedConfig

sectionedConfig

SectionedConfig. A configuration object.

serializedConfig

string. An INI-serialized version of sectionedConfig.

updateConfigFile(filePath, delta): returnValue

Updates or creates a bitcoin configuration file

filePath

string. Absolute path of a bitcoin configuration file. Will be created if it does not exist.

delta

NullableSectionedConfig. Basically a SectionedConfig but where every property's type includes null. A delta property value null means "delete this property".

returnValue

Same as writeConfigFile above.

toAbsolute(filePath, datadir?, chainName?): absoluteFilePath

Converts a datadir-relative file path into an absolute one.

filePath

string. An absolute path (e.g. '/home/carnesen/.bitcoin/bitcoin.conf') or a relative one (e.g. 'bitcoin.conf'.

datadir

string (optional). Absolute path of a bitcoin data directory. Default value is platform dependent, e.g. ~/.bitcoin on Linux.

chainName

'main' | 'regtest' | 'test' (optional). If provided, '', '/regtest', or '/testnet3', respectively, is appended to the absolute path. Blocks and other data is written to these subdirectories.

absoluteFilePath

string. An absolute file path string.

More information

This library has over 80 unit tests with >98% coverage. The tests make assertions not only about its runtime behavior but also about its types using dtslint. If you want to see more examples of how it works, that'd be a good place to start. If you encounter any bugs or have any questions or feature requests, please don't hesitate to file an issue or submit a pull request on this project's repository on GitHub.

License

MIT © Chris Arnesen