aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts/lib
diff options
context:
space:
mode:
Diffstat (limited to 'app/scripts/lib')
-rw-r--r--app/scripts/lib/account-tracker.js (renamed from app/scripts/lib/eth-store.js)76
-rw-r--r--app/scripts/lib/pending-balance-calculator.js51
2 files changed, 72 insertions, 55 deletions
diff --git a/app/scripts/lib/eth-store.js b/app/scripts/lib/account-tracker.js
index ebba98f5c..e2892b1ce 100644
--- a/app/scripts/lib/eth-store.js
+++ b/app/scripts/lib/account-tracker.js
@@ -1,4 +1,4 @@
-/* Ethereum Store
+/* Account Tracker
*
* This module is responsible for tracking any number of accounts
* and caching their current balances & transaction counts.
@@ -10,19 +10,21 @@
const async = require('async')
const EthQuery = require('eth-query')
const ObservableStore = require('obs-store')
+const EventEmitter = require('events').EventEmitter
function noop () {}
-class EthereumStore extends ObservableStore {
+class AccountTracker extends EventEmitter {
constructor (opts = {}) {
- super({
+ super()
+
+ const initState = {
accounts: {},
- transactions: {},
- currentBlockNumber: '0',
- currentBlockHash: '',
currentBlockGasLimit: '',
- })
+ }
+ this.store = new ObservableStore(initState)
+
this._provider = opts.provider
this._query = new EthQuery(this._provider)
this._blockTracker = opts.blockTracker
@@ -37,34 +39,19 @@ class EthereumStore extends ObservableStore {
//
addAccount (address) {
- const accounts = this.getState().accounts
+ const accounts = this.store.getState().accounts
accounts[address] = {}
- this.updateState({ accounts })
+ this.store.updateState({ accounts })
if (!this._currentBlockNumber) return
this._updateAccount(address)
}
removeAccount (address) {
- const accounts = this.getState().accounts
+ const accounts = this.store.getState().accounts
delete accounts[address]
- this.updateState({ accounts })
- }
-
- addTransaction (txHash) {
- const transactions = this.getState().transactions
- transactions[txHash] = {}
- this.updateState({ transactions })
- if (!this._currentBlockNumber) return
- this._updateTransaction(this._currentBlockNumber, txHash, noop)
- }
-
- removeTransaction (txHash) {
- const transactions = this.getState().transactions
- delete transactions[txHash]
- this.updateState({ transactions })
+ this.store.updateState({ accounts })
}
-
//
// private
//
@@ -72,53 +59,32 @@ class EthereumStore extends ObservableStore {
_updateForBlock (block) {
const blockNumber = '0x' + block.number.toString('hex')
this._currentBlockNumber = blockNumber
- this.updateState({ currentBlockNumber: parseInt(blockNumber) })
- this.updateState({ currentBlockHash: `0x${block.hash.toString('hex')}`})
- this.updateState({ currentBlockGasLimit: `0x${block.gasLimit.toString('hex')}` })
+
+ this.store.updateState({ currentBlockGasLimit: `0x${block.gasLimit.toString('hex')}` })
+
async.parallel([
this._updateAccounts.bind(this),
- this._updateTransactions.bind(this, blockNumber),
], (err) => {
if (err) return console.error(err)
- this.emit('block', this.getState())
+ this.emit('block', this.store.getState())
})
}
_updateAccounts (cb = noop) {
- const accounts = this.getState().accounts
+ const accounts = this.store.getState().accounts
const addresses = Object.keys(accounts)
async.each(addresses, this._updateAccount.bind(this), cb)
}
_updateAccount (address, cb = noop) {
- const accounts = this.getState().accounts
this._getAccount(address, (err, result) => {
if (err) return cb(err)
result.address = address
+ const accounts = this.store.getState().accounts
// only populate if the entry is still present
if (accounts[address]) {
accounts[address] = result
- this.updateState({ accounts })
- }
- cb(null, result)
- })
- }
-
- _updateTransactions (block, cb = noop) {
- const transactions = this.getState().transactions
- const txHashes = Object.keys(transactions)
- async.each(txHashes, this._updateTransaction.bind(this, block), cb)
- }
-
- _updateTransaction (block, txHash, cb = noop) {
- // would use the block here to determine how many confirmations the tx has
- const transactions = this.getState().transactions
- this._query.getTransaction(txHash, (err, result) => {
- if (err) return cb(err)
- // only populate if the entry is still present
- if (transactions[txHash]) {
- transactions[txHash] = result
- this.updateState({ transactions })
+ this.store.updateState({ accounts })
}
cb(null, result)
})
@@ -135,4 +101,4 @@ class EthereumStore extends ObservableStore {
}
-module.exports = EthereumStore
+module.exports = AccountTracker
diff --git a/app/scripts/lib/pending-balance-calculator.js b/app/scripts/lib/pending-balance-calculator.js
new file mode 100644
index 000000000..cea642f1a
--- /dev/null
+++ b/app/scripts/lib/pending-balance-calculator.js
@@ -0,0 +1,51 @@
+const BN = require('ethereumjs-util').BN
+const normalize = require('eth-sig-util').normalize
+
+class PendingBalanceCalculator {
+
+ // Must be initialized with two functions:
+ // getBalance => Returns a promise of a BN of the current balance in Wei
+ // getPendingTransactions => Returns an array of TxMeta Objects,
+ // which have txParams properties, which include value, gasPrice, and gas,
+ // all in a base=16 hex format.
+ constructor ({ getBalance, getPendingTransactions }) {
+ this.getPendingTransactions = getPendingTransactions
+ this.getNetworkBalance = getBalance
+ }
+
+ async getBalance() {
+ const results = await Promise.all([
+ this.getNetworkBalance(),
+ this.getPendingTransactions(),
+ ])
+
+ const [ balance, pending ] = results
+ if (!balance) return undefined
+
+ const pendingValue = pending.reduce((total, tx) => {
+ return total.add(this.calculateMaxCost(tx))
+ }, new BN(0))
+
+ return `0x${balance.sub(pendingValue).toString(16)}`
+ }
+
+ calculateMaxCost (tx) {
+ const txValue = tx.txParams.value
+ const value = this.hexToBn(txValue)
+ const gasPrice = this.hexToBn(tx.txParams.gasPrice)
+
+ const gas = tx.txParams.gas
+ const gasLimit = tx.txParams.gasLimit
+ const gasLimitBn = this.hexToBn(gas || gasLimit)
+
+ const gasCost = gasPrice.mul(gasLimitBn)
+ return value.add(gasCost)
+ }
+
+ hexToBn (hex) {
+ return new BN(normalize(hex).substring(2), 16)
+ }
+
+}
+
+module.exports = PendingBalanceCalculator