@ledgerhq/hw-app-btc
Advanced tools
Comparing version 2.1.0 to 2.1.2
@@ -1,3 +0,3 @@ | ||
// flow-typed signature: 559e6d9e212eae61339873c83e1b86ad | ||
// flow-typed version: <<STUB>>/@ledgerhq/hw-transport_v^2.0.5/flow_v0.63.1 | ||
// flow-typed signature: 825a19e4b893d9378f2444aa5a0b5785 | ||
// flow-typed version: <<STUB>>/@ledgerhq/hw-transport_v^2.1.0/flow_v0.63.1 | ||
@@ -25,2 +25,10 @@ /** | ||
*/ | ||
declare module '@ledgerhq/hw-transport/flow-typed/npm/events_vx.x.x' { | ||
declare module.exports: any; | ||
} | ||
declare module '@ledgerhq/hw-transport/flow-typed/npm/flow-typed_vx.x.x' { | ||
declare module.exports: any; | ||
} | ||
declare module '@ledgerhq/hw-transport/src/Transport' { | ||
@@ -31,4 +39,10 @@ declare module.exports: any; | ||
// Filename aliases | ||
declare module '@ledgerhq/hw-transport/flow-typed/npm/events_vx.x.x.js' { | ||
declare module.exports: $Exports<'@ledgerhq/hw-transport/flow-typed/npm/events_vx.x.x'>; | ||
} | ||
declare module '@ledgerhq/hw-transport/flow-typed/npm/flow-typed_vx.x.x.js' { | ||
declare module.exports: $Exports<'@ledgerhq/hw-transport/flow-typed/npm/flow-typed_vx.x.x'>; | ||
} | ||
declare module '@ledgerhq/hw-transport/src/Transport.js' { | ||
declare module.exports: $Exports<'@ledgerhq/hw-transport/src/Transport'>; | ||
} |
1114
lib/Btc.js
@@ -7,6 +7,20 @@ "use strict"; | ||
var _promise = require("babel-runtime/core-js/promise"); | ||
var _promise2 = _interopRequireDefault(_promise); | ||
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); | ||
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); | ||
var _createClass2 = require("babel-runtime/helpers/createClass"); | ||
var _createClass3 = _interopRequireDefault(_createClass2); | ||
var _utils = require("./utils"); | ||
const MAX_SCRIPT_BLOCK = 50; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var MAX_SCRIPT_BLOCK = 50; | ||
// TODO future refactoring | ||
@@ -17,5 +31,5 @@ // - drop utils.js & refactoring with async/await style | ||
const DEFAULT_LOCKTIME = 0; | ||
const DEFAULT_SEQUENCE = 0xffffffff; | ||
const SIGHASH_ALL = 1; | ||
var DEFAULT_LOCKTIME = 0; | ||
var DEFAULT_SEQUENCE = 0xffffffff; | ||
var SIGHASH_ALL = 1; | ||
@@ -29,5 +43,7 @@ /** | ||
*/ | ||
class Btc { | ||
constructor(transport) { | ||
var Btc = function () { | ||
function Btc(transport) { | ||
(0, _classCallCheck3.default)(this, Btc); | ||
this.transport = transport; | ||
@@ -42,545 +58,667 @@ transport.setScrambleKey("BTC"); | ||
*/ | ||
getWalletPublicKey(path) { | ||
const paths = (0, _utils.splitPath)(path); | ||
const buffer = Buffer.alloc(1 + paths.length * 4); | ||
buffer[0] = paths.length; | ||
paths.forEach((element, index) => { | ||
buffer.writeUInt32BE(element, 1 + 4 * index); | ||
}); | ||
return this.transport.send(0xe0, 0x40, 0x00, 0x00, buffer).then(response => { | ||
const publicKeyLength = response[0]; | ||
const addressLength = response[1 + publicKeyLength]; | ||
const publicKey = response.slice(1, 1 + publicKeyLength).toString("hex"); | ||
const bitcoinAddress = response.slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength).toString("ascii"); | ||
const chainCode = response.slice(1 + publicKeyLength + 1 + addressLength, 1 + publicKeyLength + 1 + addressLength + 32).toString("hex"); | ||
return { publicKey, bitcoinAddress, chainCode }; | ||
}); | ||
} | ||
getTrustedInputRaw(transactionData, indexLookup) { | ||
let data; | ||
let firstRound = false; | ||
if (typeof indexLookup === "number") { | ||
firstRound = true; | ||
const prefix = Buffer.alloc(4); | ||
prefix.writeUInt32BE(indexLookup, 0); | ||
data = Buffer.concat([prefix, transactionData], transactionData.length + 4); | ||
} else { | ||
data = transactionData; | ||
} | ||
return this.transport.send(0xe0, 0x42, firstRound ? 0x00 : 0x80, 0x00, data).then(trustedInput => trustedInput.slice(0, trustedInput.length - 2).toString("hex")); | ||
} | ||
getTrustedInput(indexLookup, transaction) { | ||
const { inputs, outputs, locktime } = transaction; | ||
if (!outputs || !locktime) { | ||
throw new Error("getTrustedInput: locktime & outputs is expected"); | ||
(0, _createClass3.default)(Btc, [{ | ||
key: "getWalletPublicKey", | ||
value: function getWalletPublicKey(path) { | ||
var paths = (0, _utils.splitPath)(path); | ||
var buffer = Buffer.alloc(1 + paths.length * 4); | ||
buffer[0] = paths.length; | ||
paths.forEach(function (element, index) { | ||
buffer.writeUInt32BE(element, 1 + 4 * index); | ||
}); | ||
return this.transport.send(0xe0, 0x40, 0x00, 0x00, buffer).then(function (response) { | ||
var publicKeyLength = response[0]; | ||
var addressLength = response[1 + publicKeyLength]; | ||
var publicKey = response.slice(1, 1 + publicKeyLength).toString("hex"); | ||
var bitcoinAddress = response.slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength).toString("ascii"); | ||
var chainCode = response.slice(1 + publicKeyLength + 1 + addressLength, 1 + publicKeyLength + 1 + addressLength + 32).toString("hex"); | ||
return { publicKey: publicKey, bitcoinAddress: bitcoinAddress, chainCode: chainCode }; | ||
}); | ||
} | ||
}, { | ||
key: "getTrustedInputRaw", | ||
value: function getTrustedInputRaw(transactionData, indexLookup) { | ||
var data = void 0; | ||
var firstRound = false; | ||
if (typeof indexLookup === "number") { | ||
firstRound = true; | ||
var prefix = Buffer.alloc(4); | ||
prefix.writeUInt32BE(indexLookup, 0); | ||
data = Buffer.concat([prefix, transactionData], transactionData.length + 4); | ||
} else { | ||
data = transactionData; | ||
} | ||
return this.transport.send(0xe0, 0x42, firstRound ? 0x00 : 0x80, 0x00, data).then(function (trustedInput) { | ||
return trustedInput.slice(0, trustedInput.length - 2).toString("hex"); | ||
}); | ||
} | ||
}, { | ||
key: "getTrustedInput", | ||
value: function getTrustedInput(indexLookup, transaction) { | ||
var _this = this; | ||
const processScriptBlocks = (script, sequence) => { | ||
const scriptBlocks = []; | ||
let offset = 0; | ||
while (offset !== script.length) { | ||
let blockSize = script.length - offset > MAX_SCRIPT_BLOCK ? MAX_SCRIPT_BLOCK : script.length - offset; | ||
if (offset + blockSize !== script.length) { | ||
scriptBlocks.push(script.slice(offset, offset + blockSize)); | ||
} else { | ||
scriptBlocks.push(Buffer.concat([script.slice(offset, offset + blockSize), sequence])); | ||
} | ||
offset += blockSize; | ||
var inputs = transaction.inputs, | ||
outputs = transaction.outputs, | ||
locktime = transaction.locktime; | ||
if (!outputs || !locktime) { | ||
throw new Error("getTrustedInput: locktime & outputs is expected"); | ||
} | ||
return (0, _utils.eachSeries)(scriptBlocks, scriptBlock => this.getTrustedInputRaw(scriptBlock)); | ||
}; | ||
const processInputs = () => { | ||
return (0, _utils.eachSeries)(inputs, input => { | ||
const data = Buffer.concat([input.prevout, this.createVarint(input.script.length)]); | ||
return this.getTrustedInputRaw(data).then(() => | ||
// iteration (eachSeries) ended | ||
// TODO notify progress | ||
// deferred.notify("input"); | ||
processScriptBlocks(input.script, input.sequence)); | ||
}).then(() => { | ||
const data = this.createVarint(outputs.length); | ||
return this.getTrustedInputRaw(data); | ||
}); | ||
}; | ||
var processScriptBlocks = function processScriptBlocks(script, sequence) { | ||
var scriptBlocks = []; | ||
var offset = 0; | ||
while (offset !== script.length) { | ||
var blockSize = script.length - offset > MAX_SCRIPT_BLOCK ? MAX_SCRIPT_BLOCK : script.length - offset; | ||
if (offset + blockSize !== script.length) { | ||
scriptBlocks.push(script.slice(offset, offset + blockSize)); | ||
} else { | ||
scriptBlocks.push(Buffer.concat([script.slice(offset, offset + blockSize), sequence])); | ||
} | ||
offset += blockSize; | ||
} | ||
return (0, _utils.eachSeries)(scriptBlocks, function (scriptBlock) { | ||
return _this.getTrustedInputRaw(scriptBlock); | ||
}); | ||
}; | ||
const processOutputs = () => (0, _utils.eachSeries)(outputs, output => { | ||
let data = output.amount; | ||
data = Buffer.concat([data, this.createVarint(output.script.length), output.script]); | ||
return this.getTrustedInputRaw(data).then(() => { | ||
// iteration (eachSeries) ended | ||
// TODO notify progress | ||
// deferred.notify("output"); | ||
}); | ||
}).then(() => this.getTrustedInputRaw(locktime)); | ||
var processInputs = function processInputs() { | ||
return (0, _utils.eachSeries)(inputs, function (input) { | ||
var data = Buffer.concat([input.prevout, _this.createVarint(input.script.length)]); | ||
return _this.getTrustedInputRaw(data).then(function () { | ||
return ( | ||
// iteration (eachSeries) ended | ||
// TODO notify progress | ||
// deferred.notify("input"); | ||
processScriptBlocks(input.script, input.sequence) | ||
); | ||
}); | ||
}).then(function () { | ||
var data = _this.createVarint(outputs.length); | ||
return _this.getTrustedInputRaw(data); | ||
}); | ||
}; | ||
const data = Buffer.concat([transaction.version, this.createVarint(inputs.length)]); | ||
return this.getTrustedInputRaw(data, indexLookup).then(processInputs).then(processOutputs); | ||
} | ||
var processOutputs = function processOutputs() { | ||
return (0, _utils.eachSeries)(outputs, function (output) { | ||
var data = output.amount; | ||
data = Buffer.concat([data, _this.createVarint(output.script.length), output.script]); | ||
return _this.getTrustedInputRaw(data).then(function () { | ||
// iteration (eachSeries) ended | ||
// TODO notify progress | ||
// deferred.notify("output"); | ||
}); | ||
}).then(function () { | ||
return _this.getTrustedInputRaw(locktime); | ||
}); | ||
}; | ||
getVarint(data, offset) { | ||
if (data[offset] < 0xfd) { | ||
return [data[offset], 1]; | ||
var data = Buffer.concat([transaction.version, this.createVarint(inputs.length)]); | ||
return this.getTrustedInputRaw(data, indexLookup).then(processInputs).then(processOutputs); | ||
} | ||
if (data[offset] === 0xfd) { | ||
return [(data[offset + 2] << 8) + data[offset + 1], 3]; | ||
}, { | ||
key: "getVarint", | ||
value: function getVarint(data, offset) { | ||
if (data[offset] < 0xfd) { | ||
return [data[offset], 1]; | ||
} | ||
if (data[offset] === 0xfd) { | ||
return [(data[offset + 2] << 8) + data[offset + 1], 3]; | ||
} | ||
if (data[offset] === 0xfe) { | ||
return [(data[offset + 4] << 24) + (data[offset + 3] << 16) + (data[offset + 2] << 8) + data[offset + 1], 5]; | ||
} | ||
throw new Error("getVarint called with unexpected parameters"); | ||
} | ||
if (data[offset] === 0xfe) { | ||
return [(data[offset + 4] << 24) + (data[offset + 3] << 16) + (data[offset + 2] << 8) + data[offset + 1], 5]; | ||
}, { | ||
key: "startUntrustedHashTransactionInputRaw", | ||
value: function startUntrustedHashTransactionInputRaw(newTransaction, firstRound, transactionData) { | ||
return this.transport.send(0xe0, 0x44, firstRound ? 0x00 : 0x80, newTransaction ? 0x00 : 0x80, transactionData); | ||
} | ||
}, { | ||
key: "startUntrustedHashTransactionInput", | ||
value: function startUntrustedHashTransactionInput(newTransaction, transaction, inputs) { | ||
var _this2 = this; | ||
throw new Error("getVarint called with unexpected parameters"); | ||
} | ||
startUntrustedHashTransactionInputRaw(newTransaction, firstRound, transactionData) { | ||
return this.transport.send(0xe0, 0x44, firstRound ? 0x00 : 0x80, newTransaction ? 0x00 : 0x80, transactionData); | ||
} | ||
startUntrustedHashTransactionInput(newTransaction, transaction, inputs) { | ||
let data = Buffer.concat([transaction.version, this.createVarint(transaction.inputs.length)]); | ||
return this.startUntrustedHashTransactionInputRaw(newTransaction, true, data).then(() => { | ||
let i = 0; | ||
return (0, _utils.eachSeries)(transaction.inputs, input => { | ||
// TODO : segwit | ||
let prefix; | ||
if (inputs[i].trustedInput) { | ||
prefix = Buffer.alloc(2); | ||
prefix[0] = 0x01; | ||
prefix[1] = inputs[i].value.length; | ||
} else { | ||
prefix = Buffer.alloc(1); | ||
prefix[0] = 0x00; | ||
} | ||
data = Buffer.concat([prefix, inputs[i].value, this.createVarint(input.script.length)]); | ||
return this.startUntrustedHashTransactionInputRaw(newTransaction, false, data).then(() => { | ||
let scriptBlocks = []; | ||
let offset = 0; | ||
if (input.script.length === 0) { | ||
scriptBlocks.push(input.sequence); | ||
var data = Buffer.concat([transaction.version, this.createVarint(transaction.inputs.length)]); | ||
return this.startUntrustedHashTransactionInputRaw(newTransaction, true, data).then(function () { | ||
var i = 0; | ||
return (0, _utils.eachSeries)(transaction.inputs, function (input) { | ||
// TODO : segwit | ||
var prefix = void 0; | ||
if (inputs[i].trustedInput) { | ||
prefix = Buffer.alloc(2); | ||
prefix[0] = 0x01; | ||
prefix[1] = inputs[i].value.length; | ||
} else { | ||
while (offset !== input.script.length) { | ||
let blockSize = input.script.length - offset > MAX_SCRIPT_BLOCK ? MAX_SCRIPT_BLOCK : input.script.length - offset; | ||
if (offset + blockSize !== input.script.length) { | ||
scriptBlocks.push(input.script.slice(offset, offset + blockSize)); | ||
} else { | ||
scriptBlocks.push(Buffer.concat([input.script.slice(offset, offset + blockSize), input.sequence])); | ||
prefix = Buffer.alloc(1); | ||
prefix[0] = 0x00; | ||
} | ||
data = Buffer.concat([prefix, inputs[i].value, _this2.createVarint(input.script.length)]); | ||
return _this2.startUntrustedHashTransactionInputRaw(newTransaction, false, data).then(function () { | ||
var scriptBlocks = []; | ||
var offset = 0; | ||
if (input.script.length === 0) { | ||
scriptBlocks.push(input.sequence); | ||
} else { | ||
while (offset !== input.script.length) { | ||
var blockSize = input.script.length - offset > MAX_SCRIPT_BLOCK ? MAX_SCRIPT_BLOCK : input.script.length - offset; | ||
if (offset + blockSize !== input.script.length) { | ||
scriptBlocks.push(input.script.slice(offset, offset + blockSize)); | ||
} else { | ||
scriptBlocks.push(Buffer.concat([input.script.slice(offset, offset + blockSize), input.sequence])); | ||
} | ||
offset += blockSize; | ||
} | ||
offset += blockSize; | ||
} | ||
} | ||
return (0, _utils.eachSeries)(scriptBlocks, scriptBlock => { | ||
return this.startUntrustedHashTransactionInputRaw(newTransaction, false, scriptBlock); | ||
}).then(() => { | ||
i++; | ||
return (0, _utils.eachSeries)(scriptBlocks, function (scriptBlock) { | ||
return _this2.startUntrustedHashTransactionInputRaw(newTransaction, false, scriptBlock); | ||
}).then(function () { | ||
i++; | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
} | ||
} | ||
}, { | ||
key: "provideOutputFullChangePath", | ||
value: function provideOutputFullChangePath(path) { | ||
var paths = (0, _utils.splitPath)(path); | ||
var buffer = Buffer.alloc(1 + paths.length * 4); | ||
buffer[0] = paths.length; | ||
paths.forEach(function (element, index) { | ||
buffer.writeUInt32BE(element, 1 + 4 * index); | ||
}); | ||
return this.transport.send(0xe0, 0x4a, 0xff, 0x00, buffer); | ||
} | ||
}, { | ||
key: "hashOutputFull", | ||
value: function hashOutputFull(outputScript) { | ||
var _this3 = this; | ||
provideOutputFullChangePath(path) { | ||
let paths = (0, _utils.splitPath)(path); | ||
let buffer = Buffer.alloc(1 + paths.length * 4); | ||
buffer[0] = paths.length; | ||
paths.forEach((element, index) => { | ||
buffer.writeUInt32BE(element, 1 + 4 * index); | ||
}); | ||
return this.transport.send(0xe0, 0x4a, 0xff, 0x00, buffer); | ||
} | ||
var offset = 0; | ||
return (0, _utils.asyncWhile)(function () { | ||
return offset < outputScript.length; | ||
}, function () { | ||
var blockSize = offset + MAX_SCRIPT_BLOCK >= outputScript.length ? outputScript.length - offset : MAX_SCRIPT_BLOCK; | ||
var p1 = offset + blockSize === outputScript.length ? 0x80 : 0x00; | ||
var data = outputScript.slice(offset, offset + blockSize); | ||
return _this3.transport.send(0xe0, 0x4a, p1, 0x00, data).then(function () { | ||
offset += blockSize; | ||
}); | ||
}); | ||
} | ||
hashOutputFull(outputScript) { | ||
let offset = 0; | ||
return (0, _utils.asyncWhile)(() => offset < outputScript.length, () => { | ||
let blockSize = offset + MAX_SCRIPT_BLOCK >= outputScript.length ? outputScript.length - offset : MAX_SCRIPT_BLOCK; | ||
let p1 = offset + blockSize === outputScript.length ? 0x80 : 0x00; | ||
let data = outputScript.slice(offset, offset + blockSize); | ||
return this.transport.send(0xe0, 0x4a, p1, 0x00, data).then(() => { | ||
offset += blockSize; | ||
/** | ||
*/ | ||
}, { | ||
key: "signTransaction", | ||
value: function signTransaction(path) { | ||
var lockTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_LOCKTIME; | ||
var sigHashType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : SIGHASH_ALL; | ||
var paths = (0, _utils.splitPath)(path); | ||
var buffer = Buffer.alloc(1 + paths.length * 4 + 1 + 4 + 1); // TODO shouldn't have to calc that, just use buffer concat all the way down | ||
var offset = 0; | ||
buffer[offset++] = paths.length; | ||
paths.forEach(function (element) { | ||
buffer.writeUInt32BE(element, offset); | ||
offset += 4; | ||
}); | ||
}); | ||
} | ||
/** | ||
*/ | ||
signTransaction(path, lockTime = DEFAULT_LOCKTIME, sigHashType = SIGHASH_ALL) { | ||
const paths = (0, _utils.splitPath)(path); | ||
const buffer = Buffer.alloc(1 + paths.length * 4 + 1 + 4 + 1); // TODO shouldn't have to calc that, just use buffer concat all the way down | ||
let offset = 0; | ||
buffer[offset++] = paths.length; | ||
paths.forEach(element => { | ||
buffer.writeUInt32BE(element, offset); | ||
buffer[offset++] = 0x00; // authorization length | ||
buffer.writeUInt32LE(lockTime, offset); | ||
offset += 4; | ||
}); | ||
buffer[offset++] = 0x00; // authorization length | ||
buffer.writeUInt32LE(lockTime, offset); | ||
offset += 4; | ||
buffer[offset++] = sigHashType; | ||
return this.transport.send(0xe0, 0x48, 0x00, 0x00, buffer).then(result => { | ||
result[0] = 0x30; | ||
return result.slice(0, result.length - 2); | ||
}); | ||
} | ||
buffer[offset++] = sigHashType; | ||
return this.transport.send(0xe0, 0x48, 0x00, 0x00, buffer).then(function (result) { | ||
result[0] = 0x30; | ||
return result.slice(0, result.length - 2); | ||
}); | ||
} | ||
/** | ||
* You can sign a message according to the Bitcoin Signature format and retrieve v, r, s given the message and the BIP 32 path of the account to sign. | ||
* @example | ||
btc.signMessageNew_async("44'/60'/0'/0'/0", Buffer.from("test").toString("hex")).then(function(result) { | ||
var v = result['v'] + 27 + 4; | ||
var signature = Buffer.from(v.toString(16) + result['r'] + result['s'], 'hex').toString('base64'); | ||
console.log("Signature : " + signature); | ||
}).catch(function(ex) {console.log(ex);}); | ||
*/ | ||
signMessageNew(path, messageHex) { | ||
const paths = (0, _utils.splitPath)(path); | ||
const message = new Buffer(messageHex, "hex"); | ||
let offset = 0; | ||
const toSend = []; | ||
while (offset !== message.length) { | ||
let maxChunkSize = offset === 0 ? MAX_SCRIPT_BLOCK - 1 - paths.length * 4 - 4 : MAX_SCRIPT_BLOCK; | ||
let chunkSize = offset + maxChunkSize > message.length ? message.length - offset : maxChunkSize; | ||
const buffer = new Buffer(offset === 0 ? 1 + paths.length * 4 + 2 + chunkSize : chunkSize); | ||
if (offset === 0) { | ||
buffer[0] = paths.length; | ||
paths.forEach((element, index) => { | ||
buffer.writeUInt32BE(element, 1 + 4 * index); | ||
/** | ||
* You can sign a message according to the Bitcoin Signature format and retrieve v, r, s given the message and the BIP 32 path of the account to sign. | ||
* @example | ||
btc.signMessageNew_async("44'/60'/0'/0'/0", Buffer.from("test").toString("hex")).then(function(result) { | ||
var v = result['v'] + 27 + 4; | ||
var signature = Buffer.from(v.toString(16) + result['r'] + result['s'], 'hex').toString('base64'); | ||
console.log("Signature : " + signature); | ||
}).catch(function(ex) {console.log(ex);}); | ||
*/ | ||
}, { | ||
key: "signMessageNew", | ||
value: function signMessageNew(path, messageHex) { | ||
var _this4 = this; | ||
var paths = (0, _utils.splitPath)(path); | ||
var message = new Buffer(messageHex, "hex"); | ||
var offset = 0; | ||
var toSend = []; | ||
var _loop = function _loop() { | ||
var maxChunkSize = offset === 0 ? MAX_SCRIPT_BLOCK - 1 - paths.length * 4 - 4 : MAX_SCRIPT_BLOCK; | ||
var chunkSize = offset + maxChunkSize > message.length ? message.length - offset : maxChunkSize; | ||
var buffer = new Buffer(offset === 0 ? 1 + paths.length * 4 + 2 + chunkSize : chunkSize); | ||
if (offset === 0) { | ||
buffer[0] = paths.length; | ||
paths.forEach(function (element, index) { | ||
buffer.writeUInt32BE(element, 1 + 4 * index); | ||
}); | ||
buffer.writeUInt16BE(message.length, 1 + 4 * paths.length); | ||
message.copy(buffer, 1 + 4 * paths.length + 2, offset, offset + chunkSize); | ||
} else { | ||
message.copy(buffer, 0, offset, offset + chunkSize); | ||
} | ||
toSend.push(buffer); | ||
offset += chunkSize; | ||
}; | ||
while (offset !== message.length) { | ||
_loop(); | ||
} | ||
return (0, _utils.foreach)(toSend, function (data, i) { | ||
return _this4.transport.send(0xe0, 0x4e, 0x00, i === 0 ? 0x01 : 0x80, data); | ||
}).then(function () { | ||
return _this4.transport.send(0xe0, 0x4e, 0x80, 0x00, Buffer.from([0x00])).then(function (response) { | ||
var v = response[0] - 0x30; | ||
var r = response.slice(4, 4 + response[3]); | ||
if (r[0] === 0) { | ||
r = r.slice(1); | ||
} | ||
r = r.toString("hex"); | ||
var offset = 4 + response[3] + 2; | ||
var s = response.slice(offset, offset + response[offset - 1]); | ||
if (s[0] === 0) { | ||
s = s.slice(1); | ||
} | ||
s = s.toString("hex"); | ||
return { v: v, r: r, s: s }; | ||
}); | ||
buffer.writeUInt16BE(message.length, 1 + 4 * paths.length); | ||
message.copy(buffer, 1 + 4 * paths.length + 2, offset, offset + chunkSize); | ||
} else { | ||
message.copy(buffer, 0, offset, offset + chunkSize); | ||
} | ||
toSend.push(buffer); | ||
offset += chunkSize; | ||
}); | ||
} | ||
return (0, _utils.foreach)(toSend, (data, i) => this.transport.send(0xe0, 0x4e, 0x00, i === 0 ? 0x01 : 0x80, data)).then(() => { | ||
return this.transport.send(0xe0, 0x4e, 0x80, 0x00, Buffer.from([0x00])).then(response => { | ||
const v = response[0] - 0x30; | ||
let r = response.slice(4, 4 + response[3]); | ||
if (r[0] === 0) { | ||
r = r.slice(1); | ||
} | ||
r = r.toString("hex"); | ||
let offset = 4 + response[3] + 2; | ||
let s = response.slice(offset, offset + response[offset - 1]); | ||
if (s[0] === 0) { | ||
s = s.slice(1); | ||
} | ||
s = s.toString("hex"); | ||
return { v, r, s }; | ||
}); | ||
}); | ||
} | ||
/** | ||
* To sign a transaction involving standard (P2PKH) inputs, call createPaymentTransactionNew with the following parameters | ||
* @param inputs is an array of [ transaction, output_index, optional redeem script, optional sequence ] where | ||
* | ||
* * transaction is the previously computed transaction object for this UTXO | ||
* * output_index is the output in the transaction used as input for this UTXO (counting from 0) | ||
* * redeem script is the optional redeem script to use when consuming a Segregated Witness input | ||
* * sequence is the sequence number to use for this input (when using RBF), or non present | ||
* @param associatedKeysets is an array of BIP 32 paths pointing to the path to the private key used for each UTXO | ||
* @param changePath is an optional BIP 32 path pointing to the path to the public key used to compute the change address | ||
* @param outputScript is the hexadecimal serialized outputs of the transaction to sign | ||
* @param lockTime is the optional lockTime of the transaction to sign, or default (0) | ||
* @param sigHashType is the hash type of the transaction to sign, or default (all) | ||
* @return the signed transaction ready to be broadcast | ||
* @example | ||
btc.createPaymentTransactionNew( | ||
[ [tx1, 1] ], | ||
["0'/0/0"], | ||
undefined, | ||
"01905f0100000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88ac" | ||
).then(res => ...); | ||
*/ | ||
createPaymentTransactionNew(inputs, associatedKeysets, changePath, outputScriptHex, lockTime = DEFAULT_LOCKTIME, sigHashType = SIGHASH_ALL) { | ||
// Inputs are provided as arrays of [transaction, output_index, optional redeem script, optional sequence] | ||
// associatedKeysets are provided as arrays of [path] | ||
const nullScript = Buffer.alloc(0); | ||
const nullPrevout = Buffer.alloc(0); | ||
const defaultVersion = Buffer.alloc(4); | ||
defaultVersion.writeUInt32LE(1, 0); | ||
const trustedInputs = []; | ||
const regularOutputs = []; | ||
const signatures = []; | ||
const publicKeys = []; | ||
let firstRun = true; | ||
const resuming = false; | ||
const targetTransaction = { | ||
inputs: [], | ||
version: defaultVersion | ||
}; | ||
/** | ||
* To sign a transaction involving standard (P2PKH) inputs, call createPaymentTransactionNew with the following parameters | ||
* @param inputs is an array of [ transaction, output_index, optional redeem script, optional sequence ] where | ||
* | ||
* * transaction is the previously computed transaction object for this UTXO | ||
* * output_index is the output in the transaction used as input for this UTXO (counting from 0) | ||
* * redeem script is the optional redeem script to use when consuming a Segregated Witness input | ||
* * sequence is the sequence number to use for this input (when using RBF), or non present | ||
* @param associatedKeysets is an array of BIP 32 paths pointing to the path to the private key used for each UTXO | ||
* @param changePath is an optional BIP 32 path pointing to the path to the public key used to compute the change address | ||
* @param outputScript is the hexadecimal serialized outputs of the transaction to sign | ||
* @param lockTime is the optional lockTime of the transaction to sign, or default (0) | ||
* @param sigHashType is the hash type of the transaction to sign, or default (all) | ||
* @return the signed transaction ready to be broadcast | ||
* @example | ||
btc.createPaymentTransactionNew( | ||
[ [tx1, 1] ], | ||
["0'/0/0"], | ||
undefined, | ||
"01905f0100000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88ac" | ||
).then(res => ...); | ||
*/ | ||
const outputScript = Buffer.from(outputScriptHex, "hex"); | ||
}, { | ||
key: "createPaymentTransactionNew", | ||
value: function createPaymentTransactionNew(inputs, associatedKeysets, changePath, outputScriptHex) { | ||
var _this5 = this; | ||
return (0, _utils.foreach)(inputs, input => (0, _utils.doIf)(!resuming, () => this.getTrustedInput(input[1], input[0]).then(trustedInput => { | ||
trustedInputs.push({ | ||
trustedInput: true, | ||
value: Buffer.from(trustedInput, "hex") | ||
}); | ||
})).then(() => { | ||
const { outputs } = input[0]; | ||
const index = input[1]; | ||
if (outputs && index <= outputs.length - 1) { | ||
regularOutputs.push(outputs[index]); | ||
} | ||
})).then(() => { | ||
for (let i = 0; i < inputs.length; i++) { | ||
let sequence = Buffer.alloc(4); | ||
sequence.writeUInt32LE(inputs[i].length >= 4 && typeof inputs[i][3] === "number" ? inputs[i][3] : DEFAULT_SEQUENCE, 0); | ||
targetTransaction.inputs.push({ | ||
script: nullScript, | ||
prevout: nullPrevout, | ||
sequence | ||
var lockTime = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : DEFAULT_LOCKTIME; | ||
var sigHashType = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : SIGHASH_ALL; | ||
// Inputs are provided as arrays of [transaction, output_index, optional redeem script, optional sequence] | ||
// associatedKeysets are provided as arrays of [path] | ||
var nullScript = Buffer.alloc(0); | ||
var nullPrevout = Buffer.alloc(0); | ||
var defaultVersion = Buffer.alloc(4); | ||
defaultVersion.writeUInt32LE(1, 0); | ||
var trustedInputs = []; | ||
var regularOutputs = []; | ||
var signatures = []; | ||
var publicKeys = []; | ||
var firstRun = true; | ||
var resuming = false; | ||
var targetTransaction = { | ||
inputs: [], | ||
version: defaultVersion | ||
}; | ||
var outputScript = Buffer.from(outputScriptHex, "hex"); | ||
return (0, _utils.foreach)(inputs, function (input) { | ||
return (0, _utils.doIf)(!resuming, function () { | ||
return _this5.getTrustedInput(input[1], input[0]).then(function (trustedInput) { | ||
trustedInputs.push({ | ||
trustedInput: true, | ||
value: Buffer.from(trustedInput, "hex") | ||
}); | ||
}); | ||
}).then(function () { | ||
var outputs = input[0].outputs; | ||
var index = input[1]; | ||
if (outputs && index <= outputs.length - 1) { | ||
regularOutputs.push(outputs[index]); | ||
} | ||
}); | ||
} | ||
}).then(() => { | ||
return (0, _utils.doIf)(!resuming, () => | ||
// Collect public keys | ||
(0, _utils.foreach)(inputs, (input, i) => this.getWalletPublicKey(associatedKeysets[i])).then(result => { | ||
for (let index = 0; index < result.length; index++) { | ||
publicKeys.push(this.compressPublicKey(Buffer.from(result[index].publicKey, "hex"))); | ||
}).then(function () { | ||
for (var i = 0; i < inputs.length; i++) { | ||
var _sequence = Buffer.alloc(4); | ||
_sequence.writeUInt32LE(inputs[i].length >= 4 && typeof inputs[i][3] === "number" ? inputs[i][3] : DEFAULT_SEQUENCE, 0); | ||
targetTransaction.inputs.push({ | ||
script: nullScript, | ||
prevout: nullPrevout, | ||
sequence: _sequence | ||
}); | ||
} | ||
})); | ||
}).then(() => (0, _utils.foreach)(inputs, (input, i) => { | ||
targetTransaction.inputs[i].script = inputs[i].length >= 3 && typeof inputs[i][2] === "string" ? Buffer.from(inputs[i][2], "hex") : regularOutputs[i].script; | ||
return this.startUntrustedHashTransactionInput(firstRun, targetTransaction, trustedInputs).then(() => Promise.resolve().then(() => { | ||
if (!resuming && typeof changePath !== "undefined") { | ||
return this.provideOutputFullChangePath(changePath); | ||
}).then(function () { | ||
return (0, _utils.doIf)(!resuming, function () { | ||
return ( | ||
// Collect public keys | ||
(0, _utils.foreach)(inputs, function (input, i) { | ||
return _this5.getWalletPublicKey(associatedKeysets[i]); | ||
}).then(function (result) { | ||
for (var index = 0; index < result.length; index++) { | ||
publicKeys.push(_this5.compressPublicKey(Buffer.from(result[index].publicKey, "hex"))); | ||
} | ||
}) | ||
); | ||
}); | ||
}).then(function () { | ||
return (0, _utils.foreach)(inputs, function (input, i) { | ||
targetTransaction.inputs[i].script = inputs[i].length >= 3 && typeof inputs[i][2] === "string" ? Buffer.from(inputs[i][2], "hex") : regularOutputs[i].script; | ||
return _this5.startUntrustedHashTransactionInput(firstRun, targetTransaction, trustedInputs).then(function () { | ||
return _promise2.default.resolve().then(function () { | ||
if (!resuming && typeof changePath !== "undefined") { | ||
return _this5.provideOutputFullChangePath(changePath); | ||
} | ||
}).then(function () { | ||
return _this5.hashOutputFull(outputScript); | ||
}).then(function () { | ||
return _this5.signTransaction(associatedKeysets[i], lockTime, sigHashType).then(function (signature) { | ||
signatures.push(signature); | ||
targetTransaction.inputs[i].script = nullScript; | ||
if (firstRun) { | ||
firstRun = false; | ||
} | ||
}); | ||
}); | ||
}); | ||
}); | ||
}).then(function () { | ||
// Populate the final input scripts | ||
for (var i = 0; i < inputs.length; i++) { | ||
var signatureSize = Buffer.alloc(1); | ||
var keySize = Buffer.alloc(1); | ||
signatureSize[0] = signatures[i].length; | ||
keySize[0] = publicKeys[i].length; | ||
targetTransaction.inputs[i].script = Buffer.concat([signatureSize, signatures[i], keySize, publicKeys[i]]); | ||
targetTransaction.inputs[i].prevout = trustedInputs[i].value.slice(4, 4 + 0x24); | ||
} | ||
}).then(() => this.hashOutputFull(outputScript)).then(() => this.signTransaction(associatedKeysets[i], lockTime, sigHashType).then(signature => { | ||
signatures.push(signature); | ||
targetTransaction.inputs[i].script = nullScript; | ||
if (firstRun) { | ||
firstRun = false; | ||
} | ||
}))); | ||
})).then(() => { | ||
// Populate the final input scripts | ||
for (let i = 0; i < inputs.length; i++) { | ||
const signatureSize = Buffer.alloc(1); | ||
const keySize = Buffer.alloc(1); | ||
signatureSize[0] = signatures[i].length; | ||
keySize[0] = publicKeys[i].length; | ||
targetTransaction.inputs[i].script = Buffer.concat([signatureSize, signatures[i], keySize, publicKeys[i]]); | ||
targetTransaction.inputs[i].prevout = trustedInputs[i].value.slice(4, 4 + 0x24); | ||
} | ||
const lockTimeBuffer = Buffer.alloc(4); | ||
lockTimeBuffer.writeUInt32LE(lockTime, 0); | ||
var lockTimeBuffer = Buffer.alloc(4); | ||
lockTimeBuffer.writeUInt32LE(lockTime, 0); | ||
const result = Buffer.concat([this.serializeTransaction(targetTransaction), outputScript, lockTimeBuffer]); | ||
var result = Buffer.concat([_this5.serializeTransaction(targetTransaction), outputScript, lockTimeBuffer]); | ||
return result.toString("hex"); | ||
}); | ||
} | ||
return result.toString("hex"); | ||
}); | ||
} | ||
/** | ||
* To obtain the signature of multisignature (P2SH) inputs, call signP2SHTransaction_async with the folowing parameters | ||
* @param inputs is an array of [ transaction, output_index, redeem script, optional sequence ] where | ||
* * transaction is the previously computed transaction object for this UTXO | ||
* * output_index is the output in the transaction used as input for this UTXO (counting from 0) | ||
* * redeem script is the mandatory redeem script associated to the current P2SH input | ||
* * sequence is the sequence number to use for this input (when using RBF), or non present | ||
* @param associatedKeysets is an array of BIP 32 paths pointing to the path to the private key used for each UTXO | ||
* @param outputScript is the hexadecimal serialized outputs of the transaction to sign | ||
* @param lockTime is the optional lockTime of the transaction to sign, or default (0) | ||
* @param sigHashType is the hash type of the transaction to sign, or default (all) | ||
* @return the signed transaction ready to be broadcast | ||
* @example | ||
btc.signP2SHTransaction( | ||
[ [tx, 1, "52210289b4a3ad52a919abd2bdd6920d8a6879b1e788c38aa76f0440a6f32a9f1996d02103a3393b1439d1693b063482c04bd40142db97bdf139eedd1b51ffb7070a37eac321030b9a409a1e476b0d5d17b804fcdb81cf30f9b99c6f3ae1178206e08bc500639853ae"] ], | ||
["0'/0/0"], | ||
"01905f0100000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88ac" | ||
).then(result => ...); | ||
*/ | ||
signP2SHTransaction(inputs, associatedKeysets, outputScriptHex, lockTime = DEFAULT_LOCKTIME, sigHashType = SIGHASH_ALL) { | ||
// Inputs are provided as arrays of [transaction, output_index, redeem script, optional sequence] | ||
// associatedKeysets are provided as arrays of [path] | ||
const nullScript = Buffer.alloc(0); | ||
const nullPrevout = Buffer.alloc(0); | ||
const defaultVersion = Buffer.alloc(4); | ||
defaultVersion.writeUInt32LE(1, 0); | ||
const trustedInputs = []; | ||
const regularOutputs = []; | ||
const signatures = []; | ||
let firstRun = true; | ||
let resuming = false; | ||
let targetTransaction = { | ||
inputs: [], | ||
version: defaultVersion | ||
}; | ||
/** | ||
* To obtain the signature of multisignature (P2SH) inputs, call signP2SHTransaction_async with the folowing parameters | ||
* @param inputs is an array of [ transaction, output_index, redeem script, optional sequence ] where | ||
* * transaction is the previously computed transaction object for this UTXO | ||
* * output_index is the output in the transaction used as input for this UTXO (counting from 0) | ||
* * redeem script is the mandatory redeem script associated to the current P2SH input | ||
* * sequence is the sequence number to use for this input (when using RBF), or non present | ||
* @param associatedKeysets is an array of BIP 32 paths pointing to the path to the private key used for each UTXO | ||
* @param outputScript is the hexadecimal serialized outputs of the transaction to sign | ||
* @param lockTime is the optional lockTime of the transaction to sign, or default (0) | ||
* @param sigHashType is the hash type of the transaction to sign, or default (all) | ||
* @return the signed transaction ready to be broadcast | ||
* @example | ||
btc.signP2SHTransaction( | ||
[ [tx, 1, "52210289b4a3ad52a919abd2bdd6920d8a6879b1e788c38aa76f0440a6f32a9f1996d02103a3393b1439d1693b063482c04bd40142db97bdf139eedd1b51ffb7070a37eac321030b9a409a1e476b0d5d17b804fcdb81cf30f9b99c6f3ae1178206e08bc500639853ae"] ], | ||
["0'/0/0"], | ||
"01905f0100000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88ac" | ||
).then(result => ...); | ||
*/ | ||
const outputScript = Buffer.from(outputScriptHex, "hex"); | ||
}, { | ||
key: "signP2SHTransaction", | ||
value: function signP2SHTransaction(inputs, associatedKeysets, outputScriptHex) { | ||
var _this6 = this; | ||
return (0, _utils.foreach)(inputs, input => (0, _utils.doIf)(!resuming, () => this.getTrustedInput(input[1], input[0]).then(trustedInput => { | ||
let inputItem = {}; | ||
inputItem.trustedInput = false; | ||
inputItem.value = Buffer.from(trustedInput, "hex").slice(4, 4 + 0x24); | ||
trustedInputs.push(inputItem); | ||
})).then(() => { | ||
const { outputs } = input[0]; | ||
const index = input[1]; | ||
if (outputs && index <= outputs.length - 1) { | ||
regularOutputs.push(outputs[index]); | ||
} | ||
})).then(() => { | ||
// Pre-build the target transaction | ||
for (let i = 0; i < inputs.length; i++) { | ||
let tmp = Buffer.alloc(4); | ||
let sequence; | ||
if (inputs[i].length >= 4 && typeof inputs[i][3] === "number") { | ||
sequence = inputs[i][3]; | ||
} else { | ||
sequence = DEFAULT_SEQUENCE; | ||
var lockTime = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : DEFAULT_LOCKTIME; | ||
var sigHashType = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : SIGHASH_ALL; | ||
// Inputs are provided as arrays of [transaction, output_index, redeem script, optional sequence] | ||
// associatedKeysets are provided as arrays of [path] | ||
var nullScript = Buffer.alloc(0); | ||
var nullPrevout = Buffer.alloc(0); | ||
var defaultVersion = Buffer.alloc(4); | ||
defaultVersion.writeUInt32LE(1, 0); | ||
var trustedInputs = []; | ||
var regularOutputs = []; | ||
var signatures = []; | ||
var firstRun = true; | ||
var resuming = false; | ||
var targetTransaction = { | ||
inputs: [], | ||
version: defaultVersion | ||
}; | ||
var outputScript = Buffer.from(outputScriptHex, "hex"); | ||
return (0, _utils.foreach)(inputs, function (input) { | ||
return (0, _utils.doIf)(!resuming, function () { | ||
return _this6.getTrustedInput(input[1], input[0]).then(function (trustedInput) { | ||
var inputItem = {}; | ||
inputItem.trustedInput = false; | ||
inputItem.value = Buffer.from(trustedInput, "hex").slice(4, 4 + 0x24); | ||
trustedInputs.push(inputItem); | ||
}); | ||
}).then(function () { | ||
var outputs = input[0].outputs; | ||
var index = input[1]; | ||
if (outputs && index <= outputs.length - 1) { | ||
regularOutputs.push(outputs[index]); | ||
} | ||
}); | ||
}).then(function () { | ||
// Pre-build the target transaction | ||
for (var i = 0; i < inputs.length; i++) { | ||
var tmp = Buffer.alloc(4); | ||
var _sequence2 = void 0; | ||
if (inputs[i].length >= 4 && typeof inputs[i][3] === "number") { | ||
_sequence2 = inputs[i][3]; | ||
} else { | ||
_sequence2 = DEFAULT_SEQUENCE; | ||
} | ||
tmp.writeUInt32LE(_sequence2, 0); | ||
targetTransaction.inputs.push({ | ||
prevout: nullPrevout, | ||
script: nullScript, | ||
sequence: tmp | ||
}); | ||
} | ||
tmp.writeUInt32LE(sequence, 0); | ||
targetTransaction.inputs.push({ | ||
prevout: nullPrevout, | ||
script: nullScript, | ||
sequence: tmp | ||
}).then(function () { | ||
return (0, _utils.foreach)(inputs, function (input, i) { | ||
targetTransaction.inputs[i].script = inputs[i].length >= 3 && typeof inputs[i][2] === "string" ? Buffer.from(inputs[i][2], "hex") : regularOutputs[i].script; | ||
return _this6.startUntrustedHashTransactionInput(firstRun, targetTransaction, trustedInputs).then(function () { | ||
return _this6.hashOutputFull(outputScript); | ||
}).then(function () { | ||
return _this6.signTransaction(associatedKeysets[i], lockTime, sigHashType).then(function (signature) { | ||
signatures.push(signature.slice(0, signature.length - 1).toString("hex")); | ||
targetTransaction.inputs[i].script = nullScript; | ||
if (firstRun) { | ||
firstRun = false; | ||
} | ||
}); | ||
}); | ||
}); | ||
}).then(function () { | ||
return signatures; | ||
}); | ||
} | ||
}, { | ||
key: "compressPublicKey", | ||
value: function compressPublicKey(publicKey) { | ||
var prefix = (publicKey[64] & 1) !== 0 ? 0x03 : 0x02; | ||
var prefixBuffer = Buffer.alloc(1); | ||
prefixBuffer[0] = prefix; | ||
return Buffer.concat([prefixBuffer, publicKey.slice(1, 1 + 32)]); | ||
} | ||
}, { | ||
key: "createVarint", | ||
value: function createVarint(value) { | ||
if (value < 0xfd) { | ||
var _buffer = Buffer.alloc(1); | ||
_buffer[0] = value; | ||
return _buffer; | ||
} | ||
}).then(() => (0, _utils.foreach)(inputs, (input, i) => { | ||
targetTransaction.inputs[i].script = inputs[i].length >= 3 && typeof inputs[i][2] === "string" ? Buffer.from(inputs[i][2], "hex") : regularOutputs[i].script; | ||
return this.startUntrustedHashTransactionInput(firstRun, targetTransaction, trustedInputs).then(() => this.hashOutputFull(outputScript)).then(() => this.signTransaction(associatedKeysets[i], lockTime, sigHashType).then(signature => { | ||
signatures.push(signature.slice(0, signature.length - 1).toString("hex")); | ||
targetTransaction.inputs[i].script = nullScript; | ||
if (firstRun) { | ||
firstRun = false; | ||
} | ||
})); | ||
})).then(() => signatures); | ||
} | ||
compressPublicKey(publicKey) { | ||
const prefix = (publicKey[64] & 1) !== 0 ? 0x03 : 0x02; | ||
const prefixBuffer = Buffer.alloc(1); | ||
prefixBuffer[0] = prefix; | ||
return Buffer.concat([prefixBuffer, publicKey.slice(1, 1 + 32)]); | ||
} | ||
createVarint(value) { | ||
if (value < 0xfd) { | ||
const buffer = Buffer.alloc(1); | ||
buffer[0] = value; | ||
return buffer; | ||
} | ||
if (value <= 0xffff) { | ||
const buffer = Buffer.alloc(3); | ||
buffer[0] = 0xfd; | ||
if (value <= 0xffff) { | ||
var _buffer2 = Buffer.alloc(3); | ||
_buffer2[0] = 0xfd; | ||
_buffer2[1] = value & 0xff; | ||
_buffer2[2] = value >> 8 & 0xff; | ||
return _buffer2; | ||
} | ||
var buffer = Buffer.alloc(5); | ||
buffer[0] = 0xfe; | ||
buffer[1] = value & 0xff; | ||
buffer[2] = value >> 8 & 0xff; | ||
buffer[3] = value >> 16 & 0xff; | ||
buffer[4] = value >> 24 & 0xff; | ||
return buffer; | ||
} | ||
const buffer = Buffer.alloc(5); | ||
buffer[0] = 0xfe; | ||
buffer[1] = value & 0xff; | ||
buffer[2] = value >> 8 & 0xff; | ||
buffer[3] = value >> 16 & 0xff; | ||
buffer[4] = value >> 24 & 0xff; | ||
return buffer; | ||
} | ||
/** | ||
* For each UTXO included in your transaction, create a transaction object from the raw serialized version of the transaction used in this UTXO. | ||
* @example | ||
const tx1 = btc.splitTransaction("01000000014ea60aeac5252c14291d428915bd7ccd1bfc4af009f4d4dc57ae597ed0420b71010000008a47304402201f36a12c240dbf9e566bc04321050b1984cd6eaf6caee8f02bb0bfec08e3354b022012ee2aeadcbbfd1e92959f57c15c1c6debb757b798451b104665aa3010569b49014104090b15bde569386734abf2a2b99f9ca6a50656627e77de663ca7325702769986cf26cc9dd7fdea0af432c8e2becc867c932e1b9dd742f2a108997c2252e2bdebffffffff0281b72e00000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88aca0860100000000001976a9144533f5fb9b4817f713c48f0bfe96b9f50c476c9b88ac00000000"); | ||
*/ | ||
splitTransaction(transactionHex) { | ||
const inputs = []; | ||
const outputs = []; | ||
let offset = 0; | ||
const transaction = Buffer.from(transactionHex, "hex"); | ||
const version = transaction.slice(offset, offset + 4); | ||
offset += 4; | ||
let varint = this.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; | ||
varint = this.getVarint(transaction, offset); | ||
/** | ||
* For each UTXO included in your transaction, create a transaction object from the raw serialized version of the transaction used in this UTXO. | ||
* @example | ||
const tx1 = btc.splitTransaction("01000000014ea60aeac5252c14291d428915bd7ccd1bfc4af009f4d4dc57ae597ed0420b71010000008a47304402201f36a12c240dbf9e566bc04321050b1984cd6eaf6caee8f02bb0bfec08e3354b022012ee2aeadcbbfd1e92959f57c15c1c6debb757b798451b104665aa3010569b49014104090b15bde569386734abf2a2b99f9ca6a50656627e77de663ca7325702769986cf26cc9dd7fdea0af432c8e2becc867c932e1b9dd742f2a108997c2252e2bdebffffffff0281b72e00000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88aca0860100000000001976a9144533f5fb9b4817f713c48f0bfe96b9f50c476c9b88ac00000000"); | ||
*/ | ||
}, { | ||
key: "splitTransaction", | ||
value: function splitTransaction(transactionHex) { | ||
var inputs = []; | ||
var outputs = []; | ||
var offset = 0; | ||
var transaction = Buffer.from(transactionHex, "hex"); | ||
var version = transaction.slice(offset, offset + 4); | ||
offset += 4; | ||
var varint = this.getVarint(transaction, offset); | ||
var numberInputs = varint[0]; | ||
offset += varint[1]; | ||
const script = transaction.slice(offset, offset + varint[0]); | ||
offset += varint[0]; | ||
const sequence = transaction.slice(offset, offset + 4); | ||
offset += 4; | ||
inputs.push({ prevout, script, sequence }); | ||
} | ||
varint = this.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; | ||
for (var i = 0; i < numberInputs; i++) { | ||
var _prevout = transaction.slice(offset, offset + 36); | ||
offset += 36; | ||
varint = this.getVarint(transaction, offset); | ||
offset += varint[1]; | ||
var _script = transaction.slice(offset, offset + varint[0]); | ||
offset += varint[0]; | ||
var _sequence3 = transaction.slice(offset, offset + 4); | ||
offset += 4; | ||
inputs.push({ prevout: _prevout, script: _script, sequence: _sequence3 }); | ||
} | ||
varint = this.getVarint(transaction, offset); | ||
var numberOutputs = varint[0]; | ||
offset += varint[1]; | ||
const script = transaction.slice(offset, offset + varint[0]); | ||
offset += varint[0]; | ||
outputs.push({ amount, script }); | ||
for (var _i = 0; _i < numberOutputs; _i++) { | ||
var _amount = transaction.slice(offset, offset + 8); | ||
offset += 8; | ||
varint = this.getVarint(transaction, offset); | ||
offset += varint[1]; | ||
var _script2 = transaction.slice(offset, offset + varint[0]); | ||
offset += varint[0]; | ||
outputs.push({ amount: _amount, script: _script2 }); | ||
} | ||
var locktime = transaction.slice(offset, offset + 4); | ||
return { version: version, inputs: inputs, outputs: outputs, locktime: locktime }; | ||
} | ||
let locktime = transaction.slice(offset, offset + 4); | ||
return { version, inputs, outputs, locktime }; | ||
} | ||
/** | ||
@example | ||
const tx1 = btc.splitTransaction("01000000014ea60aeac5252c14291d428915bd7ccd1bfc4af009f4d4dc57ae597ed0420b71010000008a47304402201f36a12c240dbf9e566bc04321050b1984cd6eaf6caee8f02bb0bfec08e3354b022012ee2aeadcbbfd1e92959f57c15c1c6debb757b798451b104665aa3010569b49014104090b15bde569386734abf2a2b99f9ca6a50656627e77de663ca7325702769986cf26cc9dd7fdea0af432c8e2becc867c932e1b9dd742f2a108997c2252e2bdebffffffff0281b72e00000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88aca0860100000000001976a9144533f5fb9b4817f713c48f0bfe96b9f50c476c9b88ac00000000"); | ||
const outputScript = btc.serializeTransactionOutputs(tx1).toString('hex'); | ||
*/ | ||
serializeTransactionOutputs({ outputs }) { | ||
let outputBuffer = Buffer.alloc(0); | ||
if (typeof outputs !== "undefined") { | ||
outputBuffer = Buffer.concat([outputBuffer, this.createVarint(outputs.length)]); | ||
outputs.forEach(output => { | ||
outputBuffer = Buffer.concat([outputBuffer, output.amount, this.createVarint(output.script.length), output.script]); | ||
}); | ||
/** | ||
@example | ||
const tx1 = btc.splitTransaction("01000000014ea60aeac5252c14291d428915bd7ccd1bfc4af009f4d4dc57ae597ed0420b71010000008a47304402201f36a12c240dbf9e566bc04321050b1984cd6eaf6caee8f02bb0bfec08e3354b022012ee2aeadcbbfd1e92959f57c15c1c6debb757b798451b104665aa3010569b49014104090b15bde569386734abf2a2b99f9ca6a50656627e77de663ca7325702769986cf26cc9dd7fdea0af432c8e2becc867c932e1b9dd742f2a108997c2252e2bdebffffffff0281b72e00000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88aca0860100000000001976a9144533f5fb9b4817f713c48f0bfe96b9f50c476c9b88ac00000000"); | ||
const outputScript = btc.serializeTransactionOutputs(tx1).toString('hex'); | ||
*/ | ||
}, { | ||
key: "serializeTransactionOutputs", | ||
value: function serializeTransactionOutputs(_ref) { | ||
var _this7 = this; | ||
var outputs = _ref.outputs; | ||
var outputBuffer = Buffer.alloc(0); | ||
if (typeof outputs !== "undefined") { | ||
outputBuffer = Buffer.concat([outputBuffer, this.createVarint(outputs.length)]); | ||
outputs.forEach(function (output) { | ||
outputBuffer = Buffer.concat([outputBuffer, output.amount, _this7.createVarint(output.script.length), output.script]); | ||
}); | ||
} | ||
return outputBuffer; | ||
} | ||
return outputBuffer; | ||
} | ||
/** | ||
*/ | ||
serializeTransaction(transaction) { | ||
let inputBuffer = Buffer.alloc(0); | ||
transaction.inputs.forEach(input => { | ||
inputBuffer = Buffer.concat([inputBuffer, input.prevout, this.createVarint(input.script.length), input.script, input.sequence]); | ||
}); | ||
/** | ||
*/ | ||
let outputBuffer = this.serializeTransactionOutputs(transaction); | ||
if (typeof transaction.outputs !== "undefined" && typeof transaction.locktime !== "undefined") { | ||
outputBuffer = Buffer.concat([outputBuffer, transaction.locktime]); | ||
}, { | ||
key: "serializeTransaction", | ||
value: function serializeTransaction(transaction) { | ||
var _this8 = this; | ||
var inputBuffer = Buffer.alloc(0); | ||
transaction.inputs.forEach(function (input) { | ||
inputBuffer = Buffer.concat([inputBuffer, input.prevout, _this8.createVarint(input.script.length), input.script, input.sequence]); | ||
}); | ||
var outputBuffer = this.serializeTransactionOutputs(transaction); | ||
if (typeof transaction.outputs !== "undefined" && typeof transaction.locktime !== "undefined") { | ||
outputBuffer = Buffer.concat([outputBuffer, transaction.locktime]); | ||
} | ||
return Buffer.concat([transaction.version, this.createVarint(transaction.inputs.length), inputBuffer, outputBuffer]); | ||
} | ||
return Buffer.concat([transaction.version, this.createVarint(transaction.inputs.length), inputBuffer, outputBuffer]); | ||
} | ||
/** | ||
*/ | ||
/** | ||
*/ | ||
displayTransactionDebug(transaction) { | ||
console.log("version " + transaction.version.toString("hex")); | ||
transaction.inputs.forEach((input, i) => { | ||
const prevout = input.prevout.toString("hex"); | ||
const script = input.script.toString("hex"); | ||
const sequence = input.sequence.toString("hex"); | ||
console.log(`input ${i} prevout ${prevout} script ${script} sequence ${sequence}`); | ||
}); | ||
(transaction.outputs || []).forEach((output, i) => { | ||
const amount = output.amount.toString("hex"); | ||
const script = output.script.toString("hex"); | ||
console.log(`output ${i} amount ${amount} script ${script}`); | ||
}); | ||
if (typeof transaction.locktime !== "undefined") { | ||
console.log("locktime " + transaction.locktime.toString("hex")); | ||
}, { | ||
key: "displayTransactionDebug", | ||
value: function displayTransactionDebug(transaction) { | ||
console.log("version " + transaction.version.toString("hex")); | ||
transaction.inputs.forEach(function (input, i) { | ||
var prevout = input.prevout.toString("hex"); | ||
var script = input.script.toString("hex"); | ||
var sequence = input.sequence.toString("hex"); | ||
console.log("input " + i + " prevout " + prevout + " script " + script + " sequence " + sequence); | ||
}); | ||
(transaction.outputs || []).forEach(function (output, i) { | ||
var amount = output.amount.toString("hex"); | ||
var script = output.script.toString("hex"); | ||
console.log("output " + i + " amount " + amount + " script " + script); | ||
}); | ||
if (typeof transaction.locktime !== "undefined") { | ||
console.log("locktime " + transaction.locktime.toString("hex")); | ||
} | ||
} | ||
} | ||
} | ||
}]); | ||
return Btc; | ||
}(); | ||
exports.default = Btc; /** | ||
*/ | ||
/** | ||
*/ | ||
exports.default = Btc; | ||
/** | ||
@@ -587,0 +725,0 @@ */ |
@@ -6,2 +6,8 @@ "use strict"; | ||
}); | ||
exports.isLedgerDevice = undefined; | ||
var _promise = require("babel-runtime/core-js/promise"); | ||
var _promise2 = _interopRequireDefault(_promise); | ||
exports.defer = defer; | ||
@@ -13,5 +19,9 @@ exports.splitPath = splitPath; | ||
exports.asyncWhile = asyncWhile; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function defer() { | ||
let resolve, reject; | ||
let promise = new Promise(function (success, failure) { | ||
var resolve = void 0, | ||
reject = void 0; | ||
var promise = new _promise2.default(function (success, failure) { | ||
resolve = success; | ||
@@ -21,3 +31,3 @@ reject = failure; | ||
if (!resolve || !reject) throw "defer() error"; // this never happens and is just to make flow happy | ||
return { promise, resolve, reject }; | ||
return { promise: promise, resolve: resolve, reject: reject }; | ||
} | ||
@@ -45,6 +55,6 @@ | ||
function splitPath(path) { | ||
let result = []; | ||
let components = path.split("/"); | ||
components.forEach(element => { | ||
let number = parseInt(element, 10); | ||
var result = []; | ||
var components = path.split("/"); | ||
components.forEach(function (element) { | ||
var number = parseInt(element, 10); | ||
if (isNaN(number)) { | ||
@@ -64,3 +74,7 @@ return; // FIXME shouldn't it throws instead? | ||
function eachSeries(arr, fun) { | ||
return arr.reduce((p, e) => p.then(() => fun(e)), Promise.resolve()); | ||
return arr.reduce(function (p, e) { | ||
return p.then(function () { | ||
return fun(e); | ||
}); | ||
}, _promise2.default.resolve()); | ||
} | ||
@@ -77,7 +91,9 @@ | ||
} | ||
return Promise.resolve().then(() => iterate(0, arr, [])); | ||
return _promise2.default.resolve().then(function () { | ||
return iterate(0, arr, []); | ||
}); | ||
} | ||
function doIf(condition, callback) { | ||
return Promise.resolve().then(() => { | ||
return _promise2.default.resolve().then(function () { | ||
if (condition) { | ||
@@ -94,3 +110,3 @@ return callback(); | ||
} else { | ||
return callback().then(res => { | ||
return callback().then(function (res) { | ||
result.push(res); | ||
@@ -101,6 +117,8 @@ return iterate(result); | ||
} | ||
return Promise.resolve([]).then(iterate); | ||
return _promise2.default.resolve([]).then(iterate); | ||
} | ||
const isLedgerDevice = exports.isLedgerDevice = device => device.vendorId === 0x2581 && device.productId === 0x3b7c || device.vendorId === 0x2c97; | ||
var isLedgerDevice = exports.isLedgerDevice = function isLedgerDevice(device) { | ||
return device.vendorId === 0x2581 && device.productId === 0x3b7c || device.vendorId === 0x2c97; | ||
}; | ||
//# sourceMappingURL=utils.js.map |
{ | ||
"name": "@ledgerhq/hw-app-btc", | ||
"version": "2.1.0", | ||
"version": "2.1.2", | ||
"description": "Ledger Hardware Wallet Bitcoin Application API", | ||
@@ -28,3 +28,3 @@ "keywords": [ | ||
"dependencies": { | ||
"@ledgerhq/hw-transport": "^2.1.0" | ||
"@ledgerhq/hw-transport": "^2.1.2" | ||
}, | ||
@@ -31,0 +31,0 @@ "devDependencies": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
163028
1873