You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

58 lines
1.4 KiB

const bs58check = require('bs58check');
const { encode: numberToCompactSizeUInt } = require('varuint-bitcoin');
const { OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG } = require('bitcoin-ops');
const addressDecode = address => bs58check.decode(address).slice(1);
const checkUInt53 = number => {
if (number < 0 || !Number.isSafeInteger(number)) {
throw new RangeError('value out of range');
}
};
const numberToUInt64 = number => {
checkUInt53(number);
const buffer = Buffer.alloc(8);
buffer.writeUInt32LE(number >>> 0);
buffer.writeUInt32LE((number / 0x100000000) | 0, 4);
return buffer;
};
const buildOutputScript = outputs => {
if (!Array.isArray(outputs)) {
throw new TypeError(`Expected 'outputs' to be of type 'array', got: '${outputs}'.`);
}
if (outputs.length === 0) {
throw new TypeError('\'outputs\' cannot be an empty array.');
}
let outputScript = [...numberToCompactSizeUInt(outputs.length)];
for (const [address, value] of outputs) {
const pubKeyHash = addressDecode(address);
const scriptPubKey = [
OP_DUP,
OP_HASH160,
pubKeyHash.length,
...pubKeyHash,
OP_EQUALVERIFY,
OP_CHECKSIG
];
outputScript = [
...outputScript,
...numberToUInt64(value),
...numberToCompactSizeUInt(scriptPubKey.length),
...scriptPubKey
];
}
return Buffer.from(outputScript).toString('hex');
};
module.exports = buildOutputScript;