mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Fix rounding issue when sending max tokens (#5695)
* Fix rounding issue when sending max tokens * Ensure amount row shows exact amount of max tokens on send screen (#2) * Fix tests * Change stored redux value from BigNumber to hex string. Fix TokenInput default value
This commit is contained in:
parent
7fe37276a1
commit
4c87c05a02
test
ui/app
actions.jsconversion-util.js
components
currency-display
index.scsssend
send-content
send-amount-row
send-from-row
send-gas-row
send-to-row
send-footer
send.component.jssend.utils.jstests
token-balance
token-currency-display
token-input
transaction-list-item
transaction-view-balance
unit-input
css/itcss/components
reducers
selectors
token-util.js@ -840,7 +840,7 @@ describe('MetaMask', function () {
|
||||
})
|
||||
|
||||
it('renders the balance for the new token', async () => {
|
||||
const balance = await findElement(driver, By.css('.transaction-view-balance .transaction-view-balance__token-balance'))
|
||||
const balance = await findElement(driver, By.css('.transaction-view-balance .transaction-view-balance__primary-balance'))
|
||||
await driver.wait(until.elementTextMatches(balance, /^100\s*TST\s*$/))
|
||||
const tokenAmount = await balance.getText()
|
||||
assert.ok(/^100\s*TST\s*$/.test(tokenAmount))
|
||||
@ -1019,8 +1019,8 @@ describe('MetaMask', function () {
|
||||
// test cancelled on firefox until https://github.com/mozilla/geckodriver/issues/906 is resolved,
|
||||
// or possibly until we use latest version of firefox in the tests
|
||||
if (process.env.SELENIUM_BROWSER !== 'firefox') {
|
||||
const tokenBalanceAmount = await findElement(driver, By.css('.transaction-view-balance__token-balance'))
|
||||
assert.equal(await tokenBalanceAmount.getText(), '43 TST')
|
||||
const tokenBalanceAmount = await findElements(driver, By.css('.transaction-view-balance__primary-balance'))
|
||||
await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /43\s*TST/))
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -1180,7 +1180,7 @@ describe('MetaMask', function () {
|
||||
})
|
||||
|
||||
it('renders the balance for the chosen token', async () => {
|
||||
const balance = await findElement(driver, By.css('.transaction-view-balance__token-balance'))
|
||||
const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance'))
|
||||
await driver.wait(until.elementTextMatches(balance, /0\s*BAT/))
|
||||
await delay(regularDelayMs)
|
||||
})
|
||||
|
@ -148,7 +148,7 @@ describe('Selectors', function () {
|
||||
|
||||
it('#getSelectedTokenToFiatRate', () => {
|
||||
const selectedTokenToFiatRate = selectors.getSelectedTokenToFiatRate(mockState)
|
||||
assert.equal(selectedTokenToFiatRate, '0.21880988420033493')
|
||||
assert.equal(selectedTokenToFiatRate, '0.21880988420033492152')
|
||||
})
|
||||
|
||||
describe('#getSelectedTokenContract', () => {
|
||||
|
@ -995,7 +995,7 @@ function updateSendTokenBalance ({
|
||||
.then(usersToken => {
|
||||
if (usersToken) {
|
||||
const newTokenBalance = calcTokenBalance({ selectedToken, usersToken })
|
||||
dispatch(setSendTokenBalance(newTokenBalance.toString(10)))
|
||||
dispatch(setSendTokenBalance(newTokenBalance))
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
|
@ -20,15 +20,24 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
currency,
|
||||
denomination,
|
||||
hideLabel,
|
||||
displayValue: propsDisplayValue,
|
||||
suffix: propsSuffix,
|
||||
...restOwnProps
|
||||
} = ownProps
|
||||
|
||||
const toCurrency = currency || currentCurrency
|
||||
const convertedValue = getValueFromWeiHex({
|
||||
value, fromCurrency: nativeCurrency, toCurrency, conversionRate, numberOfDecimals, toDenomination: denomination,
|
||||
})
|
||||
const displayValue = formatCurrency(convertedValue, toCurrency)
|
||||
const suffix = hideLabel ? undefined : toCurrency.toUpperCase()
|
||||
|
||||
const displayValue = propsDisplayValue || formatCurrency(
|
||||
getValueFromWeiHex({
|
||||
value,
|
||||
fromCurrency: nativeCurrency,
|
||||
toCurrency, conversionRate,
|
||||
numberOfDecimals,
|
||||
toDenomination: denomination,
|
||||
}),
|
||||
toCurrency
|
||||
)
|
||||
const suffix = propsSuffix || (hideLabel ? undefined : toCurrency.toUpperCase())
|
||||
|
||||
return {
|
||||
...restStateProps,
|
||||
|
@ -131,7 +131,7 @@ describe('CurrencyDisplay container', () => {
|
||||
},
|
||||
result: {
|
||||
nativeCurrency: 'ETH',
|
||||
displayValue: '1e-9',
|
||||
displayValue: '0.000000001',
|
||||
suffix: undefined,
|
||||
},
|
||||
},
|
||||
|
@ -40,6 +40,8 @@
|
||||
|
||||
@import './tabs/index';
|
||||
|
||||
@import './token-balance/index';
|
||||
|
||||
@import './transaction-activity-log/index';
|
||||
|
||||
@import './transaction-breakdown/index';
|
||||
|
@ -11,11 +11,11 @@ export default class AmountMaxButton extends Component {
|
||||
setAmountToMax: PropTypes.func,
|
||||
setMaxModeTo: PropTypes.func,
|
||||
tokenBalance: PropTypes.string,
|
||||
};
|
||||
}
|
||||
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
setMaxAmount () {
|
||||
const {
|
||||
|
@ -5,16 +5,23 @@ const {
|
||||
const ethUtil = require('ethereumjs-util')
|
||||
|
||||
function calcMaxAmount ({ balance, gasTotal, selectedToken, tokenBalance }) {
|
||||
const { decimals } = selectedToken || {}
|
||||
const multiplier = Math.pow(10, Number(decimals || 0))
|
||||
const { decimals } = selectedToken || {}
|
||||
const multiplier = Math.pow(10, Number(decimals || 0))
|
||||
|
||||
return selectedToken
|
||||
? multiplyCurrencies(tokenBalance, multiplier, {toNumericBase: 'hex'})
|
||||
: subtractCurrencies(
|
||||
ethUtil.addHexPrefix(balance),
|
||||
ethUtil.addHexPrefix(gasTotal),
|
||||
{ toNumericBase: 'hex' }
|
||||
)
|
||||
return selectedToken
|
||||
? multiplyCurrencies(
|
||||
tokenBalance,
|
||||
multiplier,
|
||||
{
|
||||
toNumericBase: 'hex',
|
||||
multiplicandBase: 16,
|
||||
}
|
||||
)
|
||||
: subtractCurrencies(
|
||||
ethUtil.addHexPrefix(balance),
|
||||
ethUtil.addHexPrefix(gasTotal),
|
||||
{ toNumericBase: 'hex' }
|
||||
)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
@ -19,7 +19,7 @@ describe('amount-max-button utils', () => {
|
||||
selectedToken: {
|
||||
decimals: 10,
|
||||
},
|
||||
tokenBalance: 100,
|
||||
tokenBalance: '64',
|
||||
}), 'e8d4a51000')
|
||||
})
|
||||
})
|
||||
|
@ -26,11 +26,11 @@ export default class SendAmountRow extends Component {
|
||||
updateSendAmount: PropTypes.func,
|
||||
updateSendAmountError: PropTypes.func,
|
||||
updateGas: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
validateAmount (amount) {
|
||||
const {
|
||||
@ -58,7 +58,6 @@ export default class SendAmountRow extends Component {
|
||||
|
||||
if (selectedToken) {
|
||||
updateGasFeeError({
|
||||
amount,
|
||||
amountConversionRate,
|
||||
balance,
|
||||
conversionRate,
|
||||
|
@ -45,10 +45,10 @@ function mapDispatchToProps (dispatch) {
|
||||
setMaxModeTo: bool => dispatch(setMaxModeTo(bool)),
|
||||
updateSendAmount: newAmount => dispatch(updateSendAmount(newAmount)),
|
||||
updateGasFeeError: (amountDataObject) => {
|
||||
dispatch(updateSendErrors(getGasFeeErrorObject(amountDataObject)))
|
||||
dispatch(updateSendErrors(getGasFeeErrorObject(amountDataObject)))
|
||||
},
|
||||
updateSendAmountError: (amountDataObject) => {
|
||||
dispatch(updateSendErrors(getAmountErrorObject(amountDataObject)))
|
||||
dispatch(updateSendErrors(getAmountErrorObject(amountDataObject)))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +82,6 @@ describe('SendAmountRow Component', function () {
|
||||
assert.deepEqual(
|
||||
propsMethodSpies.updateGasFeeError.getCall(0).args,
|
||||
[{
|
||||
amount: 'someAmount',
|
||||
amountConversionRate: 'mockAmountConversionRate',
|
||||
balance: 'mockBalance',
|
||||
conversionRate: 7,
|
||||
|
@ -12,11 +12,11 @@ export default class FromDropdown extends Component {
|
||||
onSelect: PropTypes.func,
|
||||
openDropdown: PropTypes.func,
|
||||
selectedAccount: PropTypes.object,
|
||||
};
|
||||
}
|
||||
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
render () {
|
||||
const {
|
||||
|
@ -15,11 +15,11 @@ export default class SendFromRow extends Component {
|
||||
tokenContract: PropTypes.object,
|
||||
updateSendFrom: PropTypes.func,
|
||||
setSendTokenBalance: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
async handleFromChange (newFrom) {
|
||||
const {
|
||||
@ -32,6 +32,7 @@ export default class SendFromRow extends Component {
|
||||
const usersToken = await tokenContract.balanceOf(newFrom.address)
|
||||
setSendTokenBalance(usersToken)
|
||||
}
|
||||
|
||||
updateSendFrom(newFrom)
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,8 @@ import {
|
||||
} from './send-from-row.selectors.js'
|
||||
import { calcTokenBalance } from '../../send.utils.js'
|
||||
import {
|
||||
updateSendFrom,
|
||||
setSendTokenBalance,
|
||||
updateSendFrom,
|
||||
setSendTokenBalance,
|
||||
} from '../../../../actions'
|
||||
import {
|
||||
closeFromDropdown,
|
||||
@ -37,10 +37,10 @@ function mapDispatchToProps (dispatch) {
|
||||
openFromDropdown: () => dispatch(openFromDropdown()),
|
||||
updateSendFrom: newFrom => dispatch(updateSendFrom(newFrom)),
|
||||
setSendTokenBalance: (usersToken, selectedToken) => {
|
||||
if (!usersToken) return
|
||||
if (!usersToken) return
|
||||
|
||||
const tokenBalance = calcTokenBalance({ usersToken, selectedToken })
|
||||
dispatch(setSendTokenBalance(tokenBalance))
|
||||
const tokenBalance = calcTokenBalance({ usersToken, selectedToken })
|
||||
dispatch(setSendTokenBalance(tokenBalance))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -12,11 +12,11 @@ export default class SendGasRow extends Component {
|
||||
gasLoadingError: PropTypes.bool,
|
||||
gasTotal: PropTypes.string,
|
||||
showCustomizeGasModal: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
render () {
|
||||
const {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { connect } from 'react-redux'
|
||||
import {
|
||||
getConversionRate,
|
||||
getCurrentCurrency,
|
||||
getGasTotal,
|
||||
getConversionRate,
|
||||
getCurrentCurrency,
|
||||
getGasTotal,
|
||||
} from '../../send.selectors.js'
|
||||
import { getGasLoadingError, gasFeeIsInError } from './send-gas-row.selectors.js'
|
||||
import { showModal } from '../../../../actions'
|
||||
|
@ -19,11 +19,11 @@ export default class SendToRow extends Component {
|
||||
updateSendTo: PropTypes.func,
|
||||
updateSendToError: PropTypes.func,
|
||||
scanQrCode: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
handleToChange (to, nickname = '', toError) {
|
||||
const { hasHexData, updateSendTo, updateSendToError, updateGas } = this.props
|
||||
|
@ -26,11 +26,11 @@ export default class SendFooter extends Component {
|
||||
tokenBalance: PropTypes.string,
|
||||
unapprovedTxs: PropTypes.object,
|
||||
update: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
onCancel () {
|
||||
this.props.clearSend()
|
||||
|
@ -41,11 +41,11 @@ export default class SendTransactionScreen extends PersistentForm {
|
||||
scanQrCode: PropTypes.func,
|
||||
qrCodeDetected: PropTypes.func,
|
||||
qrCodeData: PropTypes.object,
|
||||
};
|
||||
}
|
||||
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.qrCodeData) {
|
||||
@ -138,14 +138,12 @@ export default class SendTransactionScreen extends PersistentForm {
|
||||
})
|
||||
const gasFeeErrorObject = selectedToken
|
||||
? getGasFeeErrorObject({
|
||||
amount,
|
||||
amountConversionRate,
|
||||
balance,
|
||||
conversionRate,
|
||||
gasTotal,
|
||||
primaryCurrency,
|
||||
selectedToken,
|
||||
tokenBalance,
|
||||
})
|
||||
: { gasFee: null }
|
||||
updateSendErrors(Object.assign(amountErrorObject, gasFeeErrorObject))
|
||||
|
@ -89,11 +89,10 @@ function isTokenBalanceSufficient ({
|
||||
const tokenBalanceIsSufficient = conversionGTE(
|
||||
{
|
||||
value: tokenBalance,
|
||||
fromNumericBase: 'dec',
|
||||
fromNumericBase: 'hex',
|
||||
},
|
||||
{
|
||||
value: calcTokenAmount(amountInDec, decimals),
|
||||
fromNumericBase: 'dec',
|
||||
},
|
||||
)
|
||||
|
||||
@ -151,7 +150,6 @@ function getAmountErrorObject ({
|
||||
}
|
||||
|
||||
function getGasFeeErrorObject ({
|
||||
amount,
|
||||
amountConversionRate,
|
||||
balance,
|
||||
conversionRate,
|
||||
@ -180,7 +178,7 @@ function getGasFeeErrorObject ({
|
||||
|
||||
function calcTokenBalance ({ selectedToken, usersToken }) {
|
||||
const { decimals } = selectedToken || {}
|
||||
return calcTokenAmount(usersToken.balance.toString(), decimals) + ''
|
||||
return calcTokenAmount(usersToken.balance.toString(), decimals).toString(16)
|
||||
}
|
||||
|
||||
function doesAmountErrorRequireUpdate ({
|
||||
|
@ -158,14 +158,12 @@ describe('Send Component', function () {
|
||||
assert.deepEqual(
|
||||
utilsMethodStubs.getGasFeeErrorObject.getCall(0).args[0],
|
||||
{
|
||||
amount: 'mockAmount',
|
||||
amountConversionRate: 'mockAmountConversionRate',
|
||||
balance: 'mockBalance',
|
||||
conversionRate: 10,
|
||||
gasTotal: 'mockGasTotal',
|
||||
primaryCurrency: 'mockPrimaryCurrency',
|
||||
selectedToken: 'mockSelectedToken',
|
||||
tokenBalance: 'mockTokenBalance',
|
||||
}
|
||||
)
|
||||
})
|
||||
|
@ -285,11 +285,10 @@ describe('send utils', () => {
|
||||
[
|
||||
{
|
||||
value: 123,
|
||||
fromNumericBase: 'dec',
|
||||
fromNumericBase: 'hex',
|
||||
},
|
||||
{
|
||||
value: 'calc:1610',
|
||||
fromNumericBase: 'dec',
|
||||
},
|
||||
]
|
||||
)
|
||||
|
14
ui/app/components/token-balance/index.scss
Normal file
14
ui/app/components/token-balance/index.scss
Normal file
@ -0,0 +1,14 @@
|
||||
.token-balance-component {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&__text {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&__suffix {
|
||||
padding-left: 4px;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import CurrencyDisplay from '../currency-display'
|
||||
|
||||
export default class TokenBalance extends PureComponent {
|
||||
static propTypes = {
|
||||
@ -12,12 +12,14 @@ export default class TokenBalance extends PureComponent {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { className, string, withSymbol, symbol } = this.props
|
||||
const { className, string, symbol } = this.props
|
||||
|
||||
return (
|
||||
<div className={classnames('hide-text-overflow', className)}>
|
||||
{ string + (withSymbol ? ` ${symbol}` : '') }
|
||||
</div>
|
||||
<CurrencyDisplay
|
||||
className={className}
|
||||
displayValue={string}
|
||||
suffix={symbol}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import CurrencyDisplay from '../currency-display/currency-display.component'
|
||||
import CurrencyDisplay from '../currency-display'
|
||||
import { getTokenData } from '../../helpers/transactions.util'
|
||||
import { getTokenValue, calcTokenAmount } from '../../token-util'
|
||||
|
||||
@ -12,6 +12,7 @@ export default class TokenCurrencyDisplay extends PureComponent {
|
||||
|
||||
state = {
|
||||
displayValue: '',
|
||||
suffix: '',
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
@ -29,25 +30,27 @@ export default class TokenCurrencyDisplay extends PureComponent {
|
||||
|
||||
setDisplayValue () {
|
||||
const { transactionData: data, token } = this.props
|
||||
const { decimals = '', symbol = '' } = token
|
||||
const { decimals = '', symbol: suffix = '' } = token
|
||||
const tokenData = getTokenData(data)
|
||||
|
||||
let displayValue
|
||||
|
||||
if (tokenData.params && tokenData.params.length) {
|
||||
const tokenValue = getTokenValue(tokenData.params)
|
||||
const tokenAmount = calcTokenAmount(tokenValue, decimals)
|
||||
displayValue = `${tokenAmount} ${symbol}`
|
||||
displayValue = calcTokenAmount(tokenValue, decimals).toString()
|
||||
}
|
||||
|
||||
this.setState({ displayValue })
|
||||
this.setState({ displayValue, suffix })
|
||||
}
|
||||
|
||||
render () {
|
||||
const { displayValue, suffix } = this.state
|
||||
|
||||
return (
|
||||
<CurrencyDisplay
|
||||
{...this.props}
|
||||
displayValue={this.state.displayValue}
|
||||
displayValue={displayValue}
|
||||
suffix={suffix}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ export default class TokenInput extends PureComponent {
|
||||
super(props)
|
||||
|
||||
const { value: hexValue } = props
|
||||
const decimalValue = hexValue ? this.getDecimalValue(props) : 0
|
||||
const decimalValue = hexValue ? this.getValue(props) : 0
|
||||
|
||||
this.state = {
|
||||
decimalValue,
|
||||
@ -46,12 +46,12 @@ export default class TokenInput extends PureComponent {
|
||||
const { hexValue: stateHexValue } = this.state
|
||||
|
||||
if (prevPropsHexValue !== propsHexValue && propsHexValue !== stateHexValue) {
|
||||
const decimalValue = this.getDecimalValue(this.props)
|
||||
const decimalValue = this.getValue(this.props)
|
||||
this.setState({ hexValue: propsHexValue, decimalValue })
|
||||
}
|
||||
}
|
||||
|
||||
getDecimalValue (props) {
|
||||
getValue (props) {
|
||||
const { value: hexValue, selectedToken: { decimals, symbol } = {} } = props
|
||||
|
||||
const multiplier = Math.pow(10, Number(decimals || 0))
|
||||
@ -63,7 +63,7 @@ export default class TokenInput extends PureComponent {
|
||||
invertConversionRate: true,
|
||||
})
|
||||
|
||||
return Number(decimalValueString) || 0
|
||||
return Number(decimalValueString) ? decimalValueString : ''
|
||||
}
|
||||
|
||||
handleChange = decimalValue => {
|
||||
|
@ -80,6 +80,8 @@
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
|
||||
&--primary {
|
||||
text-align: end;
|
||||
|
@ -6,6 +6,12 @@
|
||||
height: 54px;
|
||||
min-width: 0;
|
||||
|
||||
@media screen and (max-width: $break-small) {
|
||||
flex-direction: column;
|
||||
height: initial;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__balance {
|
||||
margin: 0 12px;
|
||||
display: flex;
|
||||
@ -15,17 +21,8 @@
|
||||
@media screen and (max-width: $break-small) {
|
||||
align-items: center;
|
||||
margin: 16px 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__token-balance {
|
||||
margin-left: 12px;
|
||||
font-size: 1.5rem;
|
||||
|
||||
@media screen and (max-width: $break-small) {
|
||||
margin: 12px 0;
|
||||
margin-left: 0;
|
||||
font-size: 1.75rem;
|
||||
padding: 0 16px;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,6 +31,7 @@
|
||||
|
||||
@media screen and (max-width: $break-small) {
|
||||
font-size: 1.75rem;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,6 +49,7 @@
|
||||
|
||||
@media screen and (max-width: $break-small) {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,9 +70,4 @@
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $break-small) {
|
||||
flex-direction: column;
|
||||
height: initial
|
||||
}
|
||||
}
|
||||
|
@ -26,11 +26,13 @@ export default class TransactionViewBalance extends PureComponent {
|
||||
|
||||
return selectedToken
|
||||
? (
|
||||
<TokenBalance
|
||||
token={selectedToken}
|
||||
withSymbol
|
||||
className="transaction-view-balance__token-balance"
|
||||
/>
|
||||
<div className="transaction-view-balance__balance">
|
||||
<TokenBalance
|
||||
token={selectedToken}
|
||||
withSymbol
|
||||
className="transaction-view-balance__primary-balance"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="transaction-view-balance__balance">
|
||||
<UserPreferencedCurrencyDisplay
|
||||
|
@ -38,6 +38,10 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__suffix {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
&--error {
|
||||
border-color: $red;
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ export default class UnitInput extends PureComponent {
|
||||
const valueString = String(value)
|
||||
const valueLength = valueString.length || 1
|
||||
const decimalPointDeficit = valueString.match(/\./) ? -0.5 : 0
|
||||
return (valueLength + decimalPointDeficit + 0.75) + 'ch'
|
||||
return (valueLength + decimalPointDeficit + 0.5) + 'ch'
|
||||
}
|
||||
|
||||
render () {
|
||||
|
@ -62,7 +62,7 @@ const toSpecifiedDenomination = {
|
||||
}
|
||||
const baseChange = {
|
||||
hex: n => n.toString(16),
|
||||
dec: n => Number(n).toString(10),
|
||||
dec: n => (new BigNumber(n)).toString(10),
|
||||
BN: n => new BN(n.toString(16)),
|
||||
}
|
||||
|
||||
|
@ -552,6 +552,7 @@
|
||||
|
||||
&__form-field {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
|
||||
.currency-display {
|
||||
color: $tundora;
|
||||
@ -580,6 +581,7 @@
|
||||
line-height: 22px;
|
||||
width: 88px;
|
||||
font-weight: 400;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
&__from-dropdown {
|
||||
|
@ -33,7 +33,7 @@ function reduceMetamask (state, action) {
|
||||
gasLimit: null,
|
||||
gasPrice: null,
|
||||
gasTotal: null,
|
||||
tokenBalance: null,
|
||||
tokenBalance: '0x0',
|
||||
from: '',
|
||||
to: '',
|
||||
amount: '0x0',
|
||||
|
@ -137,11 +137,12 @@ export const tokenAmountAndToAddressSelector = createSelector(
|
||||
const valueParam = params.find(param => param.name === TOKEN_PARAM_VALUE)
|
||||
toAddress = toParam ? toParam.value : params[0].value
|
||||
const value = valueParam ? Number(valueParam.value) : Number(params[1].value)
|
||||
tokenAmount = roundExponential(value)
|
||||
|
||||
if (tokenDecimals) {
|
||||
tokenAmount = calcTokenAmount(value, tokenDecimals)
|
||||
tokenAmount = calcTokenAmount(value, tokenDecimals).toNumber()
|
||||
}
|
||||
|
||||
tokenAmount = roundExponential(tokenAmount)
|
||||
}
|
||||
|
||||
return {
|
||||
@ -163,7 +164,7 @@ export const approveTokenAmountAndToAddressSelector = createSelector(
|
||||
const value = Number(params.find(param => param.name === TOKEN_PARAM_VALUE).value)
|
||||
|
||||
if (tokenDecimals) {
|
||||
tokenAmount = calcTokenAmount(value, tokenDecimals)
|
||||
tokenAmount = calcTokenAmount(value, tokenDecimals).toNumber()
|
||||
}
|
||||
|
||||
tokenAmount = roundExponential(tokenAmount)
|
||||
@ -188,7 +189,7 @@ export const sendTokenTokenAmountAndToAddressSelector = createSelector(
|
||||
let value = Number(params.find(param => param.name === TOKEN_PARAM_VALUE).value)
|
||||
|
||||
if (tokenDecimals) {
|
||||
value = calcTokenAmount(value, tokenDecimals)
|
||||
value = calcTokenAmount(value, tokenDecimals).toNumber()
|
||||
}
|
||||
|
||||
tokenAmount = roundExponential(value)
|
||||
|
@ -109,7 +109,7 @@ export function tokenInfoGetter () {
|
||||
|
||||
export function calcTokenAmount (value, decimals) {
|
||||
const multiplier = Math.pow(10, Number(decimals || 0))
|
||||
return new BigNumber(String(value)).div(multiplier).toNumber()
|
||||
return new BigNumber(String(value)).div(multiplier)
|
||||
}
|
||||
|
||||
export function getTokenValue (tokenParams = []) {
|
||||
|
Loading…
Reference in New Issue
Block a user