createTX returns tx with expected inputs and outputs
This commit is contained in:
parent
3d12d3b038
commit
2dc0f69d00
2 changed files with 161 additions and 3 deletions
|
@ -164,6 +164,54 @@ var Wallet = function (seed, options) {
|
|||
})
|
||||
}
|
||||
|
||||
function getCandidateOutputs(value){
|
||||
var unspent = []
|
||||
for (var key in me.outputs){
|
||||
var output = me.outputs[key]
|
||||
if(!output.value.spend) unspent.push(output)
|
||||
}
|
||||
|
||||
var sortByValueDesc = unspent.sort(function(o1, o2){
|
||||
return o2.value - o1.value
|
||||
})
|
||||
|
||||
return sortByValueDesc;
|
||||
}
|
||||
|
||||
this.createTx = function(to, value, fixedFee) {
|
||||
var tx = new Transaction()
|
||||
tx.addOutput(to, value)
|
||||
|
||||
var utxo = getCandidateOutputs(value)
|
||||
var totalInValue = 0
|
||||
for(var i=0; i<utxo.length; i++){
|
||||
var output = utxo[i]
|
||||
tx.addInput(output.receive)
|
||||
|
||||
totalInValue += output.value
|
||||
if(totalInValue < value) continue;
|
||||
|
||||
var fee = fixedFee || tx.estimateFee()
|
||||
if(totalInValue < value + fee) continue;
|
||||
|
||||
var change = totalInValue - value - fee
|
||||
var changeAddress = getChangeAddress()
|
||||
if(change > 0) {
|
||||
tx.addOutput(changeAddress, change)
|
||||
// TODO: recalculate fee
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: sign tx
|
||||
return tx
|
||||
}
|
||||
|
||||
function getChangeAddress() {
|
||||
if(me.changeAddresses.length === 0) me.generateChangeAddress()
|
||||
return me.changeAddresses[me.changeAddresses.length - 1]
|
||||
}
|
||||
|
||||
this.getUtxoToPay = function(value) {
|
||||
var h = []
|
||||
for (var out in this.outputs) h.push(this.outputs[out])
|
||||
|
|
116
test/wallet.js
116
test/wallet.js
|
@ -1,6 +1,9 @@
|
|||
var Wallet = require('../src/wallet.js')
|
||||
var HDNode = require('../src/hdwallet.js')
|
||||
var Transaction = require('../src/transaction.js').Transaction
|
||||
var T = require('../src/transaction.js')
|
||||
var Transaction = T.Transaction
|
||||
var TransactionOut = T.TransactionOut
|
||||
var Script = require('../src/script.js')
|
||||
var convert = require('../src/convert.js')
|
||||
var assert = require('assert')
|
||||
var SHA256 = require('crypto-js/sha256')
|
||||
|
@ -158,7 +161,7 @@ describe('Wallet', function() {
|
|||
"hashLittleEndian":"c7b97b432e7b3a8e31d1a4a0fa326c8fb002d19f2da5fc4feaf9c43a2762406a",
|
||||
"outputIndex": 0,
|
||||
"scriptPubKey":"76a91468edf28474ee22f68dfe7e56e76c017c1701b84f88ac",
|
||||
"address" : "1azpkpcfczkduetfbqul4mokqai3m3hmxv",
|
||||
"address" : "1AZpKpcfCzKDUeTFBQUL4MokQai3m3HMXv",
|
||||
"value": 20000
|
||||
}
|
||||
]
|
||||
|
@ -284,7 +287,7 @@ describe('Wallet', function() {
|
|||
|
||||
describe("when tx ins outpoint contains a known txhash:i, the corresponding 'output' gets updated", function(){
|
||||
beforeEach(function(){
|
||||
wallet.addresses = [tx.outs[0].address.toString()] // the address fixtureTx2 is spending from
|
||||
wallet.addresses = [tx.outs[0].address.toString()] // the address fixtureTx2 used as input
|
||||
wallet.processTx(tx)
|
||||
|
||||
tx = Transaction.deserialize(fixtureTx2Hex)
|
||||
|
@ -314,6 +317,113 @@ describe('Wallet', function() {
|
|||
})
|
||||
})
|
||||
|
||||
describe('createTx', function(){
|
||||
var to, value, prevTx;
|
||||
|
||||
beforeEach(function(){
|
||||
to = '15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3'
|
||||
value = 500000
|
||||
|
||||
// generate 2 addresses
|
||||
wallet.generateAddress()
|
||||
wallet.generateAddress()
|
||||
|
||||
// set up 3 utxo
|
||||
utxo = [
|
||||
{
|
||||
"hash": fakeTxHash(1),
|
||||
"outputIndex": 0,
|
||||
"scriptPubKey": scriptPubKeyFor(wallet.addresses[0], 300000),
|
||||
"address" : wallet.addresses[0],
|
||||
"value": 400000 // not enough for value
|
||||
},
|
||||
{
|
||||
"hash": fakeTxHash(2),
|
||||
"outputIndex": 1,
|
||||
"scriptPubKey": scriptPubKeyFor(wallet.addresses[0], 500000),
|
||||
"address" : wallet.addresses[0],
|
||||
"value": 500000 // enough for only value
|
||||
},
|
||||
{
|
||||
"hash": fakeTxHash(3),
|
||||
"outputIndex": 0,
|
||||
"scriptPubKey": scriptPubKeyFor(wallet.addresses[1], 520000),
|
||||
"address" : wallet.addresses[1],
|
||||
"value": 520000 // enough for value and fee
|
||||
}
|
||||
]
|
||||
wallet.setUnspentOutputs(utxo)
|
||||
|
||||
function scriptPubKeyFor(address, value){
|
||||
var txOut = new TransactionOut({
|
||||
value: value,
|
||||
script: Script.createOutputScript(address)
|
||||
})
|
||||
|
||||
return txOut.scriptPubKey()
|
||||
}
|
||||
})
|
||||
|
||||
function fakeTxHash(i) {
|
||||
return "txtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtx" + i
|
||||
}
|
||||
|
||||
describe('choosing utxo', function(){
|
||||
it('calculates fees', function(){
|
||||
var tx = wallet.createTx(to, value)
|
||||
|
||||
assert.equal(tx.ins.length, 1)
|
||||
assert.deepEqual(tx.ins[0].outpoint, { hash: fakeTxHash(3), index: 0 })
|
||||
})
|
||||
|
||||
it('allows fee to be specified', function(){
|
||||
var fee = 30000
|
||||
var tx = wallet.createTx(to, value, fee)
|
||||
|
||||
assert.equal(tx.ins.length, 2)
|
||||
assert.deepEqual(tx.ins[0].outpoint, { hash: fakeTxHash(3), index: 0 })
|
||||
assert.deepEqual(tx.ins[1].outpoint, { hash: fakeTxHash(2), index: 1 })
|
||||
})
|
||||
})
|
||||
|
||||
describe('transaction outputs', function(){
|
||||
it('includes the specified address and amount', function(){
|
||||
var tx = wallet.createTx(to, value)
|
||||
|
||||
assert.equal(tx.outs.length, 1)
|
||||
var out = tx.outs[0]
|
||||
assert.equal(out.address, to)
|
||||
assert.equal(out.value, value)
|
||||
})
|
||||
|
||||
describe('change', function(){
|
||||
it('uses the last change address if there is any', function(){
|
||||
var fee = 15000
|
||||
wallet.generateChangeAddress()
|
||||
wallet.generateChangeAddress()
|
||||
var tx = wallet.createTx(to, value, fee)
|
||||
|
||||
assert.equal(tx.outs.length, 2)
|
||||
var out = tx.outs[1]
|
||||
assert.equal(out.address, wallet.changeAddresses[1])
|
||||
assert.equal(out.value, 5000)
|
||||
})
|
||||
|
||||
it('generates a change address if there is not any', function(){
|
||||
var fee = 15000
|
||||
assert.equal(wallet.changeAddresses.length, 0)
|
||||
|
||||
var tx = wallet.createTx(to, value, fee)
|
||||
|
||||
assert.equal(wallet.changeAddresses.length, 1)
|
||||
var out = tx.outs[1]
|
||||
assert.equal(out.address, wallet.changeAddresses[0])
|
||||
assert.equal(out.value, 5000)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function assertEqual(obj1, obj2){
|
||||
assert.equal(obj1.toString(), obj2.toString())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue