add tests and refactor wallet.processTx

This commit is contained in:
Wei Lu 2014-03-22 21:10:56 +08:00
parent 83381186d1
commit dbb5681366
3 changed files with 117 additions and 17 deletions

View File

@ -135,31 +135,35 @@ var Wallet = function (seed, options) {
return value == undefined return value == undefined
} }
// Processes a transaction object this.processTx = function(tx) {
// If "verified" is true, then we trust the transaction as "final"
this.processTx = function(tx, verified) {
var txhash = convert.bytesToHex(tx.getHash()) var txhash = convert.bytesToHex(tx.getHash())
for (var i = 0; i < tx.outs.length; i++) {
if (this.addresses.indexOf(tx.outs[i].address.toString()) >= 0) { tx.outs.forEach(function(txOut, i){
me.outputs[txhash+':'+i] = { var address = txOut.address.toString()
output: txhash+':'+i, if (isMyAddress(address)) {
value: tx.outs[i].value, var output = txhash+':'+i
address: tx.outs[i].address.toString(), me.outputs[output] = {
timestamp: new Date().getTime() / 1000, output: output,
pending: true value: txOut.value,
address: address,
scriptPubKey: convert.bytesToHex(txOut.script.buffer) //TODO: txOut.scriptPubKey()
// timestamp: new Date().getTime() / 1000,
// pending: true
} }
} }
} })
for (var i = 0; i < tx.ins.length; i++) {
var op = tx.ins[i].outpoint tx.ins.forEach(function(txIn, i){
var op = txIn.outpoint
var o = me.outputs[op.hash+':'+op.index] var o = me.outputs[op.hash+':'+op.index]
if (o) { if (o) {
o.spend = txhash+':'+i o.spend = txhash+':'+i
o.spendpending = true // o.spendpending = true
o.timestamp = new Date().getTime() / 1000 // o.timestamp = new Date().getTime() / 1000
} }
} })
} }
// Processes an output from an external source of the form // Processes an output from an external source of the form
// { output: txhash:index, value: integer, address: address } // { output: txhash:index, value: integer, address: address }
// Excellent compatibility with SX and pybitcointools // Excellent compatibility with SX and pybitcointools
@ -276,6 +280,18 @@ var Wallet = function (seed, options) {
throw new Error('Unknown address. Make sure the address is from the keychain and has been generated.') throw new Error('Unknown address. Make sure the address is from the keychain and has been generated.')
} }
} }
function isReceiveAddress(address){
return me.addresses.indexOf(address) > -1
}
function isChangeAddress(address){
return me.changeAddresses.indexOf(address) > -1
}
function isMyAddress(address) {
return isReceiveAddress(address) || isChangeAddress(address)
}
}; };
module.exports = Wallet; module.exports = Wallet;

4
test/fixtures/mainnet_tx.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"prevTx": "0100000001e0214ebebb0fd3414d3fdc0dbf3b0f4b247a296cafc984558622c3041b0fcc9b010000008b48304502206becda98cecf7a545d1a640221438ff8912d9b505ede67e0138485111099f696022100ccd616072501310acba10feb97cecc918e21c8e92760cd35144efec7622938f30141040cd2d2ce17a1e9b2b3b2cb294d40eecf305a25b7e7bfdafae6bb2639f4ee399b3637706c3d377ec4ab781355add443ae864b134c5e523001c442186ea60f0eb8ffffffff03a0860100000000001976a91400ea3576c8fcb0bc8392f10e23a3425ae24efea888ac40420f00000000001976a91477890e8ec967c5fd4316c489d171fd80cf86997188acf07cd210000000001976a9146fb93c557ee62b109370fd9003e456917401cbfa88ac00000000",
"tx": "0100000001576bc3c3285dbdccd8c3cbd8c03e10d7f77a5c839c744f34c3eb00511059b80c000000006b483045022100a82a31607b837c1ae510ae3338d1d3c7cbd57c15e322ab6e5dc927d49bffa66302205f0db6c90f1fae3c8db4ebfa753d7da1b2343d653ce0331aa94ed375e6ba366c0121020497bfc87c3e97e801414fed6a0db4b8c2e01c46e2cf9dff59b406b52224a76bffffffff02409c0000000000001976a9143443bc45c560866cfeabf1d52f50a6ed358c69f288ac50c30000000000001976a91477890e8ec967c5fd4316c489d171fd80cf86997188ac00000000"
}

View File

@ -1,10 +1,15 @@
var Wallet = require('../src/wallet.js') var Wallet = require('../src/wallet.js')
var HDNode = require('../src/hdwallet.js') var HDNode = require('../src/hdwallet.js')
var Transaction = require('../src/transaction.js').Transaction
var convert = require('../src/convert.js') var convert = require('../src/convert.js')
var assert = require('assert') var assert = require('assert')
var SHA256 = require('crypto-js/sha256') var SHA256 = require('crypto-js/sha256')
var Crypto = require('crypto-js') var Crypto = require('crypto-js')
var fixtureTxes = require('./fixtures/mainnet_tx')
var fixtureTx1Hex = fixtureTxes.prevTx
var fixtureTx2Hex = fixtureTxes.tx
describe('Wallet', function() { describe('Wallet', function() {
var seed, wallet; var seed, wallet;
beforeEach(function(){ beforeEach(function(){
@ -234,6 +239,81 @@ describe('Wallet', function() {
}) })
}) })
describe('processTx', function(){
var tx;
beforeEach(function(){
tx = Transaction.deserialize(fixtureTx1Hex)
})
describe("when tx outs contains an address owned by the wallet, an 'output' gets added to wallet.outputs", function(){
it("works for receive address", function(){
var totalOuts = outputCount()
wallet.addresses = [tx.outs[0].address.toString()]
wallet.processTx(tx)
assert.equal(outputCount(), totalOuts + 1)
verifyOutputAdded(0)
})
it("works for change address", function(){
var totalOuts = outputCount()
wallet.changeAddresses = [tx.outs[1].address.toString()]
wallet.processTx(tx)
assert.equal(outputCount(), totalOuts + 1)
verifyOutputAdded(1)
})
function outputCount(){
return Object.keys(wallet.outputs).length
}
function verifyOutputAdded(index) {
var txOut = tx.outs[index]
var key = convert.bytesToHex(tx.getHash()) + ":" + index
var output = wallet.outputs[key]
assert.equal(output.output, key)
assert.equal(output.value, txOut.value)
assert.equal(output.address, txOut.address)
assert.equal(output.scriptPubKey, convert.bytesToHex(txOut.script.buffer))
}
})
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.processTx(tx)
tx = Transaction.deserialize(fixtureTx2Hex)
})
it("does not add to wallet.outputs", function(){
var outputs = wallet.outputs
wallet.processTx(tx)
assert.deepEqual(wallet.outputs, outputs)
})
it("sets spend with the transaction hash and input index", function(){
wallet.processTx(tx)
var txIn = tx.ins[0]
var key = txIn.outpoint.hash + ":" + txIn.outpoint.index
var output = wallet.outputs[key]
assert.equal(output.spend, convert.bytesToHex(tx.getHash()) + ':' + 0)
})
})
it("does nothing when none of the involved addresses belong to the wallet", function(){
var outputs = wallet.outputs
wallet.processTx(tx)
assert.deepEqual(wallet.outputs, outputs)
})
})
function assertEqual(obj1, obj2){ function assertEqual(obj1, obj2){
assert.equal(obj1.toString(), obj2.toString()) assert.equal(obj1.toString(), obj2.toString())
} }