UNPKG

bitcoin-core-ts

Version:

A modern Bitcoin Core REST and RPC client.

236 lines (235 loc) 11.1 kB
"use strict"; /** * Module dependencies. */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const parser_1 = __importDefault(require("./parser")); const requester_1 = __importDefault(require("./requester")); // @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module 'loda... Remove this comment to see the full error message const lodash_1 = __importDefault(require("lodash")); // @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module 'debu... Remove this comment to see the full error message const debugnyan_1 = __importDefault(require("debugnyan")); const methods_1 = __importDefault(require("./methods")); const request_logger_1 = __importDefault(require("./logging/request-logger")); // @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module 'semv... Remove this comment to see the full error message const semver_1 = __importDefault(require("semver")); /** * List of networks and their default port mapping. */ const networks = { mainnet: 8332, regtest: 18332, signet: 38332, testnet: 18332 }; /** * Promisify helper. */ const promisify = (fn) => (...args) => new Promise((resolve, reject) => { fn(...args, (error, value) => { if (error) { reject(error); return; } resolve(value); }); }); /** * Constructor. */ class Client { constructor({ agentOptions, headers = false, host = 'localhost', logger = (0, debugnyan_1.default)('bitcoin-core'), network = 'mainnet', password, port, ssl = false, timeout = 30000, username, version, wallet } = {}) { if (!lodash_1.default.has(networks, network)) { // @ts-expect-error ts-migrate(2554) FIXME: Expected 0-1 arguments, but got 2. throw new Error(`Invalid network name "${network}"`, { network }); } this.agentOptions = agentOptions; this.auth = (password || username) && { pass: password, user: username }; this.hasNamedParametersSupport = false; this.headers = headers; this.host = host; this.password = password; // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message this.port = port || networks[network]; this.ssl = { enabled: lodash_1.default.get(ssl, 'enabled', ssl), strict: lodash_1.default.get(ssl, 'strict', lodash_1.default.get(ssl, 'enabled', ssl)) }; this.timeout = timeout; this.wallet = wallet; // Version handling. if (version) { // Capture X.Y.Z when X.Y.Z.A is passed to support oddly formatted Bitcoin Core // versions such as 0.15.0.1. const result = /[0-9]+\.[0-9]+\.[0-9]+/.exec(version); if (!result) { // @ts-expect-error ts-migrate(2554) FIXME: Expected 0-1 arguments, but got 2. throw new Error(`Invalid Version "${version}"`, { version }); } [version] = result; this.hasNamedParametersSupport = semver_1.default.satisfies(version, '>=0.14.0'); } this.version = version; this.methods = lodash_1.default.transform(methods_1.default, (result, method, name) => { result[lodash_1.default.toLower(name)] = { features: lodash_1.default.transform(method.features, (result, constraint, name) => { result[name] = { supported: version ? semver_1.default.satisfies(version, constraint) : true }; }, {}), supported: version ? semver_1.default.satisfies(version, method.version) : true }; }, {}); const request = (0, request_logger_1.default)(logger); this.request = request.defaults({ agentOptions: this.agentOptions, baseUrl: `${this.ssl.enabled ? 'https' : 'http'}://${this.host}:${this.port}`, strictSSL: this.ssl.strict, timeout: this.timeout }); this.request.getAsync = promisify(this.request.get); this.request.postAsync = promisify(this.request.post); this.requester = new requester_1.default({ methods: this.methods, version }); this.parser = new parser_1.default({ headers: this.headers }); } /** * Execute `rpc` command. */ command(...args) { return __awaiter(this, void 0, void 0, function* () { let body; let multiwallet; let [input, ...parameters] = args; // eslint-disable-line prefer-const const isBatch = Array.isArray(input); if (isBatch) { multiwallet = lodash_1.default.some(input, (command) => { return lodash_1.default.get(this.methods[command.method], 'features.multiwallet.supported', false) === true; }); body = input.map((method, index) => this.requester.prepare({ method: method.method, parameters: method.parameters, suffix: index })); } else { if (this.hasNamedParametersSupport && parameters.length === 1 && lodash_1.default.isPlainObject(parameters[0])) { parameters = parameters[0]; } multiwallet = lodash_1.default.get(this.methods[input], 'features.multiwallet.supported', false) === true; body = this.requester.prepare({ method: input, parameters }); } return this.parser.rpc(yield this.request.postAsync({ auth: lodash_1.default.pickBy(this.auth, lodash_1.default.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(hash, { extension = 'json' } = {}) { return __awaiter(this, void 0, void 0, function* () { return this.parser.rest(extension, yield this.request.getAsync({ encoding: extension === 'bin' ? null : undefined, url: `/rest/tx/${hash}.${extension}` })); }); } /** * Given a block hash, returns a block, in binary, hex-encoded binary or JSON formats. * With `summary` set to `false`, the JSON response will only contain the transaction * hash instead of the complete transaction details. The option only affects the JSON response. */ getBlockByHash(hash, { summary = false, extension = 'json' } = {}) { return __awaiter(this, void 0, void 0, function* () { const encoding = extension === 'bin' ? null : undefined; const url = `/rest/block${summary ? '/notxdetails/' : '/'}${hash}.${extension}`; return this.parser.rest(extension, yield this.request.getAsync({ encoding, url })); }); } /** * Given a block hash, returns amount of blockheaders in upward direction. */ getBlockHeadersByHash(hash, count, { extension = 'json' } = {}) { return __awaiter(this, void 0, void 0, function* () { const encoding = extension === 'bin' ? null : undefined; const url = `/rest/headers/${count}/${hash}.${extension}`; return this.parser.rest(extension, yield this.request.getAsync({ encoding, url })); }); } /** * Returns various state info regarding block chain processing. * Only supports JSON as output format. */ getBlockchainInformation() { return __awaiter(this, void 0, void 0, function* () { return this.parser.rest('json', yield this.request.getAsync(`/rest/chaininfo.json`)); }); } /** * Query unspent transaction outputs for a given set of outpoints. * See BIP64 for input and output serialisation: * - https://github.com/bitcoin/bips/blob/master/bip-0064.mediawiki */ getUnspentTransactionOutputs(outpoints, { extension = 'json' } = {}) { return __awaiter(this, void 0, void 0, function* () { const encoding = extension === 'bin' ? null : undefined; const sets = lodash_1.default.flatten([outpoints]).map((outpoint) => { return `${outpoint.id}-${outpoint.index}`; }).join('/'); const url = `/rest/getutxos/checkmempool/${sets}.${extension}`; return this.parser.rest(extension, yield this.request.getAsync({ encoding, url })); }); } /** * Returns transactions in the transaction memory pool. * Only supports JSON as output format. */ getMemoryPoolContent() { return __awaiter(this, void 0, void 0, function* () { return this.parser.rest('json', yield this.request.getAsync('/rest/mempool/contents.json')); }); } /** * 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. */ getMemoryPoolInformation() { return __awaiter(this, void 0, void 0, function* () { return this.parser.rest('json', yield this.request.getAsync('/rest/mempool/info.json')); }); } } /** * Add all known RPC methods. */ lodash_1.default.forOwn(methods_1.default, (options, method) => { // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message Client.prototype[method] = lodash_1.default.partial(Client.prototype.command, method.toLowerCase()); }); /** * Export Client class (ESM). */ exports.default = Client; /** * Export Client class (CJS) for compatibility with require('bitcoin-core'). */ // @ts-expect-error ts-migrate(2580) FIXME: Cannot find name 'module'. Do you need to install ... Remove this comment to see the full error message module.exports = Client;