docco documentation
This commit is contained in:
parent
0c8a582522
commit
ec2299362c
|
@ -17,7 +17,7 @@ module.exports = function(grunt) {
|
|||
stderr: true
|
||||
},
|
||||
command: grunt.option('target') === 'dev' ?
|
||||
'node ./browser/build.js -a -d ' : 'node ./browser/build.js -a'
|
||||
'node ./browser/build.js -a -d; docco lib/* ' : 'node ./browser/build.js -a'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -1,80 +1,51 @@
|
|||
|
||||
/*
|
||||
var tx = (new TransactionBuilder(opts))
|
||||
.setUnspent(utxos)
|
||||
.setOutputs(outs)
|
||||
.sign(keys)
|
||||
.build();
|
||||
|
||||
|
||||
var builder = (new TransactionBuilder(opts))
|
||||
.setUnspent(spent)
|
||||
.setOutputs(outs);
|
||||
|
||||
// Uncomplete tx (no signed or partially signed)
|
||||
var tx = builder.build();
|
||||
|
||||
..later..
|
||||
|
||||
builder.sign(keys);
|
||||
while ( builder.isFullySigned() ) {
|
||||
|
||||
... get new keys ...
|
||||
|
||||
builder.sign(keys);
|
||||
}
|
||||
|
||||
var tx = builder.build();
|
||||
broadcast(tx.serialize());
|
||||
|
||||
To get selected unspent outputs:
|
||||
var selectedUnspent = builder.getSelectedUnspent();
|
||||
|
||||
|
||||
@unspent
|
||||
* unspent outputs array (UTXO), using the following format:
|
||||
* [{
|
||||
* address: "mqSjTad2TKbPcKQ3Jq4kgCkKatyN44UMgZ",
|
||||
* hash: "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1",
|
||||
* scriptPubKey: "76a9146ce4e1163eb18939b1440c42844d5f0261c0338288ac",
|
||||
* vout: 1,
|
||||
* amount: 0.01,
|
||||
* confirmations: 3
|
||||
* }, ...
|
||||
* ]
|
||||
* This is compatible con insight's utxo API.
|
||||
* That amount is in BTCs (as returned in insight and bitcoind).
|
||||
* amountSat (instead of amount) can be given to provide amount in satochis.
|
||||
*
|
||||
* @outs
|
||||
* an array of [{
|
||||
* address: xx,
|
||||
* amount:0.001
|
||||
* },...]
|
||||
*
|
||||
* @keys
|
||||
* an array of strings representing private keys to sign the
|
||||
* transaction in WIF private key format OR WalletKey objects
|
||||
*
|
||||
* @opts
|
||||
* {
|
||||
* remainderOut: null,
|
||||
* fee: 0.001,
|
||||
* lockTime: null,
|
||||
* spendUnconfirmed: false,
|
||||
* signhash: SIGHASH_ALL
|
||||
* }
|
||||
* Amounts are in BTC. instead of fee and amount; feeSat and amountSat can be given,
|
||||
* repectively, to provide amounts in satoshis.
|
||||
*
|
||||
* If no remainderOut is given, and there are remainder coins, the
|
||||
* first IN out will be used to return the coins. remainderOut has the form:
|
||||
* remainderOut = { address: 1xxxxx}
|
||||
* or
|
||||
* remainderOut = { pubkeys: ['hex1','hex2',...} for multisig
|
||||
*
|
||||
*
|
||||
*/
|
||||
// Creates a bitcore Transaction object
|
||||
//
|
||||
//
|
||||
// Synopsis
|
||||
// --------
|
||||
// ```
|
||||
// var tx = (new TransactionBuilder(opts))
|
||||
// .setUnspent(utxos)
|
||||
// .setOutputs(outs)
|
||||
// .sign(keys)
|
||||
// .build();
|
||||
//
|
||||
//
|
||||
// var builder = (new TransactionBuilder(opts))
|
||||
// .setUnspent(spent)
|
||||
// .setOutputs(outs);
|
||||
//
|
||||
// // Uncomplete tx (no signed or partially signed)
|
||||
// var tx = builder.build();
|
||||
//
|
||||
// ..later..
|
||||
//
|
||||
// builder.sign(keys);
|
||||
// while ( builder.isFullySigned() ) {
|
||||
//
|
||||
// ... get new keys ...
|
||||
//
|
||||
// builder.sign(keys);
|
||||
// }
|
||||
//
|
||||
// var tx = builder.build();
|
||||
// broadcast(tx.serialize());
|
||||
//
|
||||
// //Searialize it and pass it around...
|
||||
// var string = JSON.serialize(builder.toObj());
|
||||
// // then...
|
||||
// var builder = TransactionBuilder.fromObj(JSON.parse(str);
|
||||
// builder.sign(keys);
|
||||
// // Also
|
||||
// var builder2 = TransactionBuilder.fromObj(JSON.parse(str2);
|
||||
// builder2.merge(builder); // Will merge signatures for p2sh mulsig txs.
|
||||
//
|
||||
//
|
||||
// ```
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
'use strict';
|
||||
|
@ -94,6 +65,35 @@ var log = imports.log || require('../util/log');
|
|||
var Transaction = imports.Transaction || require('./Transaction');
|
||||
var FEE_PER_1000B_SAT = parseInt(0.0001 * util.COIN);
|
||||
|
||||
// Methods
|
||||
// -------
|
||||
//
|
||||
// TransactionBuilder
|
||||
// ------------------
|
||||
// Creates a TransactionBuilder instance
|
||||
// `opts`
|
||||
// ```
|
||||
// {
|
||||
// remainderOut: null,
|
||||
// fee: 0.001,
|
||||
// lockTime: null,
|
||||
// spendUnconfirmed: false,
|
||||
// signhash: SIGHASH_ALL
|
||||
// }
|
||||
// ```
|
||||
// Amounts are in BTC. instead of fee and amount; feeSat and amountSat can be given,
|
||||
// repectively, to provide amounts in satoshis.
|
||||
//
|
||||
// If no remainderOut is given, and there are remainder coins, the
|
||||
// first IN out will be used to return the coins. remainderOut has the form:
|
||||
// ```
|
||||
// remainderOut = { address: 1xxxxx}
|
||||
// ```
|
||||
// or
|
||||
// ```
|
||||
// remainderOut = { pubkeys: ['hex1','hex2',...} for multisig
|
||||
// ```
|
||||
|
||||
function TransactionBuilder(opts) {
|
||||
opts = opts || {};
|
||||
this.lockTime = opts.lockTime || 0;
|
||||
|
@ -179,8 +179,27 @@ TransactionBuilder.infoForP2sh = function(opts, networkName) {
|
|||
};
|
||||
};
|
||||
|
||||
TransactionBuilder.prototype.setUnspent = function(utxos) {
|
||||
this.utxos = utxos;
|
||||
// setUnspent
|
||||
// ----------
|
||||
// Sets the `unspent` available for the transaction. Some (or all)
|
||||
// of them to fullfil the transaction's outputs and fee.
|
||||
// The expected format is:
|
||||
// ```
|
||||
// [{
|
||||
// address: "mqSjTad2TKbPcKQ3Jq4kgCkKatyN44UMgZ",
|
||||
// hash: "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1",
|
||||
// scriptPubKey: "76a9146ce4e1163eb18939b1440c42844d5f0261c0338288ac",
|
||||
// vout: 1,
|
||||
// amount: 0.01,
|
||||
// confirmations: 3
|
||||
// }, ...
|
||||
// ]
|
||||
// ```
|
||||
// This is compatible con insight's utxo API.
|
||||
// That amount is in BTCs (as returned in insight and bitcoind).
|
||||
// amountSat (instead of amount) can be given to provide amount in satochis.
|
||||
TransactionBuilder.prototype.setUnspent = function(unspent) {
|
||||
this.utxos = unspent;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
@ -209,6 +228,12 @@ TransactionBuilder.prototype._setInputMap = function() {
|
|||
return this;
|
||||
};
|
||||
|
||||
|
||||
// getSelectedUnspent
|
||||
// ------------------
|
||||
//
|
||||
// Returns the selected unspent outputs, to be used in the transaction.
|
||||
|
||||
TransactionBuilder.prototype.getSelectedUnspent = function() {
|
||||
return this.selectedUtxos;
|
||||
};
|
||||
|
@ -312,12 +337,12 @@ TransactionBuilder.prototype._setRemainder = function(txobj, remainderIndex) {
|
|||
typeof this.valueOutSat === 'undefined')
|
||||
throw new Error('valueInSat / valueOutSat undefined');
|
||||
|
||||
// add remainder (without modifying outs[])
|
||||
/* add remainder (without modifying outs[]) */
|
||||
var remainderSat = this.valueInSat.sub(this.valueOutSat).sub(this.feeSat);
|
||||
var l =txobj.outs.length;
|
||||
this.remainderSat = bignum(0);
|
||||
|
||||
//remove old remainder?
|
||||
/*remove old remainder? */
|
||||
if (l > remainderIndex) {
|
||||
txobj.outs.pop();
|
||||
}
|
||||
|
@ -339,10 +364,10 @@ TransactionBuilder.prototype._setRemainder = function(txobj, remainderIndex) {
|
|||
|
||||
TransactionBuilder.prototype._setFeeAndRemainder = function(txobj) {
|
||||
|
||||
//starting size estimation
|
||||
/* starting size estimation */
|
||||
var size = 500, maxSizeK, remainderIndex = txobj.outs.length;
|
||||
do {
|
||||
// based on https://en.bitcoin.it/wiki/Transaction_fees
|
||||
/* based on https://en.bitcoin.it/wiki/Transaction_fees */
|
||||
maxSizeK = parseInt(size / 1000) + 1;
|
||||
|
||||
var feeSat = this.givenFeeSat ?
|
||||
|
@ -361,6 +386,21 @@ TransactionBuilder.prototype._setFeeAndRemainder = function(txobj) {
|
|||
return this;
|
||||
};
|
||||
|
||||
// setOutputs
|
||||
// ----------
|
||||
// Sets the outputs for the transaction. Format is:
|
||||
// ```
|
||||
// an array of [{
|
||||
// address: xx,
|
||||
// amount:0.001
|
||||
// },...]
|
||||
// ```
|
||||
//
|
||||
// Note that only some of this outputs will be selected
|
||||
// to create the transaction. The selected ones can be checked
|
||||
// after calling `setOutputs`, with `.getSelectedUnspent`
|
||||
//
|
||||
|
||||
TransactionBuilder.prototype.setOutputs = function(outs) {
|
||||
var valueOutSat = bignum(0);
|
||||
|
||||
|
@ -394,7 +434,7 @@ TransactionBuilder.prototype.setOutputs = function(outs) {
|
|||
};
|
||||
|
||||
TransactionBuilder._mapKeys = function(keys) {
|
||||
//prepare keys
|
||||
/* prepare keys */
|
||||
var walletKeyMap = {};
|
||||
var l = keys.length;
|
||||
var wk;
|
||||
|
@ -505,15 +545,15 @@ TransactionBuilder.prototype._signPubKeyHash = function(walletKeyMap, input, txS
|
|||
return {inputFullySigned: true, signaturesAdded: 1, script: scriptSig.getBuffer()};
|
||||
};
|
||||
|
||||
// FOR TESTING
|
||||
// var _dumpChunks = function (scriptSig, label) {
|
||||
// console.log('## DUMP: ' + label + ' ##');
|
||||
// for(var i=0; i<scriptSig.chunks.length; i++) {
|
||||
// console.log('\tCHUNK ', i, Buffer.isBuffer(scriptSig.chunks[i])
|
||||
// ?scriptSig.chunks[i].toString('hex'):scriptSig.chunks[i] );
|
||||
// }
|
||||
// };
|
||||
|
||||
/* FOR TESTING
|
||||
var _dumpChunks = function (scriptSig, label) {
|
||||
console.log('## DUMP: ' + label + ' ##');
|
||||
for(var i=0; i<scriptSig.chunks.length; i++) {
|
||||
console.log('\tCHUNK ', i, Buffer.isBuffer(scriptSig.chunks[i])
|
||||
?scriptSig.chunks[i].toString('hex'):scriptSig.chunks[i] );
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
TransactionBuilder.prototype._chunkSignedWithKey = function(scriptSig, txSigHash, publicKey) {
|
||||
var ret;
|
||||
|
@ -599,7 +639,6 @@ TransactionBuilder.prototype._signMultiSig = function(walletKeyMap, input, txSig
|
|||
var signaturesAdded = 0;
|
||||
|
||||
for(var j=0; j<l && scriptSig.countSignatures() < nreq ; j++) {
|
||||
//console.log('[TransactionBuilder.js] pubkey [j]',j, pubkeys[j].toString('hex')); //TODO
|
||||
var wk = this._findWalletKey(walletKeyMap, {pubKeyBuf: pubkeys[j]});
|
||||
if (!wk) continue;
|
||||
|
||||
|
@ -609,8 +648,6 @@ TransactionBuilder.prototype._signMultiSig = function(walletKeyMap, input, txSig
|
|||
signaturesAdded++;
|
||||
}
|
||||
}
|
||||
if (scriptSig.countSignatures() === nreq) {
|
||||
}
|
||||
|
||||
var ret = {
|
||||
inputFullySigned: scriptSig.countSignatures() === nreq,
|
||||
|
@ -621,7 +658,6 @@ TransactionBuilder.prototype._signMultiSig = function(walletKeyMap, input, txSig
|
|||
};
|
||||
|
||||
var fnToSign = {};
|
||||
|
||||
TransactionBuilder.prototype._scriptIsAppended = function(script, scriptToAddBuf) {
|
||||
var len = script.chunks.length;
|
||||
|
||||
|
@ -647,7 +683,7 @@ TransactionBuilder.prototype._addScript = function(scriptBuf, scriptToAddBuf) {
|
|||
|
||||
TransactionBuilder.prototype._getInputForP2sh = function(script, index) {
|
||||
var scriptType = script.classify();
|
||||
// pubKeyHash is needed for TX_PUBKEYHASH and TX_PUBKEY to retrieve the keys.
|
||||
/* pubKeyHash is needed for TX_PUBKEYHASH and TX_PUBKEY to retrieve the keys. */
|
||||
var pubKeyHash;
|
||||
switch(scriptType) {
|
||||
case Script.TX_PUBKEYHASH:
|
||||
|
@ -705,6 +741,20 @@ fnToSign[Script.TX_PUBKEY] = TransactionBuilder.prototype._signPubKey;
|
|||
fnToSign[Script.TX_MULTISIG] = TransactionBuilder.prototype._signMultiSig;
|
||||
fnToSign[Script.TX_SCRIPTHASH] = TransactionBuilder.prototype._signScriptHash;
|
||||
|
||||
// sign
|
||||
// ----
|
||||
// Signs a transaction.
|
||||
// `keys`: an array of strings representing private keys to sign the
|
||||
// transaction in WIF private key format OR bitcore's `WalletKey` objects
|
||||
//
|
||||
// If multiple keys are given, each will be tested against the transaction's
|
||||
// scriptPubKeys. Only the valid private keys will be used to sign.
|
||||
// This method is fully compatible with *multisig* transactions.
|
||||
//
|
||||
// `.isFullySigned` can be queried to check is the transactions have all the needed
|
||||
// signatures.
|
||||
//
|
||||
//
|
||||
TransactionBuilder.prototype.sign = function(keys) {
|
||||
this._checkTx();
|
||||
var tx = this.tx,
|
||||
|
@ -728,13 +778,24 @@ TransactionBuilder.prototype.sign = function(keys) {
|
|||
return this;
|
||||
};
|
||||
|
||||
// [ { address:scriptHex }]
|
||||
// setHashToScriptMap
|
||||
// ------------------
|
||||
// Needed for setup Address to Script maps
|
||||
// for p2sh transactions. See `.infoForP2sh`
|
||||
// for generate the input for this call.
|
||||
//
|
||||
TransactionBuilder.prototype.setHashToScriptMap = function(hashToScriptMap) {
|
||||
this.hashToScriptMap= hashToScriptMap;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
// isFullySigned
|
||||
// -------------
|
||||
// Checks if the transaction have all the necesary signatures.
|
||||
// Also, `.signaturesAdded` and `.inputsSigned` can be queried
|
||||
// for more information about the transaction signature status.
|
||||
//
|
||||
TransactionBuilder.prototype.isFullySigned = function() {
|
||||
return this.inputsSigned === this.tx.ins.length;
|
||||
};
|
||||
|
@ -744,7 +805,13 @@ TransactionBuilder.prototype.build = function() {
|
|||
return this.tx;
|
||||
};
|
||||
|
||||
|
||||
// toObj
|
||||
// -----
|
||||
// Returns a plain Javascript object that contains
|
||||
// the full status of the TransactionBuilder instance,
|
||||
// suitable for serialization, storage and transmition.
|
||||
// See `.fromObj`
|
||||
//
|
||||
TransactionBuilder.prototype.toObj = function() {
|
||||
var data = {
|
||||
valueInSat : this.valueInSat.toString(),
|
||||
|
@ -758,7 +825,6 @@ TransactionBuilder.prototype.toObj = function() {
|
|||
inputsSigned : this.inputsSigned,
|
||||
signaturesAdded : this.signaturesAdded,
|
||||
|
||||
//opts :
|
||||
signhash : this.signhash,
|
||||
spendUnconfirmed : this.spendUnconfirmed,
|
||||
};
|
||||
|
@ -768,6 +834,11 @@ TransactionBuilder.prototype.toObj = function() {
|
|||
return data;
|
||||
};
|
||||
|
||||
// fromObj
|
||||
// -------
|
||||
// Returns a TransactionBuilder instance given
|
||||
// a plain Javascript object created previously
|
||||
// with `.toObj`. See `.toObj`.
|
||||
|
||||
TransactionBuilder.fromObj = function(data) {
|
||||
var b = new TransactionBuilder();
|
||||
|
@ -950,6 +1021,11 @@ TransactionBuilder.prototype._mergeTx = function(tx, ignoreConflictingSignatures
|
|||
}
|
||||
};
|
||||
|
||||
// merge
|
||||
// -----
|
||||
// Merge to TransactionBuilder objects, merging inputs signatures.
|
||||
// This function supports multisig p2sh inputs.
|
||||
|
||||
TransactionBuilder.prototype.merge = function(b) {
|
||||
this._checkMergeability(b);
|
||||
|
||||
|
|
Loading…
Reference in New Issue