txho
Version:
Get a Bitcoin transaction as JSON for CLI and node
229 lines (228 loc) • 8.23 kB
JavaScript
;
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;
}