mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
factor out containers for currency components (#8543)
This commit is contained in:
parent
54b423d407
commit
0aa41e397e
@ -196,6 +196,7 @@
|
||||
"@storybook/core": "^5.3.14",
|
||||
"@storybook/react": "^5.3.14",
|
||||
"@storybook/storybook-deployer": "^2.8.1",
|
||||
"@testing-library/react-hooks": "^3.2.1",
|
||||
"addons-linter": "1.14.0",
|
||||
"babel-eslint": "^10.0.2",
|
||||
"babel-loader": "^8.0.6",
|
||||
|
@ -1 +1 @@
|
||||
export { default } from './user-preferenced-currency-display.container'
|
||||
export { default } from './user-preferenced-currency-display.component'
|
||||
|
@ -3,9 +3,17 @@ import assert from 'assert'
|
||||
import { shallow } from 'enzyme'
|
||||
import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display.component'
|
||||
import CurrencyDisplay from '../../../ui/currency-display'
|
||||
import * as currencyHook from '../../../../hooks/useCurrencyDisplay'
|
||||
import * as currencyPrefHook from '../../../../hooks/useUserPreferencedCurrency'
|
||||
import sinon from 'sinon'
|
||||
|
||||
|
||||
describe('UserPreferencedCurrencyDisplay Component', function () {
|
||||
describe('rendering', function () {
|
||||
beforeEach(function () {
|
||||
sinon.stub(currencyHook, 'useCurrencyDisplay').returns(['1', {}])
|
||||
sinon.stub(currencyPrefHook, 'useUserPreferencedCurrency').returns({ currency: 'ETH', decimals: 6 })
|
||||
})
|
||||
it('should render properly', function () {
|
||||
const wrapper = shallow(
|
||||
<UserPreferencedCurrencyDisplay />
|
||||
@ -30,5 +38,8 @@ describe('UserPreferencedCurrencyDisplay Component', function () {
|
||||
assert.equal(wrapper.find(CurrencyDisplay).props().prop2, 'test')
|
||||
assert.equal(wrapper.find(CurrencyDisplay).props().prop3, 1)
|
||||
})
|
||||
afterEach(function () {
|
||||
sinon.restore()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -1,202 +0,0 @@
|
||||
import assert from 'assert'
|
||||
import proxyquire from 'proxyquire'
|
||||
|
||||
let mapStateToProps, mergeProps
|
||||
|
||||
proxyquire('../user-preferenced-currency-display.container.js', {
|
||||
'react-redux': {
|
||||
connect: (ms, _, mp) => {
|
||||
mapStateToProps = ms
|
||||
mergeProps = mp
|
||||
return () => ({})
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
describe('UserPreferencedCurrencyDisplay container', function () {
|
||||
describe('mapStateToProps()', function () {
|
||||
it('should return the correct props', function () {
|
||||
const mockState = {
|
||||
metamask: {
|
||||
nativeCurrency: 'ETH',
|
||||
preferences: {
|
||||
useNativeCurrencyAsPrimaryCurrency: true,
|
||||
showFiatInTestnets: false,
|
||||
},
|
||||
provider: {
|
||||
type: 'mainnet',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
assert.deepEqual(mapStateToProps(mockState), {
|
||||
nativeCurrency: 'ETH',
|
||||
useNativeCurrencyAsPrimaryCurrency: true,
|
||||
isMainnet: true,
|
||||
showFiatInTestnets: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('should return the correct props when not in mainnet and showFiatInTestnets is true', function () {
|
||||
const mockState = {
|
||||
metamask: {
|
||||
nativeCurrency: 'ETH',
|
||||
preferences: {
|
||||
useNativeCurrencyAsPrimaryCurrency: true,
|
||||
showFiatInTestnets: true,
|
||||
},
|
||||
provider: {
|
||||
type: 'rinkeby',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
assert.deepEqual(mapStateToProps(mockState), {
|
||||
nativeCurrency: 'ETH',
|
||||
useNativeCurrencyAsPrimaryCurrency: true,
|
||||
isMainnet: false,
|
||||
showFiatInTestnets: true,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('mergeProps()', function () {
|
||||
it('should return the correct props', function () {
|
||||
const mockDispatchProps = {}
|
||||
|
||||
const tests = [
|
||||
{
|
||||
stateProps: {
|
||||
useNativeCurrencyAsPrimaryCurrency: true,
|
||||
nativeCurrency: 'ETH',
|
||||
isMainnet: true,
|
||||
showFiatInTestnets: false,
|
||||
},
|
||||
ownProps: {
|
||||
type: 'PRIMARY',
|
||||
},
|
||||
result: {
|
||||
currency: 'ETH',
|
||||
nativeCurrency: 'ETH',
|
||||
numberOfDecimals: 6,
|
||||
prefix: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
stateProps: {
|
||||
useNativeCurrencyAsPrimaryCurrency: false,
|
||||
nativeCurrency: 'ETH',
|
||||
isMainnet: true,
|
||||
showFiatInTestnets: false,
|
||||
},
|
||||
ownProps: {
|
||||
type: 'PRIMARY',
|
||||
},
|
||||
result: {
|
||||
currency: undefined,
|
||||
nativeCurrency: 'ETH',
|
||||
numberOfDecimals: 2,
|
||||
prefix: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
stateProps: {
|
||||
useNativeCurrencyAsPrimaryCurrency: true,
|
||||
nativeCurrency: 'ETH',
|
||||
isMainnet: true,
|
||||
showFiatInTestnets: false,
|
||||
},
|
||||
ownProps: {
|
||||
type: 'SECONDARY',
|
||||
fiatNumberOfDecimals: 4,
|
||||
fiatPrefix: '-',
|
||||
},
|
||||
result: {
|
||||
nativeCurrency: 'ETH',
|
||||
currency: undefined,
|
||||
numberOfDecimals: 4,
|
||||
prefix: '-',
|
||||
},
|
||||
},
|
||||
{
|
||||
stateProps: {
|
||||
useNativeCurrencyAsPrimaryCurrency: false,
|
||||
nativeCurrency: 'ETH',
|
||||
isMainnet: true,
|
||||
showFiatInTestnets: false,
|
||||
},
|
||||
ownProps: {
|
||||
type: 'SECONDARY',
|
||||
fiatNumberOfDecimals: 4,
|
||||
numberOfDecimals: 3,
|
||||
fiatPrefix: 'a',
|
||||
prefix: 'b',
|
||||
},
|
||||
result: {
|
||||
currency: 'ETH',
|
||||
nativeCurrency: 'ETH',
|
||||
numberOfDecimals: 3,
|
||||
prefix: 'b',
|
||||
},
|
||||
},
|
||||
{
|
||||
stateProps: {
|
||||
useNativeCurrencyAsPrimaryCurrency: false,
|
||||
nativeCurrency: 'ETH',
|
||||
isMainnet: false,
|
||||
showFiatInTestnets: false,
|
||||
},
|
||||
ownProps: {
|
||||
type: 'PRIMARY',
|
||||
},
|
||||
result: {
|
||||
currency: 'ETH',
|
||||
nativeCurrency: 'ETH',
|
||||
numberOfDecimals: 6,
|
||||
prefix: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
stateProps: {
|
||||
useNativeCurrencyAsPrimaryCurrency: false,
|
||||
nativeCurrency: 'ETH',
|
||||
isMainnet: false,
|
||||
showFiatInTestnets: true,
|
||||
},
|
||||
ownProps: {
|
||||
type: 'PRIMARY',
|
||||
},
|
||||
result: {
|
||||
currency: undefined,
|
||||
nativeCurrency: 'ETH',
|
||||
numberOfDecimals: 2,
|
||||
prefix: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
stateProps: {
|
||||
useNativeCurrencyAsPrimaryCurrency: false,
|
||||
nativeCurrency: 'ETH',
|
||||
isMainnet: true,
|
||||
showFiatInTestnets: true,
|
||||
},
|
||||
ownProps: {
|
||||
type: 'PRIMARY',
|
||||
},
|
||||
result: {
|
||||
currency: undefined,
|
||||
nativeCurrency: 'ETH',
|
||||
numberOfDecimals: 2,
|
||||
prefix: undefined,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
tests.forEach(({ stateProps, ownProps, result }) => {
|
||||
assert.deepEqual(mergeProps({ ...stateProps }, mockDispatchProps, { ...ownProps }), {
|
||||
...result,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@ -1,47 +1,42 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import React, { useMemo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { PRIMARY, SECONDARY, ETH } from '../../../helpers/constants/common'
|
||||
import CurrencyDisplay from '../../ui/currency-display'
|
||||
import { useUserPreferencedCurrency } from '../../../hooks/useUserPreferencedCurrency'
|
||||
|
||||
export default class UserPreferencedCurrencyDisplay extends PureComponent {
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
prefix: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
numberOfDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
hideLabel: PropTypes.bool,
|
||||
hideTitle: PropTypes.bool,
|
||||
style: PropTypes.object,
|
||||
showEthLogo: PropTypes.bool,
|
||||
ethLogoHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
// Used in container
|
||||
type: PropTypes.oneOf([PRIMARY, SECONDARY]),
|
||||
ethNumberOfDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
fiatNumberOfDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
ethPrefix: PropTypes.string,
|
||||
fiatPrefix: PropTypes.string,
|
||||
// From container
|
||||
currency: PropTypes.string,
|
||||
nativeCurrency: PropTypes.string,
|
||||
}
|
||||
|
||||
renderEthLogo () {
|
||||
const { currency, showEthLogo, ethLogoHeight = 12 } = this.props
|
||||
export default function UserPreferencedCurrencyDisplay ({ type, showEthLogo, ethLogoHeight = 12, ethNumberOfDecimals, fiatNumberOfDecimals, numberOfDecimals: propsNumberOfDecimals, ...restProps }) {
|
||||
const { currency, numberOfDecimals } = useUserPreferencedCurrency(type, { ethNumberOfDecimals, fiatNumberOfDecimals, numberOfDecimals: propsNumberOfDecimals })
|
||||
|
||||
const prefixComponent = useMemo(() => {
|
||||
return currency === ETH && showEthLogo && (
|
||||
<img
|
||||
src="/images/eth.svg"
|
||||
height={ethLogoHeight}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}, [currency, showEthLogo, ethLogoHeight])
|
||||
|
||||
render () {
|
||||
return (
|
||||
<CurrencyDisplay
|
||||
{...this.props}
|
||||
prefixComponent={this.renderEthLogo()}
|
||||
/>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<CurrencyDisplay
|
||||
{...restProps}
|
||||
currency={currency}
|
||||
numberOfDecimals={numberOfDecimals}
|
||||
prefixComponent={prefixComponent}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
UserPreferencedCurrencyDisplay.propTypes = {
|
||||
className: PropTypes.string,
|
||||
prefix: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
numberOfDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
hideLabel: PropTypes.bool,
|
||||
hideTitle: PropTypes.bool,
|
||||
style: PropTypes.object,
|
||||
showEthLogo: PropTypes.bool,
|
||||
ethLogoHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
type: PropTypes.oneOf([PRIMARY, SECONDARY]),
|
||||
ethNumberOfDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
fiatNumberOfDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
import { connect } from 'react-redux'
|
||||
import UserPreferencedCurrencyDisplay from './user-preferenced-currency-display.component'
|
||||
import { preferencesSelector, getIsMainnet } from '../../../selectors'
|
||||
import { ETH, PRIMARY, SECONDARY } from '../../../helpers/constants/common'
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const {
|
||||
useNativeCurrencyAsPrimaryCurrency,
|
||||
showFiatInTestnets,
|
||||
} = preferencesSelector(state)
|
||||
|
||||
const isMainnet = getIsMainnet(state)
|
||||
|
||||
return {
|
||||
useNativeCurrencyAsPrimaryCurrency,
|
||||
showFiatInTestnets,
|
||||
isMainnet,
|
||||
nativeCurrency: state.metamask.nativeCurrency,
|
||||
}
|
||||
}
|
||||
|
||||
const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
const { useNativeCurrencyAsPrimaryCurrency, showFiatInTestnets, isMainnet, nativeCurrency, ...restStateProps } = stateProps
|
||||
const {
|
||||
type,
|
||||
numberOfDecimals: propsNumberOfDecimals,
|
||||
ethNumberOfDecimals,
|
||||
fiatNumberOfDecimals,
|
||||
ethPrefix,
|
||||
fiatPrefix,
|
||||
prefix: propsPrefix,
|
||||
...restOwnProps
|
||||
} = ownProps
|
||||
|
||||
let currency, numberOfDecimals, prefix
|
||||
|
||||
if ((type === PRIMARY && useNativeCurrencyAsPrimaryCurrency) ||
|
||||
(type === SECONDARY && !useNativeCurrencyAsPrimaryCurrency)) {
|
||||
// Display ETH
|
||||
currency = nativeCurrency || ETH
|
||||
numberOfDecimals = propsNumberOfDecimals || ethNumberOfDecimals || 6
|
||||
prefix = propsPrefix || ethPrefix
|
||||
} else if ((type === SECONDARY && useNativeCurrencyAsPrimaryCurrency) ||
|
||||
(type === PRIMARY && !useNativeCurrencyAsPrimaryCurrency)) {
|
||||
// Display Fiat
|
||||
numberOfDecimals = propsNumberOfDecimals || fiatNumberOfDecimals || 2
|
||||
prefix = propsPrefix || fiatPrefix
|
||||
}
|
||||
|
||||
if (!isMainnet && !showFiatInTestnets) {
|
||||
currency = nativeCurrency || ETH
|
||||
numberOfDecimals = propsNumberOfDecimals || ethNumberOfDecimals || 6
|
||||
prefix = propsPrefix || ethPrefix
|
||||
}
|
||||
|
||||
return {
|
||||
...restStateProps,
|
||||
...dispatchProps,
|
||||
...restOwnProps,
|
||||
nativeCurrency,
|
||||
currency,
|
||||
numberOfDecimals,
|
||||
prefix,
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, null, mergeProps)(UserPreferencedCurrencyDisplay)
|
@ -1,40 +1,62 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import { GWEI } from '../../../helpers/constants/common'
|
||||
import { useCurrencyDisplay } from '../../../hooks/useCurrencyDisplay'
|
||||
|
||||
|
||||
export default class CurrencyDisplay extends PureComponent {
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
displayValue: PropTypes.string,
|
||||
prefix: PropTypes.string,
|
||||
prefixComponent: PropTypes.node,
|
||||
style: PropTypes.object,
|
||||
suffix: PropTypes.string,
|
||||
hideTitle: PropTypes.bool,
|
||||
}
|
||||
|
||||
render () {
|
||||
const { className, displayValue, prefix, prefixComponent, style, suffix, hideTitle } = this.props
|
||||
const text = `${prefix || ''}${displayValue}`
|
||||
const title = suffix ? `${text} ${suffix}` : text
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames('currency-display-component', className)}
|
||||
style={style}
|
||||
title={(!hideTitle && title) || null}
|
||||
>
|
||||
{ prefixComponent }
|
||||
<span className="currency-display-component__text">{ text }</span>
|
||||
{
|
||||
suffix && (
|
||||
<span className="currency-display-component__suffix">
|
||||
{ suffix }
|
||||
</span>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default function CurrencyDisplay ({
|
||||
value,
|
||||
displayValue,
|
||||
style,
|
||||
className,
|
||||
prefix,
|
||||
prefixComponent,
|
||||
hideLabel,
|
||||
hideTitle,
|
||||
numberOfDecimals,
|
||||
denomination,
|
||||
currency,
|
||||
suffix,
|
||||
}) {
|
||||
const [title, parts] = useCurrencyDisplay(value, {
|
||||
displayValue,
|
||||
prefix,
|
||||
numberOfDecimals,
|
||||
hideLabel,
|
||||
denomination,
|
||||
currency,
|
||||
suffix,
|
||||
})
|
||||
return (
|
||||
<div
|
||||
className={classnames('currency-display-component', className)}
|
||||
style={style}
|
||||
title={(!hideTitle && title) || null}
|
||||
>
|
||||
{ prefixComponent }
|
||||
<span className="currency-display-component__text">{ parts.prefix }{ parts.value }</span>
|
||||
{
|
||||
parts.suffix && (
|
||||
<span className="currency-display-component__suffix">
|
||||
{ parts.suffix }
|
||||
</span>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
CurrencyDisplay.propTypes = {
|
||||
className: PropTypes.string,
|
||||
currency: PropTypes.string,
|
||||
denomination: PropTypes.oneOf([GWEI]),
|
||||
displayValue: PropTypes.string,
|
||||
hideLabel: PropTypes.bool,
|
||||
hideTitle: PropTypes.bool,
|
||||
numberOfDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
prefix: PropTypes.string,
|
||||
prefixComponent: PropTypes.node,
|
||||
style: PropTypes.object,
|
||||
suffix: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
}
|
||||
|
@ -1,68 +0,0 @@
|
||||
import { connect } from 'react-redux'
|
||||
import PropTypes from 'prop-types'
|
||||
import CurrencyDisplay from './currency-display.component'
|
||||
import { getValueFromWeiHex, formatCurrency } from '../../../helpers/utils/confirm-tx.util'
|
||||
import { GWEI } from '../../../helpers/constants/common'
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const { metamask: { nativeCurrency, currentCurrency, conversionRate } } = state
|
||||
|
||||
return {
|
||||
currentCurrency,
|
||||
conversionRate,
|
||||
nativeCurrency,
|
||||
}
|
||||
}
|
||||
|
||||
const mergeProps = (stateProps, _, ownProps) => {
|
||||
const { nativeCurrency, currentCurrency, conversionRate } = stateProps
|
||||
const {
|
||||
value,
|
||||
numberOfDecimals = 2,
|
||||
currency,
|
||||
denomination,
|
||||
hideLabel,
|
||||
displayValue: propsDisplayValue,
|
||||
suffix: propsSuffix,
|
||||
...restOwnProps
|
||||
} = ownProps
|
||||
|
||||
const toCurrency = currency || currentCurrency
|
||||
|
||||
const displayValue = propsDisplayValue || formatCurrency(
|
||||
getValueFromWeiHex({
|
||||
value,
|
||||
fromCurrency: nativeCurrency,
|
||||
toCurrency, conversionRate,
|
||||
numberOfDecimals,
|
||||
toDenomination: denomination,
|
||||
}),
|
||||
toCurrency
|
||||
)
|
||||
const suffix = propsSuffix || (hideLabel ? undefined : toCurrency.toUpperCase())
|
||||
|
||||
return {
|
||||
...restOwnProps,
|
||||
displayValue,
|
||||
suffix,
|
||||
}
|
||||
}
|
||||
|
||||
const CurrencyDisplayContainer = connect(mapStateToProps, null, mergeProps)(CurrencyDisplay)
|
||||
|
||||
CurrencyDisplayContainer.propTypes = {
|
||||
className: PropTypes.string,
|
||||
currency: PropTypes.string,
|
||||
denomination: PropTypes.oneOf([GWEI]),
|
||||
displayValue: PropTypes.string,
|
||||
hideLabel: PropTypes.bool,
|
||||
hideTitle: PropTypes.bool,
|
||||
numberOfDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
prefix: PropTypes.string,
|
||||
prefixComponent: PropTypes.node,
|
||||
style: PropTypes.object,
|
||||
suffix: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
}
|
||||
|
||||
export default CurrencyDisplayContainer
|
@ -1 +1 @@
|
||||
export { default } from './currency-display.container'
|
||||
export { default } from './currency-display.component'
|
||||
|
@ -2,13 +2,24 @@ import React from 'react'
|
||||
import assert from 'assert'
|
||||
import { shallow } from 'enzyme'
|
||||
import CurrencyDisplay from '../currency-display.component'
|
||||
import sinon from 'sinon'
|
||||
import * as reactRedux from 'react-redux'
|
||||
|
||||
describe('CurrencyDisplay Component', function () {
|
||||
beforeEach(function () {
|
||||
const stub = sinon.stub(reactRedux, 'useSelector')
|
||||
stub.callsFake(() => ({
|
||||
currentCurrency: 'usd',
|
||||
nativeCurrency: 'ETH',
|
||||
conversionRate: 280.45,
|
||||
}))
|
||||
})
|
||||
it('should render text with a className', function () {
|
||||
const wrapper = shallow((
|
||||
<CurrencyDisplay
|
||||
displayValue="$123.45"
|
||||
className="currency-display"
|
||||
hideLabel
|
||||
/>
|
||||
))
|
||||
|
||||
@ -22,10 +33,14 @@ describe('CurrencyDisplay Component', function () {
|
||||
displayValue="$123.45"
|
||||
className="currency-display"
|
||||
prefix="-"
|
||||
hideLabel
|
||||
/>
|
||||
))
|
||||
|
||||
assert.ok(wrapper.hasClass('currency-display'))
|
||||
assert.equal(wrapper.text(), '-$123.45')
|
||||
})
|
||||
afterEach(function () {
|
||||
sinon.restore()
|
||||
})
|
||||
})
|
||||
|
@ -1,145 +0,0 @@
|
||||
import assert from 'assert'
|
||||
import proxyquire from 'proxyquire'
|
||||
|
||||
let mapStateToProps, mergeProps
|
||||
|
||||
proxyquire('../currency-display.container.js', {
|
||||
'react-redux': {
|
||||
connect: (ms, _, mp) => {
|
||||
mapStateToProps = ms
|
||||
mergeProps = mp
|
||||
return () => ({})
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
describe('CurrencyDisplay container', function () {
|
||||
describe('mapStateToProps()', function () {
|
||||
it('should return the correct props', function () {
|
||||
const mockState = {
|
||||
metamask: {
|
||||
conversionRate: 280.45,
|
||||
currentCurrency: 'usd',
|
||||
nativeCurrency: 'ETH',
|
||||
},
|
||||
}
|
||||
|
||||
assert.deepEqual(mapStateToProps(mockState), {
|
||||
conversionRate: 280.45,
|
||||
currentCurrency: 'usd',
|
||||
nativeCurrency: 'ETH',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('mergeProps()', function () {
|
||||
it('should return the correct props', function () {
|
||||
const mockStateProps = {
|
||||
conversionRate: 280.45,
|
||||
currentCurrency: 'usd',
|
||||
nativeCurrency: 'ETH',
|
||||
}
|
||||
|
||||
const tests = [
|
||||
{
|
||||
props: {
|
||||
value: '0x2386f26fc10000',
|
||||
numberOfDecimals: 2,
|
||||
currency: 'usd',
|
||||
nativeCurrency: 'ETH',
|
||||
},
|
||||
result: {
|
||||
displayValue: '$2.80',
|
||||
suffix: 'USD',
|
||||
nativeCurrency: 'ETH',
|
||||
},
|
||||
},
|
||||
{
|
||||
props: {
|
||||
value: '0x2386f26fc10000',
|
||||
currency: 'usd',
|
||||
nativeCurrency: 'ETH',
|
||||
},
|
||||
result: {
|
||||
displayValue: '$2.80',
|
||||
suffix: 'USD',
|
||||
nativeCurrency: 'ETH',
|
||||
},
|
||||
},
|
||||
{
|
||||
props: {
|
||||
value: '0x1193461d01595930',
|
||||
currency: 'ETH',
|
||||
nativeCurrency: 'ETH',
|
||||
numberOfDecimals: 3,
|
||||
},
|
||||
result: {
|
||||
displayValue: '1.266',
|
||||
suffix: 'ETH',
|
||||
nativeCurrency: 'ETH',
|
||||
},
|
||||
},
|
||||
{
|
||||
props: {
|
||||
value: '0x1193461d01595930',
|
||||
currency: 'ETH',
|
||||
nativeCurrency: 'ETH',
|
||||
numberOfDecimals: 3,
|
||||
hideLabel: true,
|
||||
},
|
||||
result: {
|
||||
nativeCurrency: 'ETH',
|
||||
displayValue: '1.266',
|
||||
suffix: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
props: {
|
||||
value: '0x3b9aca00',
|
||||
currency: 'ETH',
|
||||
nativeCurrency: 'ETH',
|
||||
denomination: 'GWEI',
|
||||
hideLabel: true,
|
||||
},
|
||||
result: {
|
||||
nativeCurrency: 'ETH',
|
||||
displayValue: '1',
|
||||
suffix: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
props: {
|
||||
value: '0x3b9aca00',
|
||||
currency: 'ETH',
|
||||
nativeCurrency: 'ETH',
|
||||
denomination: 'WEI',
|
||||
hideLabel: true,
|
||||
},
|
||||
result: {
|
||||
nativeCurrency: 'ETH',
|
||||
displayValue: '1000000000',
|
||||
suffix: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
props: {
|
||||
value: '0x3b9aca00',
|
||||
currency: 'ETH',
|
||||
nativeCurrency: 'ETH',
|
||||
numberOfDecimals: 100,
|
||||
hideLabel: true,
|
||||
},
|
||||
result: {
|
||||
nativeCurrency: 'ETH',
|
||||
displayValue: '0.000000001',
|
||||
suffix: undefined,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
tests.forEach(({ props, result }) => {
|
||||
assert.deepEqual(mergeProps(mockStateProps, {}, { ...props }), result)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@ -1,57 +1,24 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import CurrencyDisplay from '../currency-display'
|
||||
import { getTokenData } from '../../../helpers/utils/transactions.util'
|
||||
import { getTokenValue, calcTokenAmount } from '../../../helpers/utils/token-util'
|
||||
import { useTokenDisplayValue } from '../../../hooks/useTokenDisplayValue'
|
||||
|
||||
export default class TokenCurrencyDisplay extends PureComponent {
|
||||
static propTypes = {
|
||||
transactionData: PropTypes.string,
|
||||
token: PropTypes.object,
|
||||
}
|
||||
export default function TokenCurrencyDisplay ({ className, transactionData, token, prefix }) {
|
||||
const displayValue = useTokenDisplayValue(transactionData, token)
|
||||
|
||||
state = {
|
||||
displayValue: '',
|
||||
suffix: '',
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this.setDisplayValue()
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
const { transactionData } = this.props
|
||||
const { transactionData: prevTransactionData } = prevProps
|
||||
|
||||
if (transactionData !== prevTransactionData) {
|
||||
this.setDisplayValue()
|
||||
}
|
||||
}
|
||||
|
||||
setDisplayValue () {
|
||||
const { transactionData: data, token } = this.props
|
||||
const { decimals = '', symbol: suffix = '' } = token
|
||||
const tokenData = getTokenData(data)
|
||||
|
||||
let displayValue
|
||||
|
||||
if (tokenData && tokenData.params && tokenData.params.length) {
|
||||
const tokenValue = getTokenValue(tokenData.params)
|
||||
displayValue = calcTokenAmount(tokenValue, decimals).toString()
|
||||
}
|
||||
|
||||
this.setState({ displayValue, suffix })
|
||||
}
|
||||
|
||||
render () {
|
||||
const { displayValue, suffix } = this.state
|
||||
|
||||
return (
|
||||
<CurrencyDisplay
|
||||
{...this.props}
|
||||
displayValue={displayValue}
|
||||
suffix={suffix}
|
||||
/>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<CurrencyDisplay
|
||||
className={className}
|
||||
prefix={prefix}
|
||||
displayValue={displayValue}
|
||||
suffix={token.symbol}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
TokenCurrencyDisplay.propTypes = {
|
||||
className: PropTypes.string,
|
||||
transactionData: PropTypes.string,
|
||||
token: PropTypes.object,
|
||||
prefix: PropTypes.string,
|
||||
}
|
||||
|
121
ui/app/hooks/tests/useCurrencyDisplay.test.js
Normal file
121
ui/app/hooks/tests/useCurrencyDisplay.test.js
Normal file
@ -0,0 +1,121 @@
|
||||
import assert from 'assert'
|
||||
import { renderHook } from '@testing-library/react-hooks'
|
||||
import * as reactRedux from 'react-redux'
|
||||
import { useCurrencyDisplay } from '../useCurrencyDisplay'
|
||||
import sinon from 'sinon'
|
||||
|
||||
const tests = [
|
||||
{
|
||||
input: {
|
||||
value: '0x2386f26fc10000',
|
||||
numberOfDecimals: 2,
|
||||
currency: 'usd',
|
||||
},
|
||||
result: {
|
||||
value: '$2.80',
|
||||
suffix: 'USD',
|
||||
displayValue: '$2.80 USD',
|
||||
},
|
||||
},
|
||||
{
|
||||
input: {
|
||||
value: '0x2386f26fc10000',
|
||||
currency: 'usd',
|
||||
},
|
||||
result: {
|
||||
value: '$2.80',
|
||||
suffix: 'USD',
|
||||
displayValue: '$2.80 USD',
|
||||
},
|
||||
},
|
||||
{
|
||||
input: {
|
||||
value: '0x1193461d01595930',
|
||||
currency: 'ETH',
|
||||
numberOfDecimals: 3,
|
||||
},
|
||||
result: {
|
||||
value: '1.266',
|
||||
suffix: 'ETH',
|
||||
displayValue: '1.266 ETH',
|
||||
},
|
||||
},
|
||||
{
|
||||
input: {
|
||||
value: '0x1193461d01595930',
|
||||
currency: 'ETH',
|
||||
numberOfDecimals: 3,
|
||||
hideLabel: true,
|
||||
},
|
||||
result: {
|
||||
value: '1.266',
|
||||
suffix: undefined,
|
||||
displayValue: '1.266',
|
||||
},
|
||||
},
|
||||
{
|
||||
input: {
|
||||
value: '0x3b9aca00',
|
||||
currency: 'ETH',
|
||||
denomination: 'GWEI',
|
||||
hideLabel: true,
|
||||
},
|
||||
result: {
|
||||
value: '1',
|
||||
suffix: undefined,
|
||||
displayValue: '1',
|
||||
},
|
||||
},
|
||||
{
|
||||
input: {
|
||||
value: '0x3b9aca00',
|
||||
currency: 'ETH',
|
||||
denomination: 'WEI',
|
||||
hideLabel: true,
|
||||
},
|
||||
result: {
|
||||
value: '1000000000',
|
||||
suffix: undefined,
|
||||
displayValue: '1000000000',
|
||||
},
|
||||
},
|
||||
{
|
||||
input: {
|
||||
value: '0x3b9aca00',
|
||||
currency: 'ETH',
|
||||
numberOfDecimals: 100,
|
||||
hideLabel: true,
|
||||
},
|
||||
result: {
|
||||
value: '0.000000001',
|
||||
suffix: undefined,
|
||||
displayValue: '0.000000001',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
describe('useCurrencyDisplay', function () {
|
||||
tests.forEach(({ input: { value, ...restProps }, result }) => {
|
||||
describe(`when input is { value: ${value}, decimals: ${restProps.numberOfDecimals}, denomation: ${restProps.denomination} }`, function () {
|
||||
const stub = sinon.stub(reactRedux, 'useSelector')
|
||||
stub.callsFake(() => ({
|
||||
currentCurrency: 'usd',
|
||||
nativeCurrency: 'ETH',
|
||||
conversionRate: 280.45,
|
||||
}))
|
||||
const hookReturn = renderHook(() => useCurrencyDisplay(value, restProps))
|
||||
const [ displayValue, parts ] = hookReturn.result.current
|
||||
stub.restore()
|
||||
it(`should return ${result.displayValue} as displayValue`, function () {
|
||||
assert.equal(displayValue, result.displayValue)
|
||||
})
|
||||
it(`should return ${result.value} as value`, function () {
|
||||
assert.equal(parts.value, result.value)
|
||||
})
|
||||
it(`should return ${result.suffix} as suffix`, function () {
|
||||
assert.equal(parts.suffix, result.suffix)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
136
ui/app/hooks/tests/useTokenDisplayValue.test.js
Normal file
136
ui/app/hooks/tests/useTokenDisplayValue.test.js
Normal file
@ -0,0 +1,136 @@
|
||||
import assert from 'assert'
|
||||
import { renderHook } from '@testing-library/react-hooks'
|
||||
import * as tokenUtil from '../../helpers/utils/token-util'
|
||||
import * as txUtil from '../../helpers/utils/transactions.util'
|
||||
import { useTokenDisplayValue } from '../useTokenDisplayValue'
|
||||
import sinon from 'sinon'
|
||||
|
||||
const tests = [
|
||||
{
|
||||
token: {
|
||||
symbol: 'DAI',
|
||||
decimals: 18,
|
||||
},
|
||||
tokenData: {
|
||||
params: 'decoded-params1',
|
||||
},
|
||||
tokenValue: '1000000000000000000',
|
||||
displayValue: '1',
|
||||
},
|
||||
{
|
||||
token: {
|
||||
symbol: 'DAI',
|
||||
decimals: 18,
|
||||
},
|
||||
tokenData: {
|
||||
params: 'decoded-params2',
|
||||
},
|
||||
tokenValue: '10000000000000000000',
|
||||
displayValue: '10',
|
||||
},
|
||||
{
|
||||
token: {
|
||||
symbol: 'DAI',
|
||||
decimals: 18,
|
||||
},
|
||||
tokenData: {
|
||||
params: 'decoded-params3',
|
||||
},
|
||||
tokenValue: '1500000000000000000',
|
||||
displayValue: '1.5',
|
||||
},
|
||||
{
|
||||
token: {
|
||||
symbol: 'DAI',
|
||||
decimals: 18,
|
||||
},
|
||||
tokenData: {
|
||||
params: 'decoded-params4',
|
||||
},
|
||||
tokenValue: '1756000000000000000',
|
||||
displayValue: '1.756',
|
||||
},
|
||||
{
|
||||
token: {
|
||||
symbol: 'DAI',
|
||||
decimals: 18,
|
||||
},
|
||||
tokenData: {
|
||||
params: 'decoded-params5',
|
||||
},
|
||||
tokenValue: '25500000000000000000',
|
||||
displayValue: '25.5',
|
||||
},
|
||||
{
|
||||
token: {
|
||||
symbol: 'USDC',
|
||||
decimals: 6,
|
||||
},
|
||||
tokenData: {
|
||||
params: 'decoded-params6',
|
||||
},
|
||||
tokenValue: '1000000',
|
||||
displayValue: '1',
|
||||
},
|
||||
{
|
||||
token: {
|
||||
symbol: 'USDC',
|
||||
decimals: 6,
|
||||
},
|
||||
tokenData: {
|
||||
params: 'decoded-params7',
|
||||
},
|
||||
tokenValue: '10000000',
|
||||
displayValue: '10',
|
||||
},
|
||||
{
|
||||
token: {
|
||||
symbol: 'USDC',
|
||||
decimals: 6,
|
||||
},
|
||||
tokenData: {
|
||||
params: 'decoded-params8',
|
||||
},
|
||||
tokenValue: '1500000',
|
||||
displayValue: '1.5',
|
||||
},
|
||||
{
|
||||
token: {
|
||||
symbol: 'USDC',
|
||||
decimals: 6,
|
||||
},
|
||||
tokenData: {
|
||||
params: 'decoded-params9',
|
||||
},
|
||||
tokenValue: '1756000',
|
||||
displayValue: '1.756',
|
||||
},
|
||||
{
|
||||
token: {
|
||||
symbol: 'USDC',
|
||||
decimals: 6,
|
||||
},
|
||||
tokenData: {
|
||||
params: 'decoded-params10',
|
||||
},
|
||||
tokenValue: '25500000',
|
||||
displayValue: '25.5',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
describe('useTokenDisplayValue', function () {
|
||||
tests.forEach((test, idx) => {
|
||||
describe(`when input is decimals: ${test.token.decimals} and value: ${test.tokenValue}`, function () {
|
||||
it(`should return ${test.displayValue} as displayValue`, function () {
|
||||
const getTokenValueStub = sinon.stub(tokenUtil, 'getTokenValue')
|
||||
const getTokenDataStub = sinon.stub(txUtil, 'getTokenData')
|
||||
getTokenDataStub.callsFake(() => test.tokenData)
|
||||
getTokenValueStub.callsFake(() => test.tokenValue)
|
||||
const { result } = renderHook(() => useTokenDisplayValue(`${idx}-fakestring`, test.token))
|
||||
sinon.restore()
|
||||
assert.equal(result.current, test.displayValue)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
143
ui/app/hooks/tests/useUserPreferencedCurrency.test.js
Normal file
143
ui/app/hooks/tests/useUserPreferencedCurrency.test.js
Normal file
@ -0,0 +1,143 @@
|
||||
import assert from 'assert'
|
||||
import { renderHook } from '@testing-library/react-hooks'
|
||||
import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency'
|
||||
import * as reactRedux from 'react-redux'
|
||||
import { preferencesSelector, getShouldShowFiat } from '../../selectors'
|
||||
import sinon from 'sinon'
|
||||
|
||||
const tests = [
|
||||
{
|
||||
state: {
|
||||
useNativeCurrencyAsPrimaryCurrency: true,
|
||||
nativeCurrency: 'ETH',
|
||||
showFiat: true,
|
||||
},
|
||||
params: {
|
||||
type: 'PRIMARY',
|
||||
},
|
||||
result: {
|
||||
currency: 'ETH',
|
||||
numberOfDecimals: 6,
|
||||
},
|
||||
},
|
||||
{
|
||||
state: {
|
||||
useNativeCurrencyAsPrimaryCurrency: false,
|
||||
nativeCurrency: 'ETH',
|
||||
showFiat: true,
|
||||
},
|
||||
params: {
|
||||
type: 'PRIMARY',
|
||||
},
|
||||
result: {
|
||||
currency: undefined,
|
||||
numberOfDecimals: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
state: {
|
||||
useNativeCurrencyAsPrimaryCurrency: true,
|
||||
nativeCurrency: 'ETH',
|
||||
showFiat: true,
|
||||
},
|
||||
params: {
|
||||
type: 'SECONDARY',
|
||||
fiatNumberOfDecimals: 4,
|
||||
fiatPrefix: '-',
|
||||
},
|
||||
result: {
|
||||
currency: undefined,
|
||||
numberOfDecimals: 4,
|
||||
},
|
||||
},
|
||||
{
|
||||
state: {
|
||||
useNativeCurrencyAsPrimaryCurrency: false,
|
||||
nativeCurrency: 'ETH',
|
||||
showFiat: true,
|
||||
},
|
||||
params: {
|
||||
type: 'SECONDARY',
|
||||
fiatNumberOfDecimals: 4,
|
||||
numberOfDecimals: 3,
|
||||
fiatPrefix: 'a',
|
||||
},
|
||||
result: {
|
||||
currency: 'ETH',
|
||||
numberOfDecimals: 3,
|
||||
},
|
||||
},
|
||||
{
|
||||
state: {
|
||||
useNativeCurrencyAsPrimaryCurrency: false,
|
||||
nativeCurrency: 'ETH',
|
||||
showFiat: false,
|
||||
},
|
||||
params: {
|
||||
type: 'PRIMARY',
|
||||
},
|
||||
result: {
|
||||
currency: 'ETH',
|
||||
numberOfDecimals: 6,
|
||||
},
|
||||
},
|
||||
{
|
||||
state: {
|
||||
useNativeCurrencyAsPrimaryCurrency: false,
|
||||
nativeCurrency: 'ETH',
|
||||
showFiat: true,
|
||||
},
|
||||
params: {
|
||||
type: 'PRIMARY',
|
||||
},
|
||||
result: {
|
||||
currency: undefined,
|
||||
numberOfDecimals: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
state: {
|
||||
useNativeCurrencyAsPrimaryCurrency: false,
|
||||
nativeCurrency: 'ETH',
|
||||
showFiat: true,
|
||||
},
|
||||
params: {
|
||||
type: 'PRIMARY',
|
||||
},
|
||||
result: {
|
||||
currency: undefined,
|
||||
numberOfDecimals: 2,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
function getFakeUseSelector (state) {
|
||||
return (selector) => {
|
||||
if (selector === preferencesSelector) {
|
||||
return state
|
||||
} else if (selector === getShouldShowFiat) {
|
||||
return state.showFiat
|
||||
} else {
|
||||
return state.nativeCurrency
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
describe('useUserPreferencedCurrency', function () {
|
||||
tests.forEach(({ params: { type, ...otherParams }, state, result }) => {
|
||||
describe(`when showFiat is ${state.showFiat}, useNativeCurrencyAsPrimary is ${state.useNativeCurrencyAsPrimaryCurrency} and type is ${type}`, function () {
|
||||
const stub = sinon.stub(reactRedux, 'useSelector')
|
||||
stub.callsFake(getFakeUseSelector(state))
|
||||
|
||||
const { result: hookResult } = renderHook(() => useUserPreferencedCurrency(type, otherParams))
|
||||
stub.restore()
|
||||
it(`should return currency as ${result.currency || 'not modified by user preferences'}`, function () {
|
||||
assert.equal(hookResult.current.currency, result.currency)
|
||||
})
|
||||
it(`should return decimals as ${result.numberOfDecimals || 'not modified by user preferences'}`, function () {
|
||||
assert.equal(hookResult.current.numberOfDecimals, result.numberOfDecimals)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
69
ui/app/hooks/useCurrencyDisplay.js
Normal file
69
ui/app/hooks/useCurrencyDisplay.js
Normal file
@ -0,0 +1,69 @@
|
||||
import { useMemo } from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { formatCurrency, getValueFromWeiHex } from '../helpers/utils/confirm-tx.util'
|
||||
|
||||
/**
|
||||
* Defines the shape of the options parameter for useCurrencyDisplay
|
||||
* @typedef {Object} UseCurrencyOptions
|
||||
* @property {string} [displayValue] - When present is used in lieu of formatting the inputValue
|
||||
* @property {string} [prefix] - String to prepend to the final result
|
||||
* @property {number} [numberOfDecimals] - Number of significant decimals to display
|
||||
* @property {string} [denomination] - Denomination (wei, gwei) to convert to for display
|
||||
* @property {string} [currency] - Currency type to convert to. Will override nativeCurrency
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines the return shape of the second value in the tuple
|
||||
* @typedef {Object} CurrencyDisplayParts
|
||||
* @property {string} [prefix] - string to prepend to the value for display
|
||||
* @property {string} value - string representing the value, formatted for display
|
||||
* @property {string} [suffix] - string to append to the value for display
|
||||
*/
|
||||
|
||||
/**
|
||||
* useCurrencyDisplay hook
|
||||
*
|
||||
* Given a hexadecimal encoded value string and an object of parameters used for formatting the
|
||||
* display, produce both a fully formed string and the pieces of that string used for displaying
|
||||
* the currency to the user
|
||||
* @param {string} inputValue - The value to format for display
|
||||
* @param {UseCurrencyOptions} opts - An object for options to format the inputValue
|
||||
* @return {[string, CurrencyDisplayParts]}
|
||||
*/
|
||||
export function useCurrencyDisplay (inputValue, { displayValue, prefix, numberOfDecimals, denomination, currency, ...opts }) {
|
||||
const { currentCurrency, nativeCurrency, conversionRate } = useSelector(
|
||||
({ metamask: { currentCurrency, nativeCurrency, conversionRate } }) => ({
|
||||
currentCurrency,
|
||||
nativeCurrency,
|
||||
conversionRate,
|
||||
})
|
||||
)
|
||||
|
||||
const toCurrency = currency || currentCurrency
|
||||
|
||||
const value = useMemo(() => {
|
||||
if (displayValue) {
|
||||
return displayValue
|
||||
}
|
||||
return formatCurrency(
|
||||
getValueFromWeiHex({
|
||||
value: inputValue,
|
||||
fromCurrency: nativeCurrency,
|
||||
toCurrency,
|
||||
conversionRate,
|
||||
numberOfDecimals: numberOfDecimals || 2,
|
||||
toDenomination: denomination,
|
||||
}),
|
||||
toCurrency
|
||||
)
|
||||
}, [inputValue, nativeCurrency, conversionRate, displayValue, numberOfDecimals, denomination, toCurrency])
|
||||
|
||||
let suffix
|
||||
|
||||
if (!opts.hideLabel) {
|
||||
suffix = opts.suffix || toCurrency.toUpperCase()
|
||||
}
|
||||
|
||||
|
||||
return [`${prefix || ''}${value}${suffix ? ' ' + suffix : ''}`, { prefix, value, suffix }]
|
||||
}
|
38
ui/app/hooks/useTokenDisplayValue.js
Normal file
38
ui/app/hooks/useTokenDisplayValue.js
Normal file
@ -0,0 +1,38 @@
|
||||
import { getTokenValue, calcTokenAmount } from '../helpers/utils/token-util'
|
||||
import { getTokenData } from '../helpers/utils/transactions.util'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
/**
|
||||
* Defines the shape for the Token input parameter for useTokenDisplayValue
|
||||
* @typedef {Object} Token
|
||||
* @property {string} symbol - The string to use as a suffix for the token (eg. DAI)
|
||||
* @property {number} decimals - The number of decimals to show when displaying this type of token
|
||||
*/
|
||||
|
||||
/**
|
||||
* useTokenDisplayValue
|
||||
* Given the data string from txParams and a token object with symbol and decimals, return
|
||||
* a displayValue that represents a string representing that token amount as a string. Also
|
||||
* return a tokenData object for downstream usage and the suffix for the token to use as props
|
||||
* for other hooks and/or components
|
||||
* @param {string} transactionData
|
||||
* @param {Token} token
|
||||
* @return {string} - The computed displayValue of the provided transactionData and token
|
||||
*/
|
||||
export function useTokenDisplayValue (transactionData, token) {
|
||||
if (!transactionData || !token) {
|
||||
return null
|
||||
}
|
||||
const tokenData = useMemo(() => getTokenData(transactionData), [transactionData])
|
||||
if (!tokenData?.params?.length) {
|
||||
return null
|
||||
}
|
||||
const { decimals } = token
|
||||
|
||||
const displayValue = useMemo(() => {
|
||||
const tokenValue = getTokenValue(tokenData.params)
|
||||
return calcTokenAmount(tokenValue, decimals).toString()
|
||||
}, [tokenData, decimals])
|
||||
|
||||
return displayValue
|
||||
}
|
52
ui/app/hooks/useUserPreferencedCurrency.js
Normal file
52
ui/app/hooks/useUserPreferencedCurrency.js
Normal file
@ -0,0 +1,52 @@
|
||||
import { preferencesSelector, getShouldShowFiat } from '../selectors'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { PRIMARY, SECONDARY, ETH } from '../helpers/constants/common'
|
||||
|
||||
/**
|
||||
* Defines the shape of the options parameter for useUserPreferencedCurrency
|
||||
* @typedef {Object} UseUserPreferencedCurrencyOptions
|
||||
* @property {number} [numberOfDecimals] - Number of significant decimals to display
|
||||
* @property {number} [ethNumberOfDecimals] - Number of significant decimals to display
|
||||
* when using ETH
|
||||
* @property {number} [fiatNumberOfDecimals] - Number of significant decimals to display
|
||||
* when using fiat
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines the return shape of useUserPreferencedCurrency
|
||||
* @typedef {Object} UserPreferredCurrency
|
||||
* @property {string} currency - the currency type to use (eg: 'ETH', 'usd')
|
||||
* @property {number} numberOfDecimals - Number of significant decimals to display
|
||||
*/
|
||||
|
||||
/**
|
||||
* useUserPreferencedCurrency
|
||||
*
|
||||
* returns an object that contains what currency to use for displaying values based
|
||||
* on the user's preference settings, as well as the significant number of decimals
|
||||
* to display based on the currency
|
||||
* @param {"PRIMARY" | "SECONDARY"} type - what display type is being rendered
|
||||
* @param {UseUserPreferencedCurrencyOptions} opts - options to override default values
|
||||
* @return {UserPreferredCurrency}
|
||||
*/
|
||||
export function useUserPreferencedCurrency (type, opts = {}) {
|
||||
const nativeCurrency = useSelector((state) => state.metamask.nativeCurrency)
|
||||
const {
|
||||
useNativeCurrencyAsPrimaryCurrency,
|
||||
} = useSelector(preferencesSelector)
|
||||
const showFiat = useSelector(getShouldShowFiat)
|
||||
|
||||
let currency, numberOfDecimals
|
||||
if (!showFiat || (type === PRIMARY && useNativeCurrencyAsPrimaryCurrency) ||
|
||||
(type === SECONDARY && !useNativeCurrencyAsPrimaryCurrency)) {
|
||||
// Display ETH
|
||||
currency = nativeCurrency || ETH
|
||||
numberOfDecimals = opts.numberOfDecimals || opts.ethNumberOfDecimals || 6
|
||||
} else if ((type === SECONDARY && useNativeCurrencyAsPrimaryCurrency) ||
|
||||
(type === PRIMARY && !useNativeCurrencyAsPrimaryCurrency)) {
|
||||
// Display Fiat
|
||||
numberOfDecimals = opts.numberOfDecimals || opts.fiatNumberOfDecimals || 2
|
||||
}
|
||||
|
||||
return { currency, numberOfDecimals }
|
||||
}
|
@ -104,7 +104,6 @@ export default class ChooseAccount extends Component {
|
||||
value={balance}
|
||||
style={{ color: '#6A737D' }}
|
||||
suffix={nativeCurrency}
|
||||
hideLabel
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -285,6 +285,12 @@ export function preferencesSelector ({ metamask }) {
|
||||
return metamask.preferences
|
||||
}
|
||||
|
||||
export function getShouldShowFiat (state) {
|
||||
const isMainNet = getIsMainnet(state)
|
||||
const { showFiatInTestnets } = preferencesSelector(state)
|
||||
return isMainNet || showFiatInTestnets
|
||||
}
|
||||
|
||||
export function getAdvancedInlineGasShown (state) {
|
||||
return Boolean(state.metamask.featureFlags.advancedInlineGas)
|
||||
}
|
||||
|
35
yarn.lock
35
yarn.lock
@ -1088,6 +1088,13 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.2"
|
||||
|
||||
"@babel/runtime@^7.5.4":
|
||||
version "7.9.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f"
|
||||
integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.5.5":
|
||||
version "7.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
|
||||
@ -2653,6 +2660,14 @@
|
||||
dependencies:
|
||||
defer-to-connect "^1.0.1"
|
||||
|
||||
"@testing-library/react-hooks@^3.2.1":
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-3.2.1.tgz#19b6caa048ef15faa69d439c469033873ea01294"
|
||||
integrity sha512-1OB6Ksvlk6BCJA1xpj8/WWz0XVd1qRcgqdaFAq+xeC6l61Ucj0P6QpA5u+Db/x9gU4DCX8ziR5b66Mlfg0M2RA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.4"
|
||||
"@types/testing-library__react-hooks" "^3.0.0"
|
||||
|
||||
"@types/babel__core@^7.1.0":
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.3.tgz#e441ea7df63cd080dfcd02ab199e6d16a735fc30"
|
||||
@ -2839,6 +2854,13 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-test-renderer@*":
|
||||
version "16.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-16.9.2.tgz#e1c408831e8183e5ad748fdece02214a7c2ab6c5"
|
||||
integrity sha512-4eJr1JFLIAlWhzDkBCkhrOIWOvOxcCAfQh+jiKg7l/nNZcCIL2MHl2dZhogIFKyHzedVWHaVP1Yydq/Ruu4agw==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-textarea-autosize@^4.3.3":
|
||||
version "4.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-textarea-autosize/-/react-textarea-autosize-4.3.5.tgz#6c4d2753fa1864c98c0b2b517f67bb1f6e4c46de"
|
||||
@ -2872,6 +2894,14 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
|
||||
integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
|
||||
|
||||
"@types/testing-library__react-hooks@^3.0.0":
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/testing-library__react-hooks/-/testing-library__react-hooks-3.2.0.tgz#52f3a109bef06080e3b1e3ae7ea1c014ce859897"
|
||||
integrity sha512-dE8iMTuR5lzB+MqnxlzORlXzXyCL0EKfzH0w/lau20OpkHD37EaWjZDz0iNG8b71iEtxT4XKGmSKAGVEqk46mw==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
"@types/react-test-renderer" "*"
|
||||
|
||||
"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
|
||||
@ -23991,6 +24021,11 @@ regenerator-runtime@^0.13.2:
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447"
|
||||
integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==
|
||||
|
||||
regenerator-runtime@^0.13.4:
|
||||
version "0.13.5"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697"
|
||||
integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==
|
||||
|
||||
regenerator-transform@^0.10.0:
|
||||
version "0.10.1"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
|
||||
|
Loading…
x
Reference in New Issue
Block a user