UNPKG

@ledgerhq/hw-app-btc

Version:
143 lines 4.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.splitTransaction = void 0; const logs_1 = require("@ledgerhq/logs"); const varint_1 = require("./varint"); const debug_1 = require("./debug"); function splitTransaction(transactionHex, isSegwitSupported = false, hasExtraData = false, additionals = []) { const inputs = []; const outputs = []; let witness = false; let offset = 0; const timestamp = Buffer.alloc(0); let nExpiryHeight = Buffer.alloc(0); let nVersionGroupId = Buffer.alloc(0); let extraData = Buffer.alloc(0); let witnessScript, locktime; const isDecred = additionals.includes("decred"); const isZencash = additionals.includes("zencash"); const isZcash = additionals.includes("zcash"); const transaction = Buffer.from(transactionHex, "hex"); const version = transaction.slice(offset, offset + 4); const overwinter = version.equals(Buffer.from([0x03, 0x00, 0x00, 0x80])) || version.equals(Buffer.from([0x04, 0x00, 0x00, 0x80])) || version.equals(Buffer.from([0x05, 0x00, 0x00, 0x80])); const isZcashv5 = isZcash && version.equals(Buffer.from([0x05, 0x00, 0x00, 0x80])); offset += 4; if (isSegwitSupported && transaction[offset] === 0 && transaction[offset + 1] !== 0 && !isZencash) { offset += 2; witness = true; } if (overwinter) { nVersionGroupId = transaction.slice(offset, 4 + offset); offset += 4; } if (isZcashv5) { locktime = transaction.slice(offset + 4, offset + 8); nExpiryHeight = transaction.slice(offset + 8, offset + 12); offset += 12; } let varint = (0, varint_1.getVarint)(transaction, offset); const numberInputs = varint[0]; offset += varint[1]; for (let i = 0; i < numberInputs; i++) { const prevout = transaction.slice(offset, offset + 36); offset += 36; let script = Buffer.alloc(0); let tree = Buffer.alloc(0); //No script for decred, it has a witness if (!isDecred) { varint = (0, varint_1.getVarint)(transaction, offset); offset += varint[1]; script = transaction.slice(offset, offset + varint[0]); offset += varint[0]; } else { //Tree field tree = transaction.slice(offset, offset + 1); offset += 1; } const sequence = transaction.slice(offset, offset + 4); offset += 4; inputs.push({ prevout, script, sequence, tree, }); } varint = (0, varint_1.getVarint)(transaction, offset); const numberOutputs = varint[0]; offset += varint[1]; for (let i = 0; i < numberOutputs; i++) { const amount = transaction.slice(offset, offset + 8); offset += 8; if (isDecred) { //Script version offset += 2; } varint = (0, varint_1.getVarint)(transaction, offset); offset += varint[1]; const script = transaction.slice(offset, offset + varint[0]); offset += varint[0]; outputs.push({ amount, script, }); } if (witness) { witnessScript = transaction.slice(offset, -4); locktime = transaction.slice(transaction.length - 4); } else if (!isZcashv5) { locktime = transaction.slice(offset, offset + 4); } offset += 4; if ((overwinter || isDecred) && !isZcashv5) { nExpiryHeight = transaction.slice(offset, offset + 4); offset += 4; } if (hasExtraData) { extraData = transaction.slice(offset); } //Get witnesses for Decred if (isDecred) { varint = (0, varint_1.getVarint)(transaction, offset); offset += varint[1]; if (varint[0] !== numberInputs) { throw new Error("splitTransaction: incoherent number of witnesses"); } for (let i = 0; i < numberInputs; i++) { //amount offset += 8; //block height offset += 4; //block index offset += 4; //Script size varint = (0, varint_1.getVarint)(transaction, offset); offset += varint[1]; const script = transaction.slice(offset, offset + varint[0]); offset += varint[0]; inputs[i].script = script; } } const t = { version, inputs, outputs, locktime, witness: witnessScript, timestamp, nVersionGroupId, nExpiryHeight, extraData, }; (0, logs_1.log)("btc", `splitTransaction ${transactionHex}:\n${(0, debug_1.formatTransactionDebug)(t)}`); return t; } exports.splitTransaction = splitTransaction; //# sourceMappingURL=splitTransaction.js.map