Skip to content

Commit

Permalink
Merge pull request #2 from weilu/dcousens-wallclean
Browse files Browse the repository at this point in the history
Clean up Wallet constructor function
  • Loading branch information
dcousens committed Aug 16, 2014
2 parents c13177b + e55676c commit 1ca6996
Showing 1 changed file with 73 additions and 88 deletions.
161 changes: 73 additions & 88 deletions src/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,26 @@ 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
var accountZero = masterKey.deriveHardened(0)
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)
Expand All @@ -49,91 +43,10 @@ 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')

if (isReceiveAddress(address)) {
var index = this.addresses.indexOf(address)

return this.getPrivateKey(index)
}

if (isChangeAddress(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) {
Expand Down Expand Up @@ -175,6 +88,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()
Expand Down Expand Up @@ -215,6 +136,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()
Expand Down Expand Up @@ -316,4 +253,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

0 comments on commit 1ca6996

Please sign in to comment.