1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Delete Balance controller and pending balances calculator (#8542)

This controller was not used. It was used by the
`ComputedBalancesController`, which was removed in #7057 (as it was
also unused).

The pending balances calculator was only used by the balances
controller.
This commit is contained in:
Mark Stacey 2020-05-06 20:19:28 -03:00 committed by GitHub
parent a171bbe346
commit 7e75eb15ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 0 additions and 394 deletions

View File

@ -1,134 +0,0 @@
import ObservableStore from 'obs-store'
import PendingBalanceCalculator from '../lib/pending-balance-calculator'
import { BN } from 'ethereumjs-util'
export default class BalanceController {
/**
* Controller responsible for storing and updating an account's balance.
*
* @typedef {Object} BalanceController
* @param {Object} opts - Initialize various properties of the class.
* @property {string} address A base 16 hex string. The account address which has the balance managed by this
* BalanceController.
* @property {AccountTracker} accountTracker Stores and updates the users accounts
* for which this BalanceController manages balance.
* @property {TransactionController} txController Stores, tracks and manages transactions. Here used to create a listener for
* transaction updates.
* @property {BlockTracker} blockTracker Tracks updates to blocks. On new blocks, this BalanceController updates its balance
* @property {Object} store The store for the ethBalance
* @property {string} store.ethBalance A base 16 hex string. The balance for the current account.
* @property {PendingBalanceCalculator} balanceCalc Used to calculate the accounts balance with possible pending
* transaction costs taken into account.
*
*/
constructor (opts = {}) {
this._validateParams(opts)
const { address, accountTracker, txController, blockTracker } = opts
this.address = address
this.accountTracker = accountTracker
this.txController = txController
this.blockTracker = blockTracker
const initState = {
ethBalance: undefined,
}
this.store = new ObservableStore(initState)
this.balanceCalc = new PendingBalanceCalculator({
getBalance: () => this._getBalance(),
getPendingTransactions: this._getPendingTransactions.bind(this),
})
this._registerUpdates()
}
/**
* Updates the ethBalance property to the current pending balance
*
* @returns {Promise<void>} - Promises undefined
*/
async updateBalance () {
const balance = await this.balanceCalc.getBalance()
this.store.updateState({
ethBalance: balance,
})
}
/**
* Sets up listeners and subscriptions which should trigger an update of ethBalance. These updates include:
* - when a transaction changes state to 'submitted', 'confirmed' or 'failed'
* - when the current account changes (i.e. a new account is selected)
* - when there is a block update
*
* @private
*
*/
_registerUpdates () {
const update = this.updateBalance.bind(this)
this.txController.on('tx:status-update', (_, status) => {
switch (status) {
case 'submitted':
case 'confirmed':
case 'failed':
update()
return
default:
return
}
})
this.accountTracker.store.subscribe(update)
this.blockTracker.on('latest', update)
}
/**
* Gets the balance, as a base 16 hex string, of the account at this BalanceController's current address.
* If the current account has no balance, returns undefined.
*
* @returns {Promise<BN|void>} - Promises a BN with a value equal to the balance of the current account, or undefined
* if the current account has no balance
*
*/
async _getBalance () {
const { accounts } = this.accountTracker.store.getState()
const entry = accounts[this.address]
const balance = entry.balance
return balance ? new BN(balance.substring(2), 16) : undefined
}
/**
* Gets the pending transactions (i.e. those with a 'submitted' status). These are accessed from the
* TransactionController passed to this BalanceController during construction.
*
* @private
* @returns {Promise<array>} - Promises an array of transaction objects.
*
*/
async _getPendingTransactions () {
const pending = this.txController.getFilteredTxList({
from: this.address,
status: 'submitted',
err: undefined,
})
return pending
}
/**
* Validates that the passed options have all required properties.
*
* @param {Object} opts - The options object to validate
* @throws {string} Throw a custom error indicating that address, accountTracker, txController and blockTracker are
* missing and at least one is required
*
*/
_validateParams (opts) {
const { address, accountTracker, txController, blockTracker } = opts
if (!address || !accountTracker || !txController || !blockTracker) {
const error = 'Cannot construct a balance checker without address, accountTracker, txController, and blockTracker.'
throw new Error(error)
}
}
}

View File

@ -1,79 +0,0 @@
import { BN } from 'ethereumjs-util'
import { normalize } from 'eth-sig-util'
export default class PendingBalanceCalculator {
/**
* Used for calculating a users "pending balance": their current balance minus the total possible cost of all their
* pending transactions.
*
* @typedef {Object} PendingBalanceCalculator
* @param {Function} getBalance - Returns a promise of a BN of the current balance in Wei
* @param {Function} 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
}
/**
* Returns the users "pending balance": their current balance minus the total possible cost of all their
* pending transactions.
*
* @returns {Promise<string>} - Promises a base 16 hex string that contains the user's "pending balance"
*
*/
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)}`
}
/**
* Calculates the maximum possible cost of a single transaction, based on the value, gas price and gas limit.
*
* @param {Object} tx - Contains all that data about a transaction.
* @property {object} tx.txParams Contains data needed to calculate the maximum cost of the transaction: gas,
* gasLimit and value.
*
* @returns {string} - Returns a base 16 hex string that contains the maximum possible cost of the transaction.
*/
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)
}
/**
* Converts a hex string to a BN object
*
* @param {string} hex - A number represented as a hex string
* @returns {Object} - A BN object
*
*/
hexToBn (hex) {
return new BN(normalize(hex).substring(2), 16)
}
}

View File

@ -1,41 +0,0 @@
import { BN } from 'ethereumjs-util'
const template = {
'status': 'submitted',
'history': [{}],
'txParams': {
'from': '0x7d3517b0d011698406d6e0aed8453f0be2697926',
'gas': '0x30d40',
'value': '0x0',
'nonce': '0x3',
},
}
class TxGenerator {
constructor () {
this.txs = []
}
generate (tx = {}, opts = {}) {
const { count, fromNonce } = opts
let nonce = fromNonce || this.txs.length
const txs = []
for (let i = 0; i < count; i++) {
txs.push(Object.assign({}, template, {
txParams: {
nonce: hexify(nonce++),
},
}, tx))
}
this.txs = this.txs.concat(txs)
return txs
}
}
function hexify (number) {
return '0x' + (new BN(number)).toString(16)
}
export default TxGenerator

View File

@ -1,55 +0,0 @@
import assert from 'assert'
import ObservableStore from 'obs-store'
import PollingBlockTracker from 'eth-block-tracker'
import BalanceController from '../../../../app/scripts/controllers/balance'
import AccountTracker from '../../../../app/scripts/lib/account-tracker'
import TransactionController from '../../../../app/scripts/controllers/transactions'
import { createTestProviderTools } from '../../../stub/provider'
const provider = createTestProviderTools({ scaffold: {} }).provider
const TEST_ADDRESS = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'
const accounts = {
'0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': {
balance: '0x5e942b06dc24c4d50',
address: TEST_ADDRESS,
},
}
describe('Balance Controller', function () {
let balanceController
it('errors when address, accountTracker, txController, or blockTracker', function () {
try {
balanceController = new BalanceController()
} catch (error) {
assert.equal(error.message, 'Cannot construct a balance checker without address, accountTracker, txController, and blockTracker.')
}
})
beforeEach(function () {
balanceController = new BalanceController({
address: TEST_ADDRESS,
accountTracker: new AccountTracker({
provider,
blockTracker: new PollingBlockTracker({ provider }),
}),
txController: new TransactionController({
provider,
networkStore: new ObservableStore(),
blockTracker: new PollingBlockTracker({ provider }),
}),
blockTracker: new PollingBlockTracker({ provider }),
})
balanceController.accountTracker.store.updateState({ accounts })
})
it('updates balance controller ethBalance from account tracker', async function () {
await balanceController.updateBalance()
const balanceControllerState = balanceController.store.getState()
assert.equal(balanceControllerState.ethBalance, '0x5e942b06dc24c4d50')
})
})

View File

@ -1,85 +0,0 @@
import assert from 'assert'
import PendingBalanceCalculator from '../../../app/scripts/lib/pending-balance-calculator'
import MockTxGen from '../../lib/mock-tx-gen'
import { BN } from 'ethereumjs-util'
const zeroBn = new BN(0)
const etherBn = new BN(String(1e18))
const ether = '0x' + etherBn.toString(16)
describe('PendingBalanceCalculator', function () {
let balanceCalculator, pendingTxs
describe('#calculateMaxCost(tx)', function () {
it('returns a BN for a given tx value', function () {
const txGen = new MockTxGen()
pendingTxs = txGen.generate({
status: 'submitted',
txParams: {
value: ether,
gasPrice: '0x0',
gas: '0x0',
},
}, { count: 1 })
const balanceCalculator = generateBalanceCalcWith([], zeroBn)
const result = balanceCalculator.calculateMaxCost(pendingTxs[0])
assert.equal(result.toString(), etherBn.toString(), 'computes one ether')
})
it('calculates gas costs as well', function () {
const txGen = new MockTxGen()
pendingTxs = txGen.generate({
status: 'submitted',
txParams: {
value: '0x0',
gasPrice: '0x2',
gas: '0x3',
},
}, { count: 1 })
const balanceCalculator = generateBalanceCalcWith([], zeroBn)
const result = balanceCalculator.calculateMaxCost(pendingTxs[0])
assert.equal(result.toString(), '6', 'computes 6 wei of gas')
})
})
describe('if you have no pending txs and one ether', function () {
it('returns the network balance', async function () {
balanceCalculator = generateBalanceCalcWith([], etherBn)
const result = await balanceCalculator.getBalance()
assert.equal(result, ether, `gave ${result} needed ${ether}`)
})
})
describe('if you have a one ether pending tx and one ether', function () {
it('returns the subtracted result', async function () {
const txGen = new MockTxGen()
pendingTxs = txGen.generate({
status: 'submitted',
txParams: {
value: ether,
gasPrice: '0x0',
gas: '0x0',
},
}, { count: 1 })
balanceCalculator = generateBalanceCalcWith(pendingTxs, etherBn)
const result = await balanceCalculator.getBalance()
assert.equal(result, '0x0', `gave ${result} needed '0x0'`)
return true
})
})
})
function generateBalanceCalcWith (transactions, providerStub = zeroBn) {
const getPendingTransactions = async () => transactions
const getBalance = async () => providerStub
return new PendingBalanceCalculator({
getBalance,
getPendingTransactions,
})
}