From d618aa9822fbdb1bb887e6f62d44e383518fd5be Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Thu, 14 Aug 2014 11:00:18 +1000
Subject: [PATCH 01/11] Wallet: deprecates newMasterKey

---
 src/wallet.js | 50 +++++++++++++++++++++++++++-----------------------
 1 file changed, 27 insertions(+), 23 deletions(-)

diff --git a/src/wallet.js b/src/wallet.js
index c056c95..dd492ba 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -7,14 +7,18 @@ var HDNode = require('./hdnode')
 var Transaction = require('./transaction')
 
 function Wallet(seed, network) {
+  seed = seed || crypto.randomBytes(32)
   network = network || networks.bitcoin
 
   // Stored in a closure to make accidental serialization less likely
-  var masterkey = null
+  var masterkey = HDNode.fromSeedBuffer(seed, network)
   var me = this
-  var accountZero = null
-  var internalAccount = null
-  var externalAccount = null
+
+  // HD first-level child derivation method should be hardened
+  // See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254
+  var accountZero = masterkey.deriveHardened(0)
+  var externalAccount = accountZero.derive(0)
+  var internalAccount = accountZero.derive(1)
 
   // Addresses
   this.addresses = []
@@ -23,25 +27,6 @@ function Wallet(seed, network) {
   // Transaction output data
   this.outputs = {}
 
-  // Make a new master key
-  this.newMasterKey = function(seed) {
-    seed = seed || crypto.randomBytes(32)
-    masterkey = HDNode.fromSeedBuffer(seed, network)
-
-    // HD first-level child derivation method should be hardened
-    // See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254
-    accountZero = masterkey.deriveHardened(0)
-    externalAccount = accountZero.derive(0)
-    internalAccount = accountZero.derive(1)
-
-    me.addresses = []
-    me.changeAddresses = []
-
-    me.outputs = {}
-  }
-
-  this.newMasterKey(seed)
-
   this.generateAddress = function() {
     var key = externalAccount.derive(this.addresses.length)
     this.addresses.push(key.getAddress().toString())
@@ -71,6 +56,25 @@ function Wallet(seed, network) {
     return utxo
   }
 
+  // FIXME: remove in 2.x.y
+  this.newMasterKey = function(seed) {
+    console.warn('newMasterKey is deprecated, please make a new Wallet instance instead')
+
+    seed = seed || crypto.randomBytes(32)
+    masterkey = HDNode.fromSeedBuffer(seed, network)
+
+    // HD first-level child derivation method should be hardened
+    // See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254
+    accountZero = masterkey.deriveHardened(0)
+    externalAccount = accountZero.derive(0)
+    internalAccount = accountZero.derive(1)
+
+    me.addresses = []
+    me.changeAddresses = []
+
+    me.outputs = {}
+  }
+
   this.setUnspentOutputs = function(utxo) {
     var outputs = {}
 

From 8b3470e8cabe982f6fe40faac35e88271d33b9fc Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Wed, 13 Aug 2014 12:03:53 +1000
Subject: [PATCH 02/11] Wallet: move all free functions out of Wallet scope

---
 src/wallet.js | 137 +++++++++++++++++++++++++-------------------------
 1 file changed, 68 insertions(+), 69 deletions(-)

diff --git a/src/wallet.js b/src/wallet.js
index dd492ba..b188808 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -86,59 +86,6 @@ function Wallet(seed, network) {
 
     this.outputs = outputs
   }
-
-  function outputToUnspentOutput(output){
-    var hashAndIndex = output.from.split(":")
-
-    return {
-      hash: hashAndIndex[0],
-      outputIndex: parseInt(hashAndIndex[1]),
-      address: output.address,
-      value: output.value,
-      pending: output.pending
-    }
-  }
-
-  function unspentOutputToOutput(o) {
-    var hash = o.hash
-    var key = hash + ":" + o.outputIndex
-    return {
-      from: key,
-      address: o.address,
-      value: o.value,
-      pending: o.pending
-    }
-  }
-
-  function validateUnspentOutput(uo) {
-    var missingField
-
-    if (isNullOrUndefined(uo.hash)) {
-      missingField = "hash"
-    }
-
-    var requiredKeys = ['outputIndex', 'address', 'value']
-    requiredKeys.forEach(function (key) {
-      if (isNullOrUndefined(uo[key])){
-        missingField = key
-      }
-    })
-
-    if (missingField) {
-      var message = [
-        'Invalid unspent output: key', missingField, 'is missing.',
-        'A valid unspent output must contain'
-      ]
-      message.push(requiredKeys.join(', '))
-      message.push("and hash")
-      throw new Error(message.join(' '))
-    }
-  }
-
-  function isNullOrUndefined(value) {
-    return value == undefined
-  }
-
   this.processPendingTx = function(tx){
     processTx(tx, true)
   }
@@ -193,7 +140,7 @@ function Wallet(seed, network) {
   this.createTx = function(to, value, fixedFee, changeAddress) {
     assert(value > network.dustThreshold, value + ' must be above dust threshold (' + network.dustThreshold + ' Satoshis)')
 
-    var utxos = getCandidateOutputs(value)
+    var utxos = getCandidateOutputs(this.outputs, value)
     var accum = 0
     var subTotal = value
     var addresses = []
@@ -229,21 +176,6 @@ function Wallet(seed, network) {
     return tx
   }
 
-  function getCandidateOutputs() {
-    var unspent = []
-
-    for (var key in me.outputs) {
-      var output = me.outputs[key]
-      if (!output.pending) unspent.push(output)
-    }
-
-    var sortByValueDesc = unspent.sort(function(o1, o2){
-      return o2.value - o1.value
-    })
-
-    return sortByValueDesc
-  }
-
   function estimateFeePadChangeOutput(tx) {
     var tmpTx = tx.clone()
     tmpTx.addOutput(getChangeAddress(), network.dustSoftThreshold || 0)
@@ -305,4 +237,71 @@ function Wallet(seed, network) {
   }
 }
 
+function outputToUnspentOutput(output){
+  var hashAndIndex = output.from.split(":")
+
+  return {
+    hash: hashAndIndex[0],
+    outputIndex: parseInt(hashAndIndex[1]),
+    address: output.address,
+    value: output.value,
+    pending: output.pending
+  }
+}
+
+function unspentOutputToOutput(o) {
+  var hash = o.hash
+  var key = hash + ":" + o.outputIndex
+  return {
+    from: key,
+    address: o.address,
+    value: o.value,
+    pending: o.pending
+  }
+}
+
+function validateUnspentOutput(uo) {
+  var missingField
+
+  if (isNullOrUndefined(uo.hash)) {
+    missingField = "hash"
+  }
+
+  var requiredKeys = ['outputIndex', 'address', 'value']
+  requiredKeys.forEach(function (key) {
+    if (isNullOrUndefined(uo[key])){
+      missingField = key
+    }
+  })
+
+  if (missingField) {
+    var message = [
+      'Invalid unspent output: key', missingField, 'is missing.',
+      'A valid unspent output must contain'
+    ]
+    message.push(requiredKeys.join(', '))
+    message.push("and hash")
+    throw new Error(message.join(' '))
+  }
+}
+
+function isNullOrUndefined(value) {
+  return value == undefined
+}
+
+function getCandidateOutputs(outputs/*, value*/) {
+  var unspent = []
+
+  for (var key in outputs) {
+    var output = outputs[key]
+    if (!output.pending) unspent.push(output)
+  }
+
+  var sortByValueDesc = unspent.sort(function(o1, o2){
+    return o2.value - o1.value
+  })
+
+  return sortByValueDesc
+}
+
 module.exports = Wallet

From abc3e6c71584c7b6c5311f7eab91e18bf5c0d083 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Wed, 13 Aug 2014 12:17:12 +1000
Subject: [PATCH 03/11] Wallet: move estimatePaddedTxFee out of Wallet scope

---
 src/wallet.js | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/wallet.js b/src/wallet.js
index b188808..b2d9a05 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -5,6 +5,7 @@ var networks = require('./networks')
 var Address = require('./address')
 var HDNode = require('./hdnode')
 var Transaction = require('./transaction')
+var Script = require('./script')
 
 function Wallet(seed, network) {
   seed = seed || crypto.randomBytes(32)
@@ -155,7 +156,7 @@ function Wallet(seed, network) {
       var outpoint = utxo.from.split(':')
       tx.addInput(outpoint[0], parseInt(outpoint[1]))
 
-      var fee = fixedFee == undefined ? estimateFeePadChangeOutput(tx) : fixedFee
+      var fee = fixedFee == undefined ? estimatePaddedFee(tx, network) : fixedFee
 
       accum += utxo.value
       subTotal = value + fee
@@ -176,13 +177,6 @@ function Wallet(seed, network) {
     return tx
   }
 
-  function estimateFeePadChangeOutput(tx) {
-    var tmpTx = tx.clone()
-    tmpTx.addOutput(getChangeAddress(), network.dustSoftThreshold || 0)
-
-    return network.estimateFee(tmpTx)
-  }
-
   function getChangeAddress() {
     if(me.changeAddresses.length === 0) me.generateChangeAddress();
     return me.changeAddresses[me.changeAddresses.length - 1]
@@ -285,6 +279,13 @@ function validateUnspentOutput(uo) {
   }
 }
 
+function estimatePaddedFee(tx, network) {
+  var tmpTx = tx.clone()
+  tmpTx.addOutput(Script.EMPTY, network.dustSoftThreshold || 0)
+
+  return network.estimateFee(tmpTx)
+}
+
 function isNullOrUndefined(value) {
   return value == undefined
 }

From 7c22067f6934abe254fba9b51d9cccf00b657173 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Wed, 13 Aug 2014 13:56:17 +1000
Subject: [PATCH 04/11] Wallet: clarify getPrivateKeyForAddress method
 structure

This does repeat the O(n) lookup several times, but that can be fixed by
using an O(1) lookup instead (and will be later).

Clarity first.
---
 src/wallet.js  | 15 ++++++++++-----
 test/wallet.js |  2 +-
 2 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/wallet.js b/src/wallet.js
index b2d9a05..f377377 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -208,13 +208,18 @@ function Wallet(seed, network) {
   }
 
   this.getPrivateKeyForAddress = function(address) {
-    var index
-    if((index = this.addresses.indexOf(address)) > -1) {
+    assert(isMyAddress(address), 'Unknown address. Make sure the address is from the keychain and has been generated')
+
+    if (isReceiveAddress(address)) {
+      var index = this.addresses.indexOf(address)
+
       return this.getPrivateKey(index)
-    } else if((index = this.changeAddresses.indexOf(address)) > -1) {
+    }
+
+    if (isChangeAddress(address)) {
+      var index = this.changeAddresses.indexOf(address)
+
       return this.getInternalPrivateKey(index)
-    } else {
-      throw new Error('Unknown address. Make sure the address is from the keychain and has been generated.')
     }
   }
 
diff --git a/test/wallet.js b/test/wallet.js
index 80fd7a8..456775d 100644
--- a/test/wallet.js
+++ b/test/wallet.js
@@ -164,7 +164,7 @@ describe('Wallet', function() {
       var wallet = new Wallet(seed, networks.testnet)
       assert.throws(function() {
         wallet.getPrivateKeyForAddress("n2fiWrHqD6GM5GiEqkbWAc6aaZQp3ba93X")
-      }, /Unknown address. Make sure the address is from the keychain and has been generated./)
+      }, /Unknown address. Make sure the address is from the keychain and has been generated/)
     })
   })
 

From 2f00c9ab353a5fac49c882d65433a6a737d3534b Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Thu, 14 Aug 2014 11:03:54 +1000
Subject: [PATCH 05/11] Wallet: rework unspents to primarily work on
 initialization

The RegExp for the UTXO validation was removed as the errors are now
more verbose and specific to each case.
---
 src/wallet.js  |  85 +++++++---------
 test/wallet.js | 263 ++++++++++++++++++++++++++-----------------------
 2 files changed, 177 insertions(+), 171 deletions(-)

diff --git a/src/wallet.js b/src/wallet.js
index f377377..8dd2ca2 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -7,7 +7,7 @@ var HDNode = require('./hdnode')
 var Transaction = require('./transaction')
 var Script = require('./script')
 
-function Wallet(seed, network) {
+function Wallet(seed, network, unspents) {
   seed = seed || crypto.randomBytes(32)
   network = network || networks.bitcoin
 
@@ -26,7 +26,7 @@ function Wallet(seed, network) {
   this.changeAddresses = []
 
   // Transaction output data
-  this.outputs = {}
+  this.outputs = unspents ? processUnspentOutputs(unspents) : {}
 
   this.generateAddress = function() {
     var key = externalAccount.derive(this.addresses.length)
@@ -77,16 +77,11 @@ function Wallet(seed, network) {
   }
 
   this.setUnspentOutputs = function(utxo) {
-    var outputs = {}
+    console.warn('setUnspentOutputs is deprecated, please use the constructor option instead')
 
-    utxo.forEach(function(uo){
-      validateUnspentOutput(uo)
-      var o = unspentOutputToOutput(uo)
-      outputs[o.from] = o
-    })
-
-    this.outputs = outputs
+    this.outputs = processUnspentOutputs(utxo)
   }
+
   this.processPendingTx = function(tx){
     processTx(tx, true)
   }
@@ -95,6 +90,8 @@ function Wallet(seed, network) {
     processTx(tx, false)
   }
 
+  var me = this
+
   function processTx(tx, isPending) {
     var txid = tx.getId()
 
@@ -241,49 +238,13 @@ function outputToUnspentOutput(output){
 
   return {
     hash: hashAndIndex[0],
-    outputIndex: parseInt(hashAndIndex[1]),
+    index: parseInt(hashAndIndex[1]),
     address: output.address,
     value: output.value,
     pending: output.pending
   }
 }
 
-function unspentOutputToOutput(o) {
-  var hash = o.hash
-  var key = hash + ":" + o.outputIndex
-  return {
-    from: key,
-    address: o.address,
-    value: o.value,
-    pending: o.pending
-  }
-}
-
-function validateUnspentOutput(uo) {
-  var missingField
-
-  if (isNullOrUndefined(uo.hash)) {
-    missingField = "hash"
-  }
-
-  var requiredKeys = ['outputIndex', 'address', 'value']
-  requiredKeys.forEach(function (key) {
-    if (isNullOrUndefined(uo[key])){
-      missingField = key
-    }
-  })
-
-  if (missingField) {
-    var message = [
-      'Invalid unspent output: key', missingField, 'is missing.',
-      'A valid unspent output must contain'
-    ]
-    message.push(requiredKeys.join(', '))
-    message.push("and hash")
-    throw new Error(message.join(' '))
-  }
-}
-
 function estimatePaddedFee(tx, network) {
   var tmpTx = tx.clone()
   tmpTx.addOutput(Script.EMPTY, network.dustSoftThreshold || 0)
@@ -291,8 +252,34 @@ function estimatePaddedFee(tx, network) {
   return network.estimateFee(tmpTx)
 }
 
-function isNullOrUndefined(value) {
-  return value == undefined
+function processUnspentOutputs(utxos) {
+  var outputs = {}
+
+  utxos.forEach(function(utxo){
+    var hash = new Buffer(utxo.hash, 'hex')
+    var index = utxo.index
+    var address = utxo.address
+    var value = utxo.value
+
+    // FIXME: remove alternative in 2.x.y
+    if (index === undefined) index = utxo.outputIndex
+
+    assert.equal(hash.length, 32, 'Expected hash length of 32, got ' + hash.length)
+    assert.equal(typeof index, 'number', 'Expected number index, got ' + index)
+    assert.doesNotThrow(function() { Address.fromBase58Check(address) }, 'Expected Base58 Address, got ' + address)
+    assert.equal(typeof value, 'number', 'Expected number value, got ' + value)
+
+    var key = utxo.hash + ':' + utxo.index
+
+    outputs[key] = {
+      from: key,
+      address: address,
+      value: value,
+      pending: utxo.pending
+    }
+  })
+
+  return outputs
 }
 
 function getCandidateOutputs(outputs/*, value*/) {
diff --git a/test/wallet.js b/test/wallet.js
index 456775d..c08ae2f 100644
--- a/test/wallet.js
+++ b/test/wallet.js
@@ -26,13 +26,17 @@ function fakeTxId(i) {
 }
 
 describe('Wallet', function() {
-  var seed, wallet
+  var seed
   beforeEach(function(){
     seed = crypto.sha256("don't use a string seed like this in real life")
-    wallet = new Wallet(seed)
   })
 
   describe('constructor', function() {
+    var wallet
+    beforeEach(function(){
+      wallet = new Wallet(seed)
+    })
+
     it('defaults to Bitcoin network', function() {
       assert.equal(wallet.getMasterKey().network, networks.bitcoin)
     })
@@ -116,6 +120,11 @@ describe('Wallet', function() {
   })
 
   describe('generateChangeAddress', function(){
+    var wallet
+    beforeEach(function(){
+      wallet = new Wallet(seed)
+    })
+
     it('generates change addresses', function(){
       var wallet = new Wallet(seed, networks.testnet)
       var expectedAddresses = ["mnXiDR4MKsFxcKJEZjx4353oXvo55iuptn"]
@@ -126,6 +135,11 @@ describe('Wallet', function() {
   })
 
   describe('getPrivateKey', function(){
+    var wallet
+    beforeEach(function(){
+      wallet = new Wallet(seed)
+    })
+
     it('returns the private key at the given index of external account', function(){
       var wallet = new Wallet(seed, networks.testnet)
 
@@ -135,6 +149,11 @@ describe('Wallet', function() {
   })
 
   describe('getInternalPrivateKey', function(){
+    var wallet
+    beforeEach(function(){
+      wallet = new Wallet(seed)
+    })
+
     it('returns the private key at the given index of internal account', function(){
       var wallet = new Wallet(seed, networks.testnet)
 
@@ -144,6 +163,11 @@ describe('Wallet', function() {
   })
 
   describe('getPrivateKeyForAddress', function(){
+    var wallet
+    beforeEach(function(){
+      wallet = new Wallet(seed)
+    })
+
     it('returns the private key for the given address', function(){
       var wallet = new Wallet(seed, networks.testnet)
       wallet.generateChangeAddress()
@@ -162,6 +186,7 @@ describe('Wallet', function() {
 
     it('raises an error when address is not found', function(){
       var wallet = new Wallet(seed, networks.testnet)
+
       assert.throws(function() {
         wallet.getPrivateKeyForAddress("n2fiWrHqD6GM5GiEqkbWAc6aaZQp3ba93X")
       }, /Unknown address. Make sure the address is from the keychain and has been generated/)
@@ -169,51 +194,55 @@ describe('Wallet', function() {
   })
 
   describe('Unspent Outputs', function(){
-    var expectedUtxo, expectedOutputKey
+    var utxo, expectedOutputKey
+    var wallet
+
     beforeEach(function(){
-      expectedUtxo = {
-        "hash":"6a4062273ac4f9ea4ffca52d9fd102b08f6c32faa0a4d1318e3a7b2e437bb9c7",
-        "outputIndex": 0,
+      utxo = {
         "address" : "1AZpKpcfCzKDUeTFBQUL4MokQai3m3HMXv",
-        "value": 20000,
-        "pending": true
+        "hash": fakeTxId(6),
+        "index": 0,
+        "pending": true,
+        "value": 20000
       }
-      expectedOutputKey = expectedUtxo.hash + ":" + expectedUtxo.outputIndex
+
+      expectedOutputKey = utxo.hash + ":" + utxo.index
     })
 
-    function addUtxoToOutput(utxo){
-      var key = utxo.hash + ":" + utxo.outputIndex
-      wallet.outputs[key] = {
-        from: key,
-        address: utxo.address,
-        value: utxo.value,
-        pending: utxo.pending
-      }
-    }
+    describe('on construction', function(){
+      beforeEach(function(){
+        wallet = new Wallet(seed, networks.bitcoin, [utxo])
+      })
+
+      it('matches the expected behaviour', function(){
+        var output = wallet.outputs[expectedOutputKey]
+
+        assert(output)
+        assert.equal(output.value, utxo.value)
+        assert.equal(output.address, utxo.address)
+      })
+    })
 
     describe('getBalance', function(){
-      var utxo1
-
       beforeEach(function(){
-        utxo1 = cloneObject(expectedUtxo)
-        utxo1.hash = utxo1.hash.replace('7', 'l')
+        var utxo1 = cloneObject(utxo)
+        utxo1.hash = fakeTxId(5)
+
+        wallet = new Wallet(seed, networks.bitcoin, [utxo, utxo1])
       })
 
       it('sums over utxo values', function(){
-        addUtxoToOutput(expectedUtxo)
-        addUtxoToOutput(utxo1)
-
         assert.equal(wallet.getBalance(), 40000)
       })
     })
 
     describe('getUnspentOutputs', function(){
       beforeEach(function(){
-        addUtxoToOutput(expectedUtxo)
+        wallet = new Wallet(seed, networks.bitcoin, [utxo])
       })
 
       it('parses wallet outputs to the expect format', function(){
-        assert.deepEqual(wallet.getUnspentOutputs(), [expectedUtxo])
+        assert.deepEqual(wallet.getUnspentOutputs(), [utxo])
       })
 
       it("ignores pending spending outputs (outputs with 'to' property)", function(){
@@ -223,40 +252,54 @@ describe('Wallet', function() {
         assert.deepEqual(wallet.getUnspentOutputs(), [])
       })
     })
+  })
 
-    describe('setUnspentOutputs', function(){
-      var utxo
-      beforeEach(function(){
-        utxo = cloneObject([expectedUtxo])
-      })
+  // FIXME: remove in 2.x.y
+  describe('setUnspentOutputs', function(){
+    var utxo
+    var expectedOutputKey
 
-      it('matches the expected behaviour', function(){
-        wallet.setUnspentOutputs(utxo)
-        verifyOutputs()
-      })
+    beforeEach(function(){
+      utxo = {
+        hash: fakeTxId(0),
+        index: 0,
+        address: '115qa7iPZqn6as57hxLL8E9VUnhmGQxKWi',
+        value: 500000
+      }
 
-      describe('required fields', function(){
-        ['outputIndex', 'address', 'hash', 'value'].forEach(function(field){
-          it("throws an error when " + field + " is missing", function(){
-            delete utxo[0][field]
+      expectedOutputKey = utxo.hash + ":" + utxo.index
 
-            assert.throws(function() {
-              wallet.setUnspentOutputs(utxo)
-            }, new RegExp('Invalid unspent output: key ' + field + ' is missing'))
+      wallet = new Wallet(seed, networks.bitcoin)
+    })
+
+    it('matches the expected behaviour', function(){
+      wallet.setUnspentOutputs([utxo])
+
+      var output = wallet.outputs[expectedOutputKey]
+      assert(output)
+      assert.equal(output.value, utxo.value)
+      assert.equal(output.address, utxo.address)
+    })
+
+    describe('required fields', function(){
+      ['index', 'address', 'hash', 'value'].forEach(function(field){
+        it("throws an error when " + field + " is missing", function(){
+          delete utxo[field]
+
+          assert.throws(function() {
+            wallet.setUnspentOutputs([utxo])
           })
         })
       })
-
-      function verifyOutputs() {
-        var output = wallet.outputs[expectedOutputKey]
-        assert(output)
-        assert.equal(output.value, utxo[0].value)
-        assert.equal(output.address, utxo[0].address)
-      }
     })
   })
 
   describe('Process transaction', function(){
+    var wallet
+    beforeEach(function(){
+      wallet = new Wallet(seed)
+    })
+
     var addresses
     var tx
 
@@ -389,39 +432,42 @@ describe('Wallet', function() {
   })
 
   describe('createTx', function(){
-    var to, value
+    var wallet
     var address1, address2
+    var to, value
 
     beforeEach(function(){
-      to = '15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3'
+      to = 'mt7MyTVVEWnbwpF5hBn6fgnJcv95Syk2ue'
       value = 500000
 
-      // generate 2 addresses
-      address1 = wallet.generateAddress()
-      address2 = wallet.generateAddress()
+      address1 = "n1GyUANZand9Kw6hGSV9837cCC9FFUQzQa"
+      address2 = "n2fiWrHqD6GM5GiEqkbWAc6aaZQp3ba93X"
 
-      // set up 3 utxo
-      utxo = [
+      // set up 3 utxos
+      var utxos = [
         {
           "hash": fakeTxId(1),
-          "outputIndex": 0,
-          "address" : address1,
+          "index": 0,
+          "address": address1,
           "value": 400000 // not enough for value
         },
         {
           "hash": fakeTxId(2),
-          "outputIndex": 1,
-          "address" : address1,
+          "index": 1,
+          "address": address1,
           "value": 500000 // enough for only value
         },
         {
           "hash": fakeTxId(3),
-          "outputIndex": 0,
+          "index": 0,
           "address" : address2,
           "value": 510000 // enough for value and fee
         }
       ]
-      wallet.setUnspentOutputs(utxo)
+
+      wallet = new Wallet(seed, networks.testnet, utxos)
+      wallet.generateAddress()
+      wallet.generateAddress()
     })
 
     describe('transaction fee', function(){
@@ -441,17 +487,18 @@ describe('Wallet', function() {
       })
 
       it('does not overestimate fees when network has dustSoftThreshold', function(){
-        var wallet = new Wallet(seed, networks.litecoin)
-        var address = wallet.generateAddress()
-        wallet.setUnspentOutputs([{
+        var utxo = {
           hash: fakeTxId(0),
-          outputIndex: 0,
-          address: address,
+          index: 0,
+          address: "LeyySKbQrRRwodKEj1W4a8y3YQupPLw5os",
           value: 500000
-        }])
+        }
+
+        var wallet = new Wallet(seed, networks.litecoin, [utxo])
+        wallet.generateAddress()
 
         value = 200000
-        var tx = wallet.createTx(address, value)
+        var tx = wallet.createTx(utxo.address, value)
 
         assert.equal(getFee(wallet, tx), 100000)
       })
@@ -477,18 +524,25 @@ describe('Wallet', function() {
         assert.equal(tx.ins[0].index, 0)
       })
 
-      it('ignores pending outputs', function(){
-        utxo.push(
-          {
-            "hash": fakeTxId(4),
-            "outputIndex": 0,
-            "address" : address2,
-            "value": 530000,
-            "pending": true
-          }
-        )
-        wallet.setUnspentOutputs(utxo)
+      it('uses confirmed outputs', function(){
+        var tx2 = new Transaction()
+        tx2.addInput(fakeTxId(4), 0)
+        tx2.addOutput(address2, 530000)
 
+        wallet.processConfirmedTx(tx2)
+        var tx = wallet.createTx(to, value)
+
+        assert.equal(tx.ins.length, 1)
+        assert.deepEqual(tx.ins[0].hash, tx2.getHash())
+        assert.equal(tx.ins[0].index, 0)
+      })
+
+      it('ignores pending outputs', function(){
+        var tx2 = new Transaction()
+        tx2.addInput(fakeTxId(4), 0)
+        tx2.addOutput(address2, 530000)
+
+        wallet.processPendingTx(tx2)
         var tx = wallet.createTx(to, value)
 
         assert.equal(tx.ins.length, 1)
@@ -497,46 +551,11 @@ describe('Wallet', function() {
       })
     })
 
-    describe('works for testnet', function(){
-      it('should create transaction', function(){
-        var wallet = new Wallet(seed, networks.testnet)
-        var address = wallet.generateAddress()
-
-        wallet.setUnspentOutputs([{
-          hash: fakeTxId(0),
-          outputIndex: 0,
-          address: address,
-          value: value
-        }])
-
-        var to = 'mt7MyTVVEWnbwpF5hBn6fgnJcv95Syk2ue'
-        var toValue = value - 10000
-
-        var tx = wallet.createTx(to, toValue)
-        assert.equal(tx.outs.length, 1)
-
-        var outAddress = Address.fromOutputScript(tx.outs[0].script, networks.testnet)
-        assert.equal(outAddress.toString(), to)
-        assert.equal(tx.outs[0].value, toValue)
-      })
-    })
-
     describe('changeAddress', function(){
       it('should allow custom changeAddress', function(){
-        var wallet = new Wallet(seed, networks.testnet)
-        var address = wallet.generateAddress()
-
-        wallet.setUnspentOutputs([{
-          hash: fakeTxId(0),
-          outputIndex: 0,
-          address: address,
-          value: value
-        }])
-        assert.equal(wallet.getBalance(), value)
-
         var changeAddress = 'mfrFjnKZUvTcvdAK2fUX5D8v1Epu5H8JCk'
-        var to = 'mt7MyTVVEWnbwpF5hBn6fgnJcv95Syk2ue'
-        var toValue = value / 2
+        var fromValue = 510000
+        var toValue = fromValue / 2
         var fee = 1e3
 
         var tx = wallet.createTx(to, toValue, fee, changeAddress)
@@ -549,7 +568,7 @@ describe('Wallet', function() {
         assert.equal(tx.outs[0].value, toValue)
 
         assert.equal(outAddress1.toString(), changeAddress)
-        assert.equal(tx.outs[1].value, value - (toValue + fee))
+        assert.equal(tx.outs[1].value, fromValue - (toValue + fee))
       })
     })
 
@@ -559,7 +578,7 @@ describe('Wallet', function() {
 
         assert.equal(tx.outs.length, 1)
         var out = tx.outs[0]
-        var outAddress = Address.fromOutputScript(out.script)
+        var outAddress = Address.fromOutputScript(out.script, networks.testnet)
 
         assert.equal(outAddress.toString(), to)
         assert.equal(out.value, value)
@@ -574,7 +593,7 @@ describe('Wallet', function() {
 
           assert.equal(tx.outs.length, 2)
           var out = tx.outs[1]
-          var outAddress = Address.fromOutputScript(out.script)
+          var outAddress = Address.fromOutputScript(out.script, networks.testnet)
 
           assert.equal(outAddress.toString(), wallet.changeAddresses[1])
           assert.equal(out.value, 10000)
@@ -588,7 +607,7 @@ describe('Wallet', function() {
 
           assert.equal(wallet.changeAddresses.length, 1)
           var out = tx.outs[1]
-          var outAddress = Address.fromOutputScript(out.script)
+          var outAddress = Address.fromOutputScript(out.script, networks.testnet)
 
           assert.equal(outAddress.toString(), wallet.changeAddresses[0])
           assert.equal(out.value, 10000)

From 7fd41fae4ae8022de3fbf9fb9ff4335d28ee1c31 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Thu, 14 Aug 2014 10:27:14 +1000
Subject: [PATCH 06/11] Wallet: move most instance methods to prototype

---
 src/wallet.js | 123 ++++++++++++++++++++++++++++----------------------
 1 file changed, 70 insertions(+), 53 deletions(-)

diff --git a/src/wallet.js b/src/wallet.js
index 8dd2ca2..d904360 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -28,35 +28,6 @@ function Wallet(seed, network, unspents) {
   // Transaction output data
   this.outputs = unspents ? processUnspentOutputs(unspents) : {}
 
-  this.generateAddress = function() {
-    var key = externalAccount.derive(this.addresses.length)
-    this.addresses.push(key.getAddress().toString())
-    return this.addresses[this.addresses.length - 1]
-  }
-
-  this.generateChangeAddress = function() {
-    var key = internalAccount.derive(this.changeAddresses.length)
-    this.changeAddresses.push(key.getAddress().toString())
-    return this.changeAddresses[this.changeAddresses.length - 1]
-  }
-
-  this.getBalance = function() {
-    return this.getUnspentOutputs().reduce(function(memo, output){
-      return memo + output.value
-    }, 0)
-  }
-
-  this.getUnspentOutputs = function() {
-    var utxo = []
-
-    for(var key in this.outputs){
-      var output = this.outputs[key]
-      if(!output.to) utxo.push(outputToUnspentOutput(output))
-    }
-
-    return utxo
-  }
-
   // FIXME: remove in 2.x.y
   this.newMasterKey = function(seed) {
     console.warn('newMasterKey is deprecated, please make a new Wallet instance instead')
@@ -76,12 +47,6 @@ function Wallet(seed, network, unspents) {
     me.outputs = {}
   }
 
-  this.setUnspentOutputs = function(utxo) {
-    console.warn('setUnspentOutputs is deprecated, please use the constructor option instead')
-
-    this.outputs = processUnspentOutputs(utxo)
-  }
-
   this.processPendingTx = function(tx){
     processTx(tx, true)
   }
@@ -161,7 +126,7 @@ function Wallet(seed, network, unspents) {
         var change = accum - subTotal
 
         if (change > network.dustThreshold) {
-          tx.addOutput(changeAddress || getChangeAddress(), change)
+          tx.addOutput(changeAddress || this.getChangeAddress(), change)
         }
 
         break
@@ -174,23 +139,6 @@ function Wallet(seed, network, unspents) {
     return tx
   }
 
-  function getChangeAddress() {
-    if(me.changeAddresses.length === 0) me.generateChangeAddress();
-    return me.changeAddresses[me.changeAddresses.length - 1]
-  }
-
-  this.signWith = function(tx, addresses) {
-    assert.equal(tx.ins.length, addresses.length, 'Number of addresses must match number of transaction inputs')
-
-    addresses.forEach(function(address, i) {
-      var key = me.getPrivateKeyForAddress(address)
-
-      tx.sign(i, key)
-    })
-
-    return tx
-  }
-
   this.getMasterKey = function() { return masterkey }
   this.getAccountZero = function() { return accountZero }
   this.getInternalAccount = function() { return internalAccount }
@@ -233,6 +181,75 @@ function Wallet(seed, network, unspents) {
   }
 }
 
+Wallet.prototype.generateAddress = function() {
+  var k = this.addresses.length
+  var address = this.getExternalAccount().derive(k).getAddress()
+
+  this.addresses.push(address.toString())
+
+  return this.getReceiveAddress()
+}
+
+Wallet.prototype.generateChangeAddress = function() {
+  var k = this.changeAddresses.length
+  var address = this.getInternalAccount().derive(k).getAddress()
+
+  this.changeAddresses.push(address.toString())
+
+  return this.getChangeAddress()
+}
+
+Wallet.prototype.getBalance = function() {
+  return this.getUnspentOutputs().reduce(function(accum, output) {
+    return accum + output.value
+  }, 0)
+}
+
+Wallet.prototype.getChangeAddress = function() {
+  if (this.changeAddresses.length === 0) {
+    this.generateChangeAddress()
+  }
+
+  return this.changeAddresses[this.changeAddresses.length - 1]
+}
+
+Wallet.prototype.getReceiveAddress = function() {
+  if (this.addresses.length === 0) {
+    this.generateAddress()
+  }
+
+  return this.addresses[this.addresses.length - 1]
+}
+
+Wallet.prototype.getUnspentOutputs = function() {
+  var utxo = []
+
+  for(var key in this.outputs){
+    var output = this.outputs[key]
+    if(!output.to) utxo.push(outputToUnspentOutput(output))
+  }
+
+  return utxo
+}
+
+Wallet.prototype.setUnspentOutputs = function(utxo) {
+  console.warn('setUnspentOutputs is deprecated, please use the constructor option instead')
+
+  this.outputs = processUnspentOutputs(utxo)
+}
+
+Wallet.prototype.signWith = function(tx, addresses) {
+  assert.equal(tx.ins.length, addresses.length, 'Number of addresses must match number of transaction inputs')
+
+  addresses.forEach(function(address, i) {
+    var key = this.getPrivateKeyForAddress(address)
+
+    tx.sign(i, key)
+  }, this)
+
+  return tx
+}
+
 function outputToUnspentOutput(output){
   var hashAndIndex = output.from.split(":")
 

From 6df785bb6591bf15e2b0fcc2d784c81ecd7fa008 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Thu, 14 Aug 2014 10:39:14 +1000
Subject: [PATCH 07/11] Wallet: move createTx to prototype

---
 src/wallet.js | 96 ++++++++++++++++++++++++++-------------------------
 1 file changed, 49 insertions(+), 47 deletions(-)

diff --git a/src/wallet.js b/src/wallet.js
index d904360..ced3ac5 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -25,6 +25,8 @@ function Wallet(seed, network, unspents) {
   this.addresses = []
   this.changeAddresses = []
 
+  this.network = network
+
   // Transaction output data
   this.outputs = unspents ? processUnspentOutputs(unspents) : {}
 
@@ -100,58 +102,11 @@ function Wallet(seed, network, unspents) {
     })
   }
 
-  this.createTx = function(to, value, fixedFee, changeAddress) {
-    assert(value > network.dustThreshold, value + ' must be above dust threshold (' + network.dustThreshold + ' Satoshis)')
-
-    var utxos = getCandidateOutputs(this.outputs, value)
-    var accum = 0
-    var subTotal = value
-    var addresses = []
-
-    var tx = new Transaction()
-    tx.addOutput(to, value)
-
-    for (var i = 0; i < utxos.length; ++i) {
-      var utxo = utxos[i]
-      addresses.push(utxo.address)
-
-      var outpoint = utxo.from.split(':')
-      tx.addInput(outpoint[0], parseInt(outpoint[1]))
-
-      var fee = fixedFee == undefined ? estimatePaddedFee(tx, network) : fixedFee
-
-      accum += utxo.value
-      subTotal = value + fee
-      if (accum >= subTotal) {
-        var change = accum - subTotal
-
-        if (change > network.dustThreshold) {
-          tx.addOutput(changeAddress || this.getChangeAddress(), change)
-        }
-
-        break
-      }
-    }
-
-    assert(accum >= subTotal, 'Not enough funds (incl. fee): ' + accum + ' < ' + subTotal)
-
-    this.signWith(tx, addresses)
-    return tx
-  }
-
   this.getMasterKey = function() { return masterkey }
   this.getAccountZero = function() { return accountZero }
   this.getInternalAccount = function() { return internalAccount }
   this.getExternalAccount = function() { return externalAccount }
 
-  this.getPrivateKey = function(index) {
-    return externalAccount.derive(index).privKey
-  }
-
-  this.getInternalPrivateKey = function(index) {
-    return internalAccount.derive(index).privKey
-  }
-
   this.getPrivateKeyForAddress = function(address) {
     assert(isMyAddress(address), 'Unknown address. Make sure the address is from the keychain and has been generated')
 
@@ -181,6 +136,45 @@ function Wallet(seed, network, unspents) {
   }
 }
 
+Wallet.prototype.createTx = function(to, value, fixedFee, changeAddress) {
+  assert(value > this.network.dustThreshold, value + ' must be above dust threshold (' + this.network.dustThreshold + ' Satoshis)')
+
+  var utxos = getCandidateOutputs(this.outputs, value)
+  var accum = 0
+  var subTotal = value
+  var addresses = []
+
+  var tx = new Transaction()
+  tx.addOutput(to, value)
+
+  for (var i = 0; i < utxos.length; ++i) {
+    var utxo = utxos[i]
+    addresses.push(utxo.address)
+
+    var outpoint = utxo.from.split(':')
+    tx.addInput(outpoint[0], parseInt(outpoint[1]))
+
+    var fee = fixedFee == undefined ? estimatePaddedFee(tx, this.network) : fixedFee
+
+    accum += utxo.value
+    subTotal = value + fee
+    if (accum >= subTotal) {
+      var change = accum - subTotal
+
+      if (change > this.network.dustThreshold) {
+        tx.addOutput(changeAddress || this.getChangeAddress(), change)
+      }
+
+      break
+    }
+  }
+
+  assert(accum >= subTotal, 'Not enough funds (incl. fee): ' + accum + ' < ' + subTotal)
+
+  this.signWith(tx, addresses)
+  return tx
+}
+
 Wallet.prototype.generateAddress = function() {
   var k = this.addresses.length
   var address = this.getExternalAccount().derive(k).getAddress()
@@ -213,6 +207,14 @@ Wallet.prototype.getChangeAddress = function() {
   return this.changeAddresses[this.changeAddresses.length - 1]
 }
 
+Wallet.prototype.getInternalPrivateKey = function(index) {
+  return this.getInternalAccount().derive(index).privKey
+}
+
+Wallet.prototype.getPrivateKey = function(index) {
+  return this.getExternalAccount().derive(index).privKey
+}
+
 Wallet.prototype.getReceiveAddress = function() {
   if (this.addresses.length === 0) {
     this.generateAddress()

From c13177bb29acc7d3ab85d726190802722d05a4a6 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Thu, 14 Aug 2014 17:29:14 +1000
Subject: [PATCH 08/11] Wallet: rename masterkey to masterKey

---
 src/wallet.js | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/wallet.js b/src/wallet.js
index ced3ac5..ad7ccbd 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -12,12 +12,12 @@ function Wallet(seed, network, unspents) {
   network = network || networks.bitcoin
 
   // Stored in a closure to make accidental serialization less likely
-  var masterkey = HDNode.fromSeedBuffer(seed, network)
+  var masterKey = HDNode.fromSeedBuffer(seed, network)
   var me = this
 
   // HD first-level child derivation method should be hardened
   // See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254
-  var accountZero = masterkey.deriveHardened(0)
+  var accountZero = masterKey.deriveHardened(0)
   var externalAccount = accountZero.derive(0)
   var internalAccount = accountZero.derive(1)
 
@@ -35,11 +35,11 @@ function Wallet(seed, network, unspents) {
     console.warn('newMasterKey is deprecated, please make a new Wallet instance instead')
 
     seed = seed || crypto.randomBytes(32)
-    masterkey = HDNode.fromSeedBuffer(seed, network)
+    masterKey = HDNode.fromSeedBuffer(seed, network)
 
     // HD first-level child derivation method should be hardened
     // See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254
-    accountZero = masterkey.deriveHardened(0)
+    accountZero = masterKey.deriveHardened(0)
     externalAccount = accountZero.derive(0)
     internalAccount = accountZero.derive(1)
 
@@ -102,10 +102,10 @@ function Wallet(seed, network, unspents) {
     })
   }
 
-  this.getMasterKey = function() { return masterkey }
+  this.getMasterKey = function() { return masterKey }
   this.getAccountZero = function() { return accountZero }
-  this.getInternalAccount = function() { return internalAccount }
   this.getExternalAccount = function() { return externalAccount }
+  this.getInternalAccount = function() { return internalAccount }
 
   this.getPrivateKeyForAddress = function(address) {
     assert(isMyAddress(address), 'Unknown address. Make sure the address is from the keychain and has been generated')

From 2b4d94cd92495992ce27425acf40440c6e025dc5 Mon Sep 17 00:00:00 2001
From: Wei Lu <luwei.here@gmail.com>
Date: Sat, 16 Aug 2014 14:19:19 +0800
Subject: [PATCH 09/11] Wallet: move processPendingTx & processConfirmedTx to
 prototype

also, move processTx out of Wallet scope
---
 src/wallet.js | 129 ++++++++++++++++++++++++--------------------------
 1 file changed, 61 insertions(+), 68 deletions(-)

diff --git a/src/wallet.js b/src/wallet.js
index ad7ccbd..23142d5 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -49,91 +49,28 @@ function Wallet(seed, network, unspents) {
     me.outputs = {}
   }
 
-  this.processPendingTx = function(tx){
-    processTx(tx, true)
-  }
-
-  this.processConfirmedTx = function(tx){
-    processTx(tx, false)
-  }
-
-  var me = this
-
-  function processTx(tx, isPending) {
-    var txid = tx.getId()
-
-    tx.outs.forEach(function(txOut, i) {
-      var address
-
-      try {
-        address = Address.fromOutputScript(txOut.script, network).toString()
-      } catch(e) {
-        if (!(e.message.match(/has no matching Address/))) throw e
-      }
-
-      if (isMyAddress(address)) {
-        var output = txid + ':' + i
-
-        me.outputs[output] = {
-          from: output,
-          value: txOut.value,
-          address: address,
-          pending: isPending
-        }
-      }
-    })
-
-    tx.ins.forEach(function(txIn, i) {
-      // copy and convert to big-endian hex
-      var txinId = new Buffer(txIn.hash)
-      Array.prototype.reverse.call(txinId)
-      txinId = txinId.toString('hex')
-
-      var output = txinId + ':' + txIn.index
-
-      if (!(output in me.outputs)) return
-
-      if (isPending) {
-        me.outputs[output].to = txid + ':' + i
-        me.outputs[output].pending = true
-      } else {
-        delete me.outputs[output]
-      }
-    })
-  }
-
   this.getMasterKey = function() { return masterKey }
   this.getAccountZero = function() { return accountZero }
   this.getExternalAccount = function() { return externalAccount }
   this.getInternalAccount = function() { return internalAccount }
 
   this.getPrivateKeyForAddress = function(address) {
-    assert(isMyAddress(address), 'Unknown address. Make sure the address is from the keychain and has been generated')
+    var myAddresses = this.addresses.concat(this.changeAddresses)
+    assert(includeAddress(myAddresses, address),
+           'Unknown address. Make sure the address is from the keychain and has been generated')
 
-    if (isReceiveAddress(address)) {
+    if (includeAddress(this.addresses, address)) {
       var index = this.addresses.indexOf(address)
 
       return this.getPrivateKey(index)
     }
 
-    if (isChangeAddress(address)) {
+    if (includeAddress(this.changeAddresses, address)) {
       var index = this.changeAddresses.indexOf(address)
 
       return this.getInternalPrivateKey(index)
     }
   }
-
-  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)
-  }
 }
 
 Wallet.prototype.createTx = function(to, value, fixedFee, changeAddress) {
@@ -175,6 +112,14 @@ Wallet.prototype.createTx = function(to, value, fixedFee, changeAddress) {
   return tx
 }
 
+Wallet.prototype.processPendingTx = function(tx){
+  processTx.bind(this)(tx, true)
+}
+
+Wallet.prototype.processConfirmedTx = function(tx){
+  processTx.bind(this)(tx, false)
+}
+
 Wallet.prototype.generateAddress = function() {
   var k = this.addresses.length
   var address = this.getExternalAccount().derive(k).getAddress()
@@ -316,4 +261,52 @@ function getCandidateOutputs(outputs/*, value*/) {
   return sortByValueDesc
 }
 
+function processTx(tx, isPending) {
+  var txid = tx.getId()
+
+  tx.outs.forEach(function(txOut, i) {
+    var address
+
+    try {
+      address = Address.fromOutputScript(txOut.script, this.network).toString()
+    } catch(e) {
+      if (!(e.message.match(/has no matching Address/))) throw e
+    }
+
+    var myAddresses = this.addresses.concat(this.changeAddresses)
+    if (includeAddress(myAddresses, address)) {
+      var output = txid + ':' + i
+
+      this.outputs[output] = {
+        from: output,
+        value: txOut.value,
+        address: address,
+        pending: isPending
+      }
+    }
+  }, this)
+
+  tx.ins.forEach(function(txIn, i) {
+    // copy and convert to big-endian hex
+    var txinId = new Buffer(txIn.hash)
+    Array.prototype.reverse.call(txinId)
+    txinId = txinId.toString('hex')
+
+    var output = txinId + ':' + txIn.index
+
+    if (!(output in this.outputs)) return
+
+    if (isPending) {
+      this.outputs[output].to = txid + ':' + i
+      this.outputs[output].pending = true
+    } else {
+      delete this.outputs[output]
+    }
+  }, this)
+}
+
+function includeAddress(addresses, address) {
+  return addresses.indexOf(address) > -1
+}
+
 module.exports = Wallet

From 00d58604a47ecbe169c991ddc4f7e5fb247f7d57 Mon Sep 17 00:00:00 2001
From: Wei Lu <luwei.here@gmail.com>
Date: Sat, 16 Aug 2014 14:24:24 +0800
Subject: [PATCH 10/11] Wallet: move getPrivateKeyForAddress to prototype

also, move the assert to the end to simplify the logic
---
 src/wallet.js | 34 ++++++++++++++++------------------
 1 file changed, 16 insertions(+), 18 deletions(-)

diff --git a/src/wallet.js b/src/wallet.js
index 23142d5..137ec86 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -53,24 +53,6 @@ function Wallet(seed, network, unspents) {
   this.getAccountZero = function() { return accountZero }
   this.getExternalAccount = function() { return externalAccount }
   this.getInternalAccount = function() { return internalAccount }
-
-  this.getPrivateKeyForAddress = function(address) {
-    var myAddresses = this.addresses.concat(this.changeAddresses)
-    assert(includeAddress(myAddresses, address),
-           'Unknown address. Make sure the address is from the keychain and has been generated')
-
-    if (includeAddress(this.addresses, address)) {
-      var index = this.addresses.indexOf(address)
-
-      return this.getPrivateKey(index)
-    }
-
-    if (includeAddress(this.changeAddresses, address)) {
-      var index = this.changeAddresses.indexOf(address)
-
-      return this.getInternalPrivateKey(index)
-    }
-  }
 }
 
 Wallet.prototype.createTx = function(to, value, fixedFee, changeAddress) {
@@ -160,6 +142,22 @@ Wallet.prototype.getPrivateKey = function(index) {
   return this.getExternalAccount().derive(index).privKey
 }
 
+Wallet.prototype.getPrivateKeyForAddress = function(address) {
+  if (includeAddress(this.addresses, address)) {
+    var index = this.addresses.indexOf(address)
+
+    return this.getPrivateKey(index)
+  }
+
+  if (includeAddress(this.changeAddresses, address)) {
+    var index = this.changeAddresses.indexOf(address)
+
+    return this.getInternalPrivateKey(index)
+  }
+
+  assert(false, 'Unknown address. Make sure the address is from the keychain and has been generated')
+}
+
 Wallet.prototype.getReceiveAddress = function() {
   if (this.addresses.length === 0) {
     this.generateAddress()

From e55676cf8e6b441dad5d747ea5da062338971c9d Mon Sep 17 00:00:00 2001
From: Wei Lu <luwei.here@gmail.com>
Date: Sat, 16 Aug 2014 14:27:12 +0800
Subject: [PATCH 11/11] Wallet: remove unncessary comments

---
 src/wallet.js | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/src/wallet.js b/src/wallet.js
index 137ec86..6e26612 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -13,7 +13,6 @@ function Wallet(seed, network, unspents) {
 
   // Stored in a closure to make accidental serialization less likely
   var masterKey = HDNode.fromSeedBuffer(seed, network)
-  var me = this
 
   // HD first-level child derivation method should be hardened
   // See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254
@@ -21,24 +20,19 @@ function Wallet(seed, network, unspents) {
   var externalAccount = accountZero.derive(0)
   var internalAccount = accountZero.derive(1)
 
-  // Addresses
   this.addresses = []
   this.changeAddresses = []
-
   this.network = network
-
-  // Transaction output data
   this.outputs = unspents ? processUnspentOutputs(unspents) : {}
 
   // FIXME: remove in 2.x.y
+  var me = this
   this.newMasterKey = function(seed) {
     console.warn('newMasterKey is deprecated, please make a new Wallet instance instead')
 
     seed = seed || crypto.randomBytes(32)
     masterKey = HDNode.fromSeedBuffer(seed, network)
 
-    // HD first-level child derivation method should be hardened
-    // See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254
     accountZero = masterKey.deriveHardened(0)
     externalAccount = accountZero.derive(0)
     internalAccount = accountZero.derive(1)