UNPKG

txho

Version:

Get a Bitcoin transaction as JSON for CLI and node

229 lines (228 loc) 8.23 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; exports.__esModule = true; var bsv = require("bsv"); var txo_1 = require("./bundle/txo"); var filterObj_1 = require("./filterObj"); var opCodes_1 = require("./opCodes"); var base64 = require("base-64"); var js_sha256_1 = require("js-sha256"); var misc_1 = require("./misc"); var atobPipe = base64.encode('|'); var re = { probablyBinary: /[\x00-\x08\x0E-\x1f]/, timestamp: /^[1-2][0-9]{9}$/, miliTimestamp: /^[1-2][0-9]{12}$/ }; var defaultTxConfig = { network: bsv.Networks.livenet, maxDataSize: 512, cellAuto: false, cellB64: false, cellStr: false, cellHex: false, cellBuf: false, cellHash: false, cellAll: false, txo: null, only: null, hide: null, pool: null, splitDelimiter: function (cell, payload, n) { return atobPipe === cell.b64 || 'OP_RETURN' === cell.opName || 'OP_FALSE' === cell.opName; } }; function default_1(transaction, config) { var _a, _b; if (config === void 0) { config = defaultTxConfig; } var conf = __assign(__assign({}, defaultTxConfig), config); if (conf.cleanData) { transaction = misc_1.findHexs(transaction) .sort(function (a, b) { return b.length - a.length; }) .shift(); } if (conf.cellAll) { conf.cellAuto = conf.cellB64 = conf.cellStr = conf.cellHex = conf.cellHash = true; } if (conf.txo) { return filterOutput(txo_1.fromTx(transaction, conf.txo), conf); } var txData; try { txData = new bsv.Transaction(transaction); } catch (e) { console.error(e.message); if (64 === transaction.length) console.error('\nThe input looks like a transaction ID and not the raw transaction data. Try using `txid` instead of `rawtx`.\n'); if (e.message.includes('deserialize a transaction')) { console.error('\nIs your input dirty or needs a trim? Try the `cleanData` flag.\n'); } process.exit(1); } if (!txData) return 'tx not valid'; var txObj = txData.toObject(); var tx = { txid: txObj.hash, lockTime: txObj.nLockTime, "in": [], out: [] }; var data = []; (_a = txData.inputs) === null || _a === void 0 ? void 0 : _a.forEach(function (input, inputIndex) { if (!input.script) { return tx["in"].push(input); } var payload = input.script.chunks.map(function (c, chunkIndex) { var _a = transformChuncks(c, conf), row = _a[0], hoistedData = _a[1]; if (hoistedData) { row.uri = txObj.hash + ".in." + inputIndex + "." + chunkIndex; row.display.uri = row.uri; data.push(__assign(__assign({}, hoistedData), { txid: txObj.hash, type: 'in', iScript: inputIndex, iChunk: chunkIndex })); } return row; }); var origin = { txid: input.prevTxId.toString('hex'), iOut: input.outputIndex }; var address = input.script.toAddress(conf.network).toString(); if (address && address.length > 13) { origin.address = address; } tx["in"].push({ seq: input.sequenceNumber, origin: origin, payload: payload.map(function (e) { return e.display || e; }) }); }); (_b = txData.outputs) === null || _b === void 0 ? void 0 : _b.forEach(function (output, outputIndex) { if (!output.script) { return tx.out.push(output); } var payload = output.script.chunks.map(function (c, chunkIndex) { var _a = transformChuncks(c, conf), row = _a[0], hoistedData = _a[1]; if (hoistedData) { row.uri = txObj.hash + ".out." + outputIndex + "." + chunkIndex; row.display.uri = row.uri; data.push(__assign(__assign({}, hoistedData), { txid: txObj.hash, type: 'out', iScript: outputIndex, iChunk: chunkIndex })); } return row; }); var result = { value: output.satoshis }; var address = output.script.toAddress(conf.network).toString(); if (address && address.length > 13) { result.address = address; } result.payload = payload.map(function (e) { return e.display || e; }); var split = [[]]; for (var i = 0; i < payload.length; i++) { if (conf.splitDelimiter(payload[i], payload, i)) { if (0 === split[split.length - 1].length) { continue; } split.push([]); continue; } split[split.length - 1].push(payload[i].display || payload[i]); } result.split = split; tx.out.push(result); }); return filterOutput({ tx: tx, data: data, datamap: datamap(data) }, conf); } exports["default"] = default_1; function transformChuncks(c, conf) { var cell = {}; if (c.buf) { if (0 < conf.maxDataSize && conf.maxDataSize < c.buf.byteLength) { cell = { size: c.buf.byteLength, sha256: js_sha256_1.sha256.hex(c.buf) }; return [ __assign(__assign({}, cell), { display: cell }), __assign(__assign({}, cell), { b64: c.buf.toString('base64') }), ]; } cell = { b64: c.buf.toString('base64'), str: c.buf.toString('utf8'), hex: c.buf.toString('hex'), buf: c.buf, display: {} }; if (conf.cellStr) cell.display.str = cell.str; if (conf.cellHex) cell.display.hex = cell.hex; if (conf.cellB64) cell.display.b64 = cell.b64; if (conf.cellBuf) cell.display.buf = cell.buf; if (conf.cellHash) cell.sha256 = js_sha256_1.sha256.hex(c.buf); if (conf.cellAuto) { if (!re.probablyBinary.test(cell.str)) { if (re.timestamp.test(cell.str)) { cell.utc = cell.display.utc = new Date(parseInt(cell.str) * 1000).toISOString(); } else if (re.miliTimestamp.test(cell.str)) { cell.utc = cell.display.utc = new Date(parseInt(cell.str)).toISOString(); } cell.display.str = cell.str; } if ([64, 256, 512].includes(cell.hex.length)) cell.display.hex = cell.hex; if (!cell.display.str && !cell.display.hex) cell.display.b64 = cell.b64; } if (!Object.keys(cell.display).length) { cell.display.b64 = cell.b64; } } else if (typeof c.opcodenum !== 'undefined') { cell.opName = opCodes_1.opName(c.opcodenum); cell.op = c.opcodenum; } else { cell.buf = c; } return [cell]; } function filterOutput(obj, conf) { var _a, _b; var filterConfig = null; if ((_a = conf.only) === null || _a === void 0 ? void 0 : _a.trim().length) { filterConfig = {}; conf.only .trim() .split(',') .forEach(function (e) { return (filterConfig[e.trim()] = 1); }); obj = filterObj_1["default"](obj, filterConfig); } if ((_b = conf.hide) === null || _b === void 0 ? void 0 : _b.trim().length) { filterConfig = {}; conf.hide .trim() .split(',') .forEach(function (e) { return (filterConfig[e.trim()] = 0); }); obj = filterObj_1["default"](obj, filterConfig); } return obj; } function datamap(data) { var datamap = {}; for (var nn in data) { var n = +nn; datamap[data[n].txid + "." + data[n].type + "." + data[n].iScript + "." + data[n].iChunk] = n; } return datamap; }