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:
parent
a171bbe346
commit
7e75eb15ef
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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
|
|
@ -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')
|
|
||||||
})
|
|
||||||
})
|
|
@ -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,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user