selectUnspent function and tests
This commit is contained in:
parent
303d5731c0
commit
ada92746b7
|
@ -679,6 +679,56 @@ Transaction.prototype.parse = function (parser) {
|
||||||
this.calcHash();
|
this.calcHash();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* selectUnspent
|
||||||
|
*
|
||||||
|
* Selects some unspend outputs for later usage in tx inputs
|
||||||
|
*
|
||||||
|
* @unspentArray: unspent array (UTXO) avaible on the form:
|
||||||
|
* [{
|
||||||
|
* address: "mqSjTad2TKbPcKQ3Jq4kgCkKatyN44UMgZ",
|
||||||
|
* hash: "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1",
|
||||||
|
* scriptPubKey: "76a9146ce4e1163eb18939b1440c42844d5f0261c0338288ac",
|
||||||
|
* vout: 1,
|
||||||
|
* amount: 0.01,
|
||||||
|
* }, [...]
|
||||||
|
* ]
|
||||||
|
* This is compatible con insight's /utxo API.
|
||||||
|
* NOTE that amount is in BTCs! (as returned in insight and bitcoind.
|
||||||
|
*
|
||||||
|
* @totalNeededAmount: output transaction amount in BTC, including fee
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Return the selected outputs or null if there are not enough funds.
|
||||||
|
* It does not check for confirmations. The unspendArray should be filtered.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Transaction.selectUnspent = function (unspentArray, totalNeededAmount) {
|
||||||
|
|
||||||
|
// TODO we could randomize or select the selection
|
||||||
|
|
||||||
|
var selected = [];
|
||||||
|
var l = unspentArray.length;
|
||||||
|
var totalSat = bignum(0);
|
||||||
|
var totalNeededAmountSat = bignum(totalNeededAmount * util.COIN);
|
||||||
|
var fullfill = false;
|
||||||
|
|
||||||
|
for(var i = 0; i<l; i++) {
|
||||||
|
var u = unspentArray[i];
|
||||||
|
var sat = bignum(u.amount * util.COIN);
|
||||||
|
totalSat = totalSat.add(sat);
|
||||||
|
selected.push(u);
|
||||||
|
if(totalSat.cmp(totalNeededAmountSat) >= 0) {
|
||||||
|
fullfill = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!fullfill) return [];
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var TransactionInputsCache = exports.TransactionInputsCache =
|
var TransactionInputsCache = exports.TransactionInputsCache =
|
||||||
function TransactionInputsCache(tx)
|
function TransactionInputsCache(tx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"address": "mqSjTad2TKbPcKQ3Jq4kgCkKatyN44UMgZ",
|
||||||
|
"txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1",
|
||||||
|
"scriptPubKey": "76a9146ce4e1163eb18939b1440c42844d5f0261c0338288ac",
|
||||||
|
"vout": 1,
|
||||||
|
"amount": 0.01
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "mqSjTad2TKbPcKQ3Jq4kgCkKatyN44UMgZ",
|
||||||
|
"txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc2",
|
||||||
|
"scriptPubKey": "76a9146ce4e1163eb18939b1440c42844d5f0261c0338288ad",
|
||||||
|
"vout": 1,
|
||||||
|
"amount": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "mqSjTad2TKbPcKQ3Jq4kgCkKatyN44UMgZ",
|
||||||
|
"txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc3",
|
||||||
|
"scriptPubKey": "76a9146ce4e1163eb18939b1440c42844d5f0261c0338288ae",
|
||||||
|
"vout": 3,
|
||||||
|
"amount": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
|
@ -25,11 +25,40 @@ describe('Transaction', function() {
|
||||||
should.exist(In);
|
should.exist(In);
|
||||||
should.exist(Out);
|
should.exist(Out);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should be able to create instance', function() {
|
it('should be able to create instance', function() {
|
||||||
var t = new Transaction();
|
var t = new Transaction();
|
||||||
should.exist(t);
|
should.exist(t);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should be able to select unspents', function() {
|
||||||
|
var u = Transaction.selectUnspent(testdata.dataUnspends,1.0);
|
||||||
|
u.length.should.equal(3);
|
||||||
|
u = Transaction.selectUnspent(testdata.dataUnspends,0.5);
|
||||||
|
u.length.should.equal(3);
|
||||||
|
u = Transaction.selectUnspent(testdata.dataUnspends,0.1);
|
||||||
|
u.length.should.equal(2);
|
||||||
|
u = Transaction.selectUnspent(testdata.dataUnspends,0.05);
|
||||||
|
u.length.should.equal(2);
|
||||||
|
u = Transaction.selectUnspent(testdata.dataUnspends,0.015);
|
||||||
|
u.length.should.equal(2);
|
||||||
|
u = Transaction.selectUnspent(testdata.dataUnspends,0.01);
|
||||||
|
u.length.should.equal(1);
|
||||||
|
should.exist(u[0].amount);
|
||||||
|
should.exist(u[0].txid);
|
||||||
|
should.exist(u[0].scriptPubKey);
|
||||||
|
should.exist(u[0].vout);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it.skip('should be able to create instance thru #create', function() {
|
||||||
|
var t = Transaction.create({
|
||||||
|
});
|
||||||
|
should.exist(t);
|
||||||
|
});
|
||||||
|
|
||||||
// Read tests from test/data/tx_valid.json
|
// Read tests from test/data/tx_valid.json
|
||||||
// Format is an array of arrays
|
// Format is an array of arrays
|
||||||
// Inner arrays are either [ "comment" ]
|
// Inner arrays are either [ "comment" ]
|
||||||
|
|
|
@ -7,6 +7,8 @@ var dataTxValid = JSON.parse(fs.readFileSync('test/data/tx_valid.json'));
|
||||||
var dataTxInvalid = JSON.parse(fs.readFileSync('test/data/tx_invalid.json'));
|
var dataTxInvalid = JSON.parse(fs.readFileSync('test/data/tx_invalid.json'));
|
||||||
var dataScriptValid = JSON.parse(fs.readFileSync('test/data/script_valid.json'));
|
var dataScriptValid = JSON.parse(fs.readFileSync('test/data/script_valid.json'));
|
||||||
var dataScriptInvalid = JSON.parse(fs.readFileSync('test/data/script_invalid.json'));
|
var dataScriptInvalid = JSON.parse(fs.readFileSync('test/data/script_invalid.json'));
|
||||||
|
var dataUnspends = JSON.parse(fs.readFileSync('test/data/unspends.json'));
|
||||||
|
|
||||||
|
|
||||||
module.exports.dataValid = dataValid;
|
module.exports.dataValid = dataValid;
|
||||||
module.exports.dataInvalid = dataInvalid;
|
module.exports.dataInvalid = dataInvalid;
|
||||||
|
@ -16,3 +18,4 @@ module.exports.dataTxInvalid = dataTxInvalid;
|
||||||
module.exports.dataScriptValid = dataScriptValid;
|
module.exports.dataScriptValid = dataScriptValid;
|
||||||
module.exports.dataScriptInvalid = dataScriptInvalid;
|
module.exports.dataScriptInvalid = dataScriptInvalid;
|
||||||
module.exports.dataScriptAll = dataScriptValid.concat(dataScriptInvalid);
|
module.exports.dataScriptAll = dataScriptValid.concat(dataScriptInvalid);
|
||||||
|
module.exports.dataUnspends = dataUnspends;
|
||||||
|
|
Loading…
Reference in New Issue