nerve-sdk-js
Version:
nerve nerve-js nerve-sdk nerve-js-sdk
491 lines (406 loc) • 16.2 kB
JavaScript
"use strict";
var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = {
enumerable: true,
get: function get() {
return m[k];
}
};
}
Object.defineProperty(o, k2, desc);
} : function (o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
});
var __setModuleDefault = void 0 && (void 0).__setModuleDefault || (Object.create ? function (o, v) {
Object.defineProperty(o, "default", {
enumerable: true,
value: v
});
} : function (o, v) {
o["default"] = v;
});
var __importStar = void 0 && (void 0).__importStar || function () {
var _ownKeys = function ownKeys(o) {
_ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) {
if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
}
return ar;
};
return _ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = _ownKeys(mod), i = 0; i < k.length; i++) {
if (k[i] !== "default") __createBinding(result, mod, k[i]);
}
__setModuleDefault(result, mod);
return result;
};
}();
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getContractTxdata = getContractTxdata;
exports.getCurrentInputsdata = getCurrentInputsdata;
exports.getCurrentTxdata = getCurrentTxdata;
exports.getPreTxdata = getPreTxdata;
exports.getPrePreTxdata = getPrePreTxdata;
exports.getPrePreOutputsData = getPrePreOutputsData;
exports.getPreOutputsData = getPreOutputsData;
exports.getLengthHex = getLengthHex;
exports.getSize = getSize;
var tbc = __importStar(require("tbc-lib-js"));
var partial_sha256 = require('tbc-lib-js/lib/util/partial-sha256');
var version = 10;
var vliolength = '10'; // Version + nLockTime + inputCount + outputCount (16 bytes)
var amountlength = '08'; // Length of the amount field (8 bytes)
var hashlength = '20'; // Length of the hash field (32 bytes)
/**
* Retrieves the transaction data needed for contract operations.
* @param tx - The transaction object.
* @returns The transaction data as a hex string.
*/
function getContractTxdata(tx, vout) {
var writer = new tbc.encoding.BufferWriter();
writer.write(Buffer.from(vliolength, 'hex'));
writer.writeUInt32LE(version);
writer.writeUInt32LE(tx.nLockTime);
writer.writeInt32LE(tx.inputs.length);
writer.writeInt32LE(tx.outputs.length);
var inputWriter = new tbc.encoding.BufferWriter();
var inputWriter2 = new tbc.encoding.BufferWriter();
for (var input of tx.inputs) {
inputWriter.writeReverse(input.prevTxId);
inputWriter.writeUInt32LE(input.outputIndex);
inputWriter.writeUInt32LE(input.sequenceNumber);
inputWriter2.write(tbc.crypto.Hash.sha256(input.script.toBuffer()));
}
writer.write(Buffer.from(hashlength, 'hex'));
writer.write(tbc.crypto.Hash.sha256(inputWriter.toBuffer()));
writer.write(Buffer.from(hashlength, 'hex'));
writer.write(tbc.crypto.Hash.sha256(inputWriter2.toBuffer()));
var {
outputs1,
outputs1length,
outputs2,
outputs2length
} = getPrePreOutputsData(tx, vout);
writer.write(Buffer.from(outputs1length, 'hex'));
writer.write(Buffer.from(outputs1, 'hex'));
writer.write(Buffer.from(amountlength, 'hex'));
writer.writeUInt64LEBN(tx.outputs[vout].satoshisBN);
writer.write(Buffer.from(hashlength, 'hex'));
writer.write(tbc.crypto.Hash.sha256(tx.outputs[vout].script.toBuffer()));
writer.write(Buffer.from(outputs2length, 'hex'));
writer.write(Buffer.from(outputs2, 'hex'));
var contracttxdata = writer.toBuffer().toString('hex');
return "".concat(contracttxdata);
}
/**
* Retrieves the inputs data from the current transaction.
* @param tx - The transaction object.
* @returns The inputs data as a hex string.
*/
function getCurrentInputsdata(tx) {
var writer = new tbc.encoding.BufferWriter();
var inputWriter = new tbc.encoding.BufferWriter();
for (var input of tx.inputs) {
inputWriter.writeReverse(input.prevTxId);
inputWriter.writeUInt32LE(input.outputIndex);
inputWriter.writeUInt32LE(input.sequenceNumber);
}
writer.write(getLengthHex(inputWriter.toBuffer().length));
writer.write(inputWriter.toBuffer());
var currentinputsdata = writer.toBuffer().toString('hex');
return "".concat(currentinputsdata);
}
/**
* Retrieves the current transaction data needed for unlocking scripts.
* @param tx - The transaction object.
* @param inputIndex - The index of the input being unlocked.
* @returns The transaction data as a hex string.
*/
function getCurrentTxdata(tx, inputIndex) {
var endTag = '51';
var writer = new tbc.encoding.BufferWriter();
for (var i = 0; i < tx.outputs.length; i++) {
var lockingscript = tx.outputs[i].script.toBuffer();
if (lockingscript.length == 1564) {
// For scripts longer than 1500 bytes, calculate partial hash
var size = getSize(lockingscript.length); // Size in little-endian
var partialhash = partial_sha256.calculate_partial_hash(lockingscript.subarray(0, 1536));
var suffixdata = lockingscript.subarray(1536);
writer.write(Buffer.from(amountlength, 'hex'));
writer.writeUInt64LEBN(tx.outputs[i].satoshisBN);
writer.write(getLengthHex(suffixdata.length)); // Suffix data
writer.write(suffixdata);
writer.write(Buffer.from(hashlength, 'hex')); // Partial hash
writer.write(Buffer.from(partialhash, 'hex'));
writer.write(getLengthHex(size.length));
writer.write(size);
writer.write(Buffer.from(amountlength, 'hex'));
writer.writeUInt64LEBN(tx.outputs[i + 1].satoshisBN);
writer.write(getLengthHex(tx.outputs[i + 1].script.toBuffer().length));
writer.write(tx.outputs[i + 1].script.toBuffer());
i++;
} else {
// For shorter scripts, include the entire locking script
var _size = getSize(lockingscript.length);
var _partialhash = '00';
var _suffixdata = lockingscript;
writer.write(Buffer.from(amountlength, 'hex'));
writer.writeUInt64LEBN(tx.outputs[i].satoshisBN);
writer.write(getLengthHex(_suffixdata.length)); // Entire locking script
writer.write(_suffixdata);
writer.write(Buffer.from(_partialhash, 'hex')); // No partial hash
writer.write(getLengthHex(_size.length));
writer.write(_size);
}
writer.write(Buffer.from('52', 'hex'));
}
var currenttxdata = writer.toBuffer().toString('hex');
var inputIndexMap = {
0: '00',
1: '51',
2: '52',
3: '53',
4: '54',
5: '55'
};
return "".concat(endTag).concat(currenttxdata).concat(inputIndexMap[inputIndex]);
}
/**
* Retrieves the previous transaction data needed for unlocking scripts.
* @param tx - The previous transaction object.
* @param vout - The output index in the previous transaction.
* @returns The transaction data as a hex string.
*/
function getPreTxdata(tx, vout) {
var writer = new tbc.encoding.BufferWriter();
writer.write(Buffer.from(vliolength, 'hex'));
writer.writeUInt32LE(version);
writer.writeUInt32LE(tx.nLockTime);
writer.writeInt32LE(tx.inputs.length);
writer.writeInt32LE(tx.outputs.length);
var inputWriter = new tbc.encoding.BufferWriter();
var inputWriter2 = new tbc.encoding.BufferWriter();
for (var input of tx.inputs) {
inputWriter.writeReverse(input.prevTxId);
inputWriter.writeUInt32LE(input.outputIndex);
inputWriter.writeUInt32LE(input.sequenceNumber);
inputWriter2.write(tbc.crypto.Hash.sha256(input.script.toBuffer()));
}
writer.write(getLengthHex(inputWriter.toBuffer().length));
writer.write(inputWriter.toBuffer());
writer.write(Buffer.from(hashlength, 'hex'));
writer.write(tbc.crypto.Hash.sha256(inputWriter2.toBuffer()));
var {
outputs1,
outputs1length,
outputs2,
outputs2length
} = getPreOutputsData(tx, vout);
writer.write(Buffer.from(outputs1length, 'hex'));
writer.write(Buffer.from(outputs1, 'hex'));
var lockingscript = tx.outputs[vout].script.toBuffer();
var size = getSize(lockingscript.length); // Size in little-endian
var partialhash = partial_sha256.calculate_partial_hash(lockingscript.subarray(0, 1536));
var suffixdata = lockingscript.subarray(1536);
writer.write(Buffer.from(amountlength, 'hex'));
writer.writeUInt64LEBN(tx.outputs[vout].satoshisBN);
writer.write(getLengthHex(suffixdata.length)); // Suffix data
writer.write(suffixdata);
writer.write(Buffer.from(hashlength, 'hex')); // Partial hash
writer.write(Buffer.from(partialhash, 'hex'));
writer.write(getLengthHex(size.length));
writer.write(size);
writer.write(Buffer.from(amountlength, 'hex'));
writer.writeUInt64LEBN(tx.outputs[vout + 1].satoshisBN);
writer.write(getLengthHex(tx.outputs[vout + 1].script.toBuffer().length));
writer.write(tx.outputs[vout + 1].script.toBuffer());
writer.write(Buffer.from(outputs2length, 'hex'));
writer.write(Buffer.from(outputs2, 'hex'));
var pretxdata = writer.toBuffer().toString('hex');
return "".concat(pretxdata);
}
/**
* Retrieves the previous transaction data from the grandparent transaction.
* @param tx - The grandparent transaction object.
* @param vout - The output index in the grandparent transaction.
* @returns The transaction data as a hex string with a suffix '52'.
*/
function getPrePreTxdata(tx, vout) {
var writer = new tbc.encoding.BufferWriter();
writer.write(Buffer.from(vliolength, 'hex'));
writer.writeUInt32LE(version);
writer.writeUInt32LE(tx.nLockTime);
writer.writeInt32LE(tx.inputs.length);
writer.writeInt32LE(tx.outputs.length);
var inputWriter = new tbc.encoding.BufferWriter();
var inputWriter2 = new tbc.encoding.BufferWriter();
for (var input of tx.inputs) {
inputWriter.writeReverse(input.prevTxId);
inputWriter.writeUInt32LE(input.outputIndex);
inputWriter.writeUInt32LE(input.sequenceNumber);
inputWriter2.write(tbc.crypto.Hash.sha256(input.script.toBuffer()));
}
writer.write(Buffer.from(hashlength, 'hex'));
writer.write(tbc.crypto.Hash.sha256(inputWriter.toBuffer()));
writer.write(Buffer.from(hashlength, 'hex'));
writer.write(tbc.crypto.Hash.sha256(inputWriter2.toBuffer()));
var {
outputs1,
outputs1length,
outputs2,
outputs2length
} = getPrePreOutputsData(tx, vout);
writer.write(Buffer.from(outputs1length, 'hex'));
writer.write(Buffer.from(outputs1, 'hex'));
var lockingscript = tx.outputs[vout].script.toBuffer();
if (lockingscript.length == 1564) {
var size = getSize(lockingscript.length); // Size in little-endian
var partialhash = partial_sha256.calculate_partial_hash(lockingscript.subarray(0, 1536));
var suffixdata = lockingscript.subarray(1536);
writer.write(Buffer.from(amountlength, 'hex'));
writer.writeUInt64LEBN(tx.outputs[vout].satoshisBN);
writer.write(getLengthHex(suffixdata.length)); // Suffix data
writer.write(suffixdata);
writer.write(Buffer.from(hashlength, 'hex')); // Partial hash
writer.write(Buffer.from(partialhash, 'hex'));
writer.write(getLengthHex(size.length));
writer.write(size);
} else {
var _size2 = getSize(lockingscript.length); // Size in little-endian
var _partialhash2 = '00';
var _suffixdata2 = lockingscript;
writer.write(Buffer.from(amountlength, 'hex'));
writer.writeUInt64LEBN(tx.outputs[vout].satoshisBN);
writer.write(getLengthHex(_suffixdata2.length)); // Entire locking script
writer.write(_suffixdata2);
writer.write(Buffer.from(_partialhash2, 'hex')); // No partial hash
writer.write(getLengthHex(_size2.length));
writer.write(_size2);
}
writer.write(Buffer.from(outputs2length, 'hex'));
writer.write(Buffer.from(outputs2, 'hex'));
var prepretxdata = writer.toBuffer().toString('hex');
return "".concat(prepretxdata, "52");
}
/**
* Helper function to get outputs data before the specified output index for the grandparent transaction.
* @param tx - The transaction object.
* @param vout - The output index.
* @returns An object containing outputs1, outputs1length, outputs2, and outputs2length.
*/
function getPrePreOutputsData(tx, vout) {
var outputs1 = ''; // Outputs before the specified index
var outputs1length = '';
var outputs2 = ''; // Outputs after the specified index
var outputs2length = '';
if (vout === 0) {
outputs1 = '00';
outputs1length = '';
} else {
var outputWriter1 = new tbc.encoding.BufferWriter();
for (var i = 0; i < vout; i++) {
outputWriter1.writeUInt64LEBN(tx.outputs[i].satoshisBN);
outputWriter1.write(tbc.crypto.Hash.sha256(tx.outputs[i].script.toBuffer()));
}
outputs1 = outputWriter1.toBuffer().toString('hex');
outputs1length = getLengthHex(outputs1.length / 2).toString('hex');
}
var outputWriter2 = new tbc.encoding.BufferWriter();
for (var _i = vout + 1; _i < tx.outputs.length; _i++) {
outputWriter2.writeUInt64LEBN(tx.outputs[_i].satoshisBN);
outputWriter2.write(tbc.crypto.Hash.sha256(tx.outputs[_i].script.toBuffer()));
}
outputs2 = outputWriter2.toBuffer().toString('hex');
if (outputs2 === '') {
outputs2 = '00';
outputs2length = '';
} else {
outputs2length = getLengthHex(outputs2.length / 2).toString('hex');
}
return {
outputs1,
outputs1length,
outputs2,
outputs2length
};
}
/**
* Helper function to get outputs data before the specified output index for the parent transaction.
* @param tx - The transaction object.
* @param vout - The output index.
* @returns An object containing outputs1, outputs1length, outputs2, and outputs2length.
*/
function getPreOutputsData(tx, vout) {
var outputs1 = ''; // Outputs before the specified index
var outputs1length = '';
var outputs2 = ''; // Outputs after the specified index
var outputs2length = '';
if (vout === 0) {
outputs1 = '00';
outputs1length = '';
} else {
var outputWriter1 = new tbc.encoding.BufferWriter();
for (var i = 0; i < vout; i++) {
outputWriter1.writeUInt64LEBN(tx.outputs[i].satoshisBN);
outputWriter1.write(tbc.crypto.Hash.sha256(tx.outputs[i].script.toBuffer()));
}
outputs1 = outputWriter1.toBuffer().toString('hex');
outputs1length = getLengthHex(outputs1.length / 2).toString('hex');
}
var outputWriter2 = new tbc.encoding.BufferWriter();
for (var _i2 = vout + 2; _i2 < tx.outputs.length; _i2++) {
// For parent transaction, outputs2 starts from vout + 2
outputWriter2.writeUInt64LEBN(tx.outputs[_i2].satoshisBN);
outputWriter2.write(tbc.crypto.Hash.sha256(tx.outputs[_i2].script.toBuffer()));
}
outputs2 = outputWriter2.toBuffer().toString('hex');
if (outputs2 === '') {
outputs2 = '00';
outputs2length = '';
} else {
outputs2length = getLengthHex(outputs2.length / 2).toString('hex');
}
return {
outputs1,
outputs1length,
outputs2,
outputs2length
};
}
/**
* Calculates the length of data and adds OP_PUSHDATA1 or OP_PUSHDATA2 if necessary.
* @param length - The length of the data.
* @returns A buffer representing the length with appropriate push opcode.
*/
function getLengthHex(length) {
if (length < 76) {
return Buffer.from(length.toString(16).padStart(2, '0'), 'hex');
} else if (length > 75 && length < 256) {
return Buffer.concat([Buffer.from('4c', 'hex'), Buffer.from(length.toString(16), 'hex')]);
} else {
return Buffer.concat([Buffer.from('4d', 'hex'), Buffer.from(length.toString(16).padStart(4, '0'), 'hex').reverse()]);
}
}
/**
* Converts the size of data to a little-endian buffer.
* @param length - The length of the data.
* @returns A buffer representing the size in little-endian format.
*/
function getSize(length) {
if (length < 256) {
return Buffer.from(length.toString(16).padStart(2, '0'), 'hex');
} else {
return Buffer.from(length.toString(16).padStart(4, '0'), 'hex').reverse();
}
}